1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Linux kernel module helpers. 4 */ 5 6 #include <linux/of.h> 7 #include <linux/module.h> 8 #include <linux/slab.h> 9 #include <linux/string.h> 10 11 ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) 12 { 13 const char *compat; 14 char *c; 15 struct property *p; 16 ssize_t csize; 17 ssize_t tsize; 18 19 /* Name & Type */ 20 /* %p eats all alphanum characters, so %c must be used here */ 21 csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', 22 of_node_get_device_type(np)); 23 tsize = csize; 24 len -= csize; 25 if (str) 26 str += csize; 27 28 of_property_for_each_string(np, "compatible", p, compat) { 29 csize = strlen(compat) + 1; 30 tsize += csize; 31 if (csize > len) 32 continue; 33 34 csize = snprintf(str, len, "C%s", compat); 35 for (c = str; c; ) { 36 c = strchr(c, ' '); 37 if (c) 38 *c++ = '_'; 39 } 40 len -= csize; 41 str += csize; 42 } 43 44 return tsize; 45 } 46 47 int of_request_module(const struct device_node *np) 48 { 49 char *str; 50 ssize_t size; 51 int ret; 52 53 if (!np) 54 return -ENODEV; 55 56 size = of_modalias(np, NULL, 0); 57 if (size < 0) 58 return size; 59 60 /* Reserve an additional byte for the trailing '\0' */ 61 size++; 62 63 str = kmalloc(size, GFP_KERNEL); 64 if (!str) 65 return -ENOMEM; 66 67 of_modalias(np, str, size); 68 str[size - 1] = '\0'; 69 ret = request_module(str); 70 kfree(str); 71 72 return ret; 73 } 74 EXPORT_SYMBOL_GPL(of_request_module); 75