mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Depending on device.c for pure OF handling is considered backwards. Let's extract the content of of_device_request_module() to have the real logic under module.c. The next step will be to convert users of of_device_request_module() to use the new helper. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Link: https://lore.kernel.org/r/20230404172148.82422-11-srinivas.kandagatla@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
		
			
				
	
	
		
			74 lines
		
	
	
	
		
			1.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
	
		
			1.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// 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;
 | 
						|
 | 
						|
	/* 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);
 |