83 lines · 1.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Linux kernel module helpers. */ #include <linux/of.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/string.h> 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; 	/*	 * Prevent a kernel oops in vsnprintf() -- it only allows passing a	 * NULL ptr when the length is also 0. Also filter out the negative	 * lengths...	 */	if ((len > 0 && !str) || len < 0)		return -EINVAL; 	/* 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;	if (csize >= len)		csize = len > 0 ? len - 1 : 0;	len -= csize;	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);