diff options
Diffstat (limited to 'drivers/leds/led-class.c')
| -rw-r--r-- | drivers/leds/led-class.c | 62 | 
1 files changed, 39 insertions, 23 deletions
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4793e77808e2..647b1263c579 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -14,6 +14,7 @@  #include <linux/leds.h>  #include <linux/list.h>  #include <linux/module.h> +#include <linux/property.h>  #include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/timer.h> @@ -213,13 +214,6 @@ static int led_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); -static int match_name(struct device *dev, const void *data) -{ -	if (!dev_name(dev)) -		return 0; -	return !strcmp(dev_name(dev), (char *)data); -} -  static int led_classdev_next_name(const char *init_name, char *name,  				  size_t len)  { @@ -230,7 +224,7 @@ static int led_classdev_next_name(const char *init_name, char *name,  	strlcpy(name, init_name, len);  	while ((ret < len) && -	       (dev = class_find_device(leds_class, NULL, name, match_name))) { +	       (dev = class_find_device_by_name(leds_class, name))) {  		put_device(dev);  		ret = snprintf(name, len, "%s_%u", init_name, ++i);  	} @@ -242,31 +236,48 @@ static int led_classdev_next_name(const char *init_name, char *name,  }  /** - * of_led_classdev_register - register a new object of led_classdev class. + * led_classdev_register_ext - register a new object of led_classdev class + *			       with init data.   *   * @parent: parent of LED device   * @led_cdev: the led_classdev structure for this device. - * @np: DT node describing this LED + * @init_data: LED class device initialization data   */ -int of_led_classdev_register(struct device *parent, struct device_node *np, -			    struct led_classdev *led_cdev) +int led_classdev_register_ext(struct device *parent, +			      struct led_classdev *led_cdev, +			      struct led_init_data *init_data)  { -	char name[LED_MAX_NAME_SIZE]; +	char composed_name[LED_MAX_NAME_SIZE]; +	char final_name[LED_MAX_NAME_SIZE]; +	const char *proposed_name = composed_name;  	int ret; -	ret = led_classdev_next_name(led_cdev->name, name, sizeof(name)); +	if (init_data) { +		if (init_data->devname_mandatory && !init_data->devicename) { +			dev_err(parent, "Mandatory device name is missing"); +			return -EINVAL; +		} +		ret = led_compose_name(parent, init_data, composed_name); +		if (ret < 0) +			return ret; +	} else { +		proposed_name = led_cdev->name; +	} + +	ret = led_classdev_next_name(proposed_name, final_name, sizeof(final_name));  	if (ret < 0)  		return ret;  	mutex_init(&led_cdev->led_access);  	mutex_lock(&led_cdev->led_access);  	led_cdev->dev = device_create_with_groups(leds_class, parent, 0, -				led_cdev, led_cdev->groups, "%s", name); +				led_cdev, led_cdev->groups, "%s", final_name);  	if (IS_ERR(led_cdev->dev)) {  		mutex_unlock(&led_cdev->led_access);  		return PTR_ERR(led_cdev->dev);  	} -	led_cdev->dev->of_node = np; +	if (init_data && init_data->fwnode) +		led_cdev->dev->fwnode = init_data->fwnode;  	if (ret)  		dev_warn(parent, "Led %s renamed to %s due to name collision", @@ -276,6 +287,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,  		ret = led_add_brightness_hw_changed(led_cdev);  		if (ret) {  			device_unregister(led_cdev->dev); +			led_cdev->dev = NULL;  			mutex_unlock(&led_cdev->led_access);  			return ret;  		} @@ -311,7 +323,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,  	return 0;  } -EXPORT_SYMBOL_GPL(of_led_classdev_register); +EXPORT_SYMBOL_GPL(led_classdev_register_ext);  /**   * led_classdev_unregister - unregisters a object of led_properties class. @@ -321,6 +333,9 @@ EXPORT_SYMBOL_GPL(of_led_classdev_register);   */  void led_classdev_unregister(struct led_classdev *led_cdev)  { +	if (IS_ERR_OR_NULL(led_cdev->dev)) +		return; +  #ifdef CONFIG_LEDS_TRIGGERS  	down_write(&led_cdev->trigger_lock);  	if (led_cdev->trigger) @@ -356,14 +371,15 @@ static void devm_led_classdev_release(struct device *dev, void *res)  }  /** - * devm_of_led_classdev_register - resource managed led_classdev_register() + * devm_led_classdev_register_ext - resource managed led_classdev_register_ext()   *   * @parent: parent of LED device   * @led_cdev: the led_classdev structure for this device. + * @init_data: LED class device initialization data   */ -int devm_of_led_classdev_register(struct device *parent, -				  struct device_node *np, -				  struct led_classdev *led_cdev) +int devm_led_classdev_register_ext(struct device *parent, +				   struct led_classdev *led_cdev, +				   struct led_init_data *init_data)  {  	struct led_classdev **dr;  	int rc; @@ -372,7 +388,7 @@ int devm_of_led_classdev_register(struct device *parent,  	if (!dr)  		return -ENOMEM; -	rc = of_led_classdev_register(parent, np, led_cdev); +	rc = led_classdev_register_ext(parent, led_cdev, init_data);  	if (rc) {  		devres_free(dr);  		return rc; @@ -383,7 +399,7 @@ int devm_of_led_classdev_register(struct device *parent,  	return 0;  } -EXPORT_SYMBOL_GPL(devm_of_led_classdev_register); +EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext);  static int devm_led_classdev_match(struct device *dev, void *res, void *data)  {  |