// SPDX-License-Identifier: GPL-2.0 /* * Linux kernel module helpers. */ #include #include #include #include ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) { const char *compat; char *c; struct property *p; ssize_t csize; ssize_t tsize; /* Name & Type */ /* %p eats all alphanum characters, so %c must be used here */ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', of_node_get_device_type(np)); tsize = csize; len -= csize; if (str) str += csize; of_property_for_each_string(np, "compatible", p, compat) { csize = strlen(compat) + 1; tsize += csize; if (csize > len) continue; csize = snprintf(str, len, "C%s", compat); for (c = str; c; ) { c = strchr(c, ' '); if (c) *c++ = '_'; } len -= csize; str += csize; } return tsize; } int of_request_module(const struct device_node *np) { char *str; ssize_t size; int ret; if (!np) return -ENODEV; size = of_modalias(np, NULL, 0); if (size < 0) return size; /* Reserve an additional byte for the trailing '\0' */ size++; str = kmalloc(size, GFP_KERNEL); if (!str) return -ENOMEM; of_modalias(np, str, size); str[size - 1] = '\0'; ret = request_module(str); kfree(str); return ret; } EXPORT_SYMBOL_GPL(of_request_module);