diff options
Diffstat (limited to 'drivers/leds/led-class.c')
-rw-r--r-- | drivers/leds/led-class.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 24fcff682b24..c20ac8ccf52b 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -25,15 +25,20 @@ static DEFINE_MUTEX(leds_lookup_lock); static LIST_HEAD(leds_lookup_list); +static struct workqueue_struct *leds_wq; + static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); + unsigned int brightness; - /* no lock needed for this */ + mutex_lock(&led_cdev->led_access); led_update_brightness(led_cdev); + brightness = led_cdev->brightness; + mutex_unlock(&led_cdev->led_access); - return sprintf(buf, "%u\n", led_cdev->brightness); + return sprintf(buf, "%u\n", brightness); } static ssize_t brightness_store(struct device *dev, @@ -57,7 +62,6 @@ static ssize_t brightness_store(struct device *dev, if (state == LED_OFF) led_trigger_remove(led_cdev); led_set_brightness(led_cdev, state); - flush_work(&led_cdev->set_brightness_work); ret = size; unlock: @@ -70,19 +74,24 @@ static ssize_t max_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); + unsigned int max_brightness; + + mutex_lock(&led_cdev->led_access); + max_brightness = led_cdev->max_brightness; + mutex_unlock(&led_cdev->led_access); - return sprintf(buf, "%u\n", led_cdev->max_brightness); + return sprintf(buf, "%u\n", max_brightness); } static DEVICE_ATTR_RO(max_brightness); #ifdef CONFIG_LEDS_TRIGGERS -static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0); -static struct bin_attribute *led_trigger_bin_attrs[] = { +static const BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0); +static const struct bin_attribute *const led_trigger_bin_attrs[] = { &bin_attr_trigger, NULL, }; static const struct attribute_group led_trigger_group = { - .bin_attrs = led_trigger_bin_attrs, + .bin_attrs_new = led_trigger_bin_attrs, }; #endif @@ -258,7 +267,6 @@ struct led_classdev *of_led_get(struct device_node *np, int index) led_dev = class_find_device_by_of_node(&leds_class, led_node); of_node_put(led_node); - put_device(led_dev); return led_module_get(led_dev); } @@ -503,6 +511,11 @@ int led_classdev_register_ext(struct device *parent, ret = led_classdev_next_name(proposed_name, final_name, sizeof(final_name)); if (ret < 0) return ret; + else if (ret && led_cdev->flags & LED_REJECT_NAME_CONFLICT) + return -EEXIST; + else if (ret) + dev_warn(parent, "Led %s renamed to %s due to name collision\n", + proposed_name, final_name); if (led_cdev->color >= LED_COLOR_ID_MAX) dev_warn(parent, "LED %s color identifier out of range\n", final_name); @@ -518,10 +531,6 @@ int led_classdev_register_ext(struct device *parent, if (init_data && init_data->fwnode) device_set_node(led_cdev->dev, init_data->fwnode); - if (ret) - dev_warn(parent, "Led %s renamed to %s due to name collision", - proposed_name, dev_name(led_cdev->dev)); - if (led_cdev->flags & LED_BRIGHT_HW_CHANGED) { ret = led_add_brightness_hw_changed(led_cdev); if (ret) { @@ -549,15 +558,11 @@ int led_classdev_register_ext(struct device *parent, led_update_brightness(led_cdev); + led_cdev->wq = leds_wq; + led_init_core(led_cdev); #ifdef CONFIG_LEDS_TRIGGERS - /* - * If no default trigger was given and hw_control_trigger is set, - * make it the default trigger. - */ - if (!led_cdev->default_trigger && led_cdev->hw_control_trigger) - led_cdev->default_trigger = led_cdev->hw_control_trigger; led_trigger_set_default(led_cdev); #endif @@ -673,12 +678,19 @@ EXPORT_SYMBOL_GPL(devm_led_classdev_unregister); static int __init leds_init(void) { + leds_wq = alloc_ordered_workqueue("leds", 0); + if (!leds_wq) { + pr_err("Failed to create LEDs ordered workqueue\n"); + return -ENOMEM; + } + return class_register(&leds_class); } static void __exit leds_exit(void) { class_unregister(&leds_class); + destroy_workqueue(leds_wq); } subsys_initcall(leds_init); |