Loading drivers/leds/led-class.c +118 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "leds.h" static struct class *leds_class; static DEFINE_MUTEX(leds_lookup_lock); static LIST_HEAD(leds_lookup_list); static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) Loading Loading @@ -215,6 +217,23 @@ static int led_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); static struct led_classdev *led_module_get(struct device *led_dev) { struct led_classdev *led_cdev; if (!led_dev) return ERR_PTR(-EPROBE_DEFER); led_cdev = dev_get_drvdata(led_dev); if (!try_module_get(led_cdev->dev->parent->driver->owner)) { put_device(led_cdev->dev); return ERR_PTR(-ENODEV); } return led_cdev; } /** * of_led_get() - request a LED device via the LED framework * @np: device node to get the LED device from Loading @@ -226,7 +245,6 @@ static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); struct led_classdev *of_led_get(struct device_node *np, int index) { struct device *led_dev; struct led_classdev *led_cdev; struct device_node *led_node; led_node = of_parse_phandle(np, "leds", index); Loading @@ -236,15 +254,7 @@ 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); if (!led_dev) return ERR_PTR(-EPROBE_DEFER); led_cdev = dev_get_drvdata(led_dev); if (!try_module_get(led_cdev->dev->parent->driver->owner)) return ERR_PTR(-ENODEV); return led_cdev; return led_module_get(led_dev); } EXPORT_SYMBOL_GPL(of_led_get); Loading @@ -255,6 +265,7 @@ EXPORT_SYMBOL_GPL(of_led_get); void led_put(struct led_classdev *led_cdev) { module_put(led_cdev->dev->parent->driver->owner); put_device(led_cdev->dev); } EXPORT_SYMBOL_GPL(led_put); Loading @@ -265,6 +276,22 @@ static void devm_led_release(struct device *dev, void *res) led_put(*p); } static struct led_classdev *__devm_led_get(struct device *dev, struct led_classdev *led) { struct led_classdev **dr; dr = devres_alloc(devm_led_release, sizeof(struct led_classdev *), GFP_KERNEL); if (!dr) { led_put(led); return ERR_PTR(-ENOMEM); } *dr = led; devres_add(dev, dr); return led; } /** * devm_of_led_get - Resource-managed request of a LED device * @dev: LED consumer Loading @@ -280,7 +307,6 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, int index) { struct led_classdev *led; struct led_classdev **dr; if (!dev) return ERR_PTR(-EINVAL); Loading @@ -289,19 +315,91 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, if (IS_ERR(led)) return led; dr = devres_alloc(devm_led_release, sizeof(struct led_classdev *), GFP_KERNEL); if (!dr) { led_put(led); return ERR_PTR(-ENOMEM); return __devm_led_get(dev, led); } EXPORT_SYMBOL_GPL(devm_of_led_get); *dr = led; devres_add(dev, dr); /** * led_get() - request a LED device via the LED framework * @dev: device for which to get the LED device * @con_id: name of the LED from the device's point of view * * @return a pointer to a LED device or ERR_PTR(errno) on failure. */ struct led_classdev *led_get(struct device *dev, char *con_id) { struct led_lookup_data *lookup; const char *provider = NULL; struct device *led_dev; mutex_lock(&leds_lookup_lock); list_for_each_entry(lookup, &leds_lookup_list, list) { if (!strcmp(lookup->dev_id, dev_name(dev)) && !strcmp(lookup->con_id, con_id)) { provider = kstrdup_const(lookup->provider, GFP_KERNEL); break; } } mutex_unlock(&leds_lookup_lock); if (!provider) return ERR_PTR(-ENOENT); led_dev = class_find_device_by_name(leds_class, provider); kfree_const(provider); return led_module_get(led_dev); } EXPORT_SYMBOL_GPL(led_get); /** * devm_led_get() - request a LED device via the LED framework * @dev: device for which to get the LED device * @con_id: name of the LED from the device's point of view * * The LED device returned from this function is automatically released * on driver detach. * * @return a pointer to a LED device or ERR_PTR(errno) on failure. */ struct led_classdev *devm_led_get(struct device *dev, char *con_id) { struct led_classdev *led; led = led_get(dev, con_id); if (IS_ERR(led)) return led; return __devm_led_get(dev, led); } EXPORT_SYMBOL_GPL(devm_of_led_get); EXPORT_SYMBOL_GPL(devm_led_get); /** * led_add_lookup() - Add a LED lookup table entry * @led_lookup: the lookup table entry to add * * Add a LED lookup table entry. On systems without devicetree the lookup table * is used by led_get() to find LEDs. */ void led_add_lookup(struct led_lookup_data *led_lookup) { mutex_lock(&leds_lookup_lock); list_add_tail(&led_lookup->list, &leds_lookup_list); mutex_unlock(&leds_lookup_lock); } EXPORT_SYMBOL_GPL(led_add_lookup); /** * led_remove_lookup() - Remove a LED lookup table entry * @led_lookup: the lookup table entry to remove */ void led_remove_lookup(struct led_lookup_data *led_lookup) { mutex_lock(&leds_lookup_lock); list_del(&led_lookup->list); mutex_unlock(&leds_lookup_lock); } EXPORT_SYMBOL_GPL(led_remove_lookup); static int led_classdev_next_name(const char *init_name, char *name, size_t len) Loading include/linux/leds.h +21 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,21 @@ enum led_default_state { LEDS_DEFSTATE_KEEP = 2, }; /** * struct led_lookup_data - represents a single LED lookup entry * * @list: internal list of all LED lookup entries * @provider: name of led_classdev providing the LED * @dev_id: name of the device associated with this LED * @con_id: name of the LED from the device's point of view */ struct led_lookup_data { struct list_head list; const char *provider; const char *dev_id; const char *con_id; }; struct led_init_data { /* device fwnode handle */ struct fwnode_handle *fwnode; Loading Loading @@ -211,6 +226,12 @@ void devm_led_classdev_unregister(struct device *parent, void led_classdev_suspend(struct led_classdev *led_cdev); void led_classdev_resume(struct led_classdev *led_cdev); void led_add_lookup(struct led_lookup_data *led_lookup); void led_remove_lookup(struct led_lookup_data *led_lookup); struct led_classdev *__must_check led_get(struct device *dev, char *con_id); struct led_classdev *__must_check devm_led_get(struct device *dev, char *con_id); extern struct led_classdev *of_led_get(struct device_node *np, int index); extern void led_put(struct led_classdev *led_cdev); struct led_classdev *__must_check devm_of_led_get(struct device *dev, Loading Loading
drivers/leds/led-class.c +118 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "leds.h" static struct class *leds_class; static DEFINE_MUTEX(leds_lookup_lock); static LIST_HEAD(leds_lookup_list); static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) Loading Loading @@ -215,6 +217,23 @@ static int led_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); static struct led_classdev *led_module_get(struct device *led_dev) { struct led_classdev *led_cdev; if (!led_dev) return ERR_PTR(-EPROBE_DEFER); led_cdev = dev_get_drvdata(led_dev); if (!try_module_get(led_cdev->dev->parent->driver->owner)) { put_device(led_cdev->dev); return ERR_PTR(-ENODEV); } return led_cdev; } /** * of_led_get() - request a LED device via the LED framework * @np: device node to get the LED device from Loading @@ -226,7 +245,6 @@ static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); struct led_classdev *of_led_get(struct device_node *np, int index) { struct device *led_dev; struct led_classdev *led_cdev; struct device_node *led_node; led_node = of_parse_phandle(np, "leds", index); Loading @@ -236,15 +254,7 @@ 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); if (!led_dev) return ERR_PTR(-EPROBE_DEFER); led_cdev = dev_get_drvdata(led_dev); if (!try_module_get(led_cdev->dev->parent->driver->owner)) return ERR_PTR(-ENODEV); return led_cdev; return led_module_get(led_dev); } EXPORT_SYMBOL_GPL(of_led_get); Loading @@ -255,6 +265,7 @@ EXPORT_SYMBOL_GPL(of_led_get); void led_put(struct led_classdev *led_cdev) { module_put(led_cdev->dev->parent->driver->owner); put_device(led_cdev->dev); } EXPORT_SYMBOL_GPL(led_put); Loading @@ -265,6 +276,22 @@ static void devm_led_release(struct device *dev, void *res) led_put(*p); } static struct led_classdev *__devm_led_get(struct device *dev, struct led_classdev *led) { struct led_classdev **dr; dr = devres_alloc(devm_led_release, sizeof(struct led_classdev *), GFP_KERNEL); if (!dr) { led_put(led); return ERR_PTR(-ENOMEM); } *dr = led; devres_add(dev, dr); return led; } /** * devm_of_led_get - Resource-managed request of a LED device * @dev: LED consumer Loading @@ -280,7 +307,6 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, int index) { struct led_classdev *led; struct led_classdev **dr; if (!dev) return ERR_PTR(-EINVAL); Loading @@ -289,19 +315,91 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, if (IS_ERR(led)) return led; dr = devres_alloc(devm_led_release, sizeof(struct led_classdev *), GFP_KERNEL); if (!dr) { led_put(led); return ERR_PTR(-ENOMEM); return __devm_led_get(dev, led); } EXPORT_SYMBOL_GPL(devm_of_led_get); *dr = led; devres_add(dev, dr); /** * led_get() - request a LED device via the LED framework * @dev: device for which to get the LED device * @con_id: name of the LED from the device's point of view * * @return a pointer to a LED device or ERR_PTR(errno) on failure. */ struct led_classdev *led_get(struct device *dev, char *con_id) { struct led_lookup_data *lookup; const char *provider = NULL; struct device *led_dev; mutex_lock(&leds_lookup_lock); list_for_each_entry(lookup, &leds_lookup_list, list) { if (!strcmp(lookup->dev_id, dev_name(dev)) && !strcmp(lookup->con_id, con_id)) { provider = kstrdup_const(lookup->provider, GFP_KERNEL); break; } } mutex_unlock(&leds_lookup_lock); if (!provider) return ERR_PTR(-ENOENT); led_dev = class_find_device_by_name(leds_class, provider); kfree_const(provider); return led_module_get(led_dev); } EXPORT_SYMBOL_GPL(led_get); /** * devm_led_get() - request a LED device via the LED framework * @dev: device for which to get the LED device * @con_id: name of the LED from the device's point of view * * The LED device returned from this function is automatically released * on driver detach. * * @return a pointer to a LED device or ERR_PTR(errno) on failure. */ struct led_classdev *devm_led_get(struct device *dev, char *con_id) { struct led_classdev *led; led = led_get(dev, con_id); if (IS_ERR(led)) return led; return __devm_led_get(dev, led); } EXPORT_SYMBOL_GPL(devm_of_led_get); EXPORT_SYMBOL_GPL(devm_led_get); /** * led_add_lookup() - Add a LED lookup table entry * @led_lookup: the lookup table entry to add * * Add a LED lookup table entry. On systems without devicetree the lookup table * is used by led_get() to find LEDs. */ void led_add_lookup(struct led_lookup_data *led_lookup) { mutex_lock(&leds_lookup_lock); list_add_tail(&led_lookup->list, &leds_lookup_list); mutex_unlock(&leds_lookup_lock); } EXPORT_SYMBOL_GPL(led_add_lookup); /** * led_remove_lookup() - Remove a LED lookup table entry * @led_lookup: the lookup table entry to remove */ void led_remove_lookup(struct led_lookup_data *led_lookup) { mutex_lock(&leds_lookup_lock); list_del(&led_lookup->list); mutex_unlock(&leds_lookup_lock); } EXPORT_SYMBOL_GPL(led_remove_lookup); static int led_classdev_next_name(const char *init_name, char *name, size_t len) Loading
include/linux/leds.h +21 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,21 @@ enum led_default_state { LEDS_DEFSTATE_KEEP = 2, }; /** * struct led_lookup_data - represents a single LED lookup entry * * @list: internal list of all LED lookup entries * @provider: name of led_classdev providing the LED * @dev_id: name of the device associated with this LED * @con_id: name of the LED from the device's point of view */ struct led_lookup_data { struct list_head list; const char *provider; const char *dev_id; const char *con_id; }; struct led_init_data { /* device fwnode handle */ struct fwnode_handle *fwnode; Loading Loading @@ -211,6 +226,12 @@ void devm_led_classdev_unregister(struct device *parent, void led_classdev_suspend(struct led_classdev *led_cdev); void led_classdev_resume(struct led_classdev *led_cdev); void led_add_lookup(struct led_lookup_data *led_lookup); void led_remove_lookup(struct led_lookup_data *led_lookup); struct led_classdev *__must_check led_get(struct device *dev, char *con_id); struct led_classdev *__must_check devm_led_get(struct device *dev, char *con_id); extern struct led_classdev *of_led_get(struct device_node *np, int index); extern void led_put(struct led_classdev *led_cdev); struct led_classdev *__must_check devm_of_led_get(struct device *dev, Loading