From 51251542c9688c399e14d852258a675b331e761b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 10:47:38 +0200 Subject: leds: max77650: add MODULE_ALIAS() Define a MODULE_ALIAS() in the LED sub-driver for max77650 so that the appropriate module gets loaded together with the core mfd driver. Signed-off-by: Bartosz Golaszewski Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/leds/leds-max77650.c') diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 8a8e5c65b157..150421387534 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -143,3 +143,4 @@ module_platform_driver(max77650_led_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver"); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max77650-led"); -- cgit v1.2.3 From 730f693d79da8130c8ac18d1083cdb333fd8d7c8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 11 Jul 2019 13:24:05 +0530 Subject: leds: max77650: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence create a new label, err_node_put, which puts the previous node and returns variable rv. Modify the mid-loop return statements to instead store the return value in rv and jump to err_node_put. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Dan Murphy Acked-by: Bartosz Golaszewski Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/leds/leds-max77650.c') diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 150421387534..04738324b3e6 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -91,8 +91,10 @@ static int max77650_led_probe(struct platform_device *pdev) for_each_child_of_node(of_node, child) { rv = of_property_read_u32(child, "reg", ®); - if (rv || reg >= MAX77650_LED_NUM_LEDS) - return -EINVAL; + if (rv || reg >= MAX77650_LED_NUM_LEDS) { + rv = -EINVAL; + goto err_node_put; + } led = &leds[reg]; led->map = map; @@ -107,8 +109,10 @@ static int max77650_led_probe(struct platform_device *pdev) } else { led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, "max77650:%s", label); - if (!led->cdev.name) - return -ENOMEM; + if (!led->cdev.name) { + rv = -ENOMEM; + goto err_node_put; + } } of_property_read_string(child, "linux,default-trigger", @@ -116,20 +120,23 @@ static int max77650_led_probe(struct platform_device *pdev) rv = devm_of_led_classdev_register(dev, child, &led->cdev); if (rv) - return rv; + goto err_node_put; rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT); if (rv) - return rv; + goto err_node_put; rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT); if (rv) - return rv; + goto err_node_put; } return regmap_write(map, MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); +err_node_put: + of_node_put(child); + return rv; } static struct platform_driver max77650_led_driver = { -- cgit v1.2.3 From b2b998c0f944993c9ef435569651e407d607af41 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Sun, 9 Jun 2019 20:19:03 +0200 Subject: leds: class: Improve LED and LED flash class registration API Replace of_led_classdev_register() with led_classdev_register_ext(), which accepts easily extendable struct led_init_data, instead of the fixed struct device_node argument. The latter can be now passed in an fwnode property of the struct led_init_data. The modification is driven by the need for passing additional arguments required for the forthcoming generic mechanism for composing LED names. Currently the LED name is conveyed in the "name" char pointer property of the struct led_classdev. This is redundant since LED class device name is accessible throughout the whole LED class device life time via associated struct device's kobj->name property. The change will not break any existing clients since the patch alters also existing led_classdev{_flash}_register() macro wrappers, that pass NULL in place of init_data, which leads to using legacy name initialization path basing on the struct led_classdev's "name" property. Three existing users of devm_of_led_classdev_registers() are modified to use devm_led_classdev_register(), which will not impact their operation since they in fact didn't need to pass struct device_node on registration from the beginning. Signed-off-by: Jacek Anaszewski Cc: Baolin Wang Cc: Dan Murphy Cc: Daniel Mack Cc: Linus Walleij Cc: Oleh Kravchenko Cc: Sakari Ailus Cc: Simon Shields Acked-by: Pavel Machek --- drivers/leds/led-class-flash.c | 9 +++++---- drivers/leds/led-class.c | 29 +++++++++++++++++------------ drivers/leds/leds-cr0014114.c | 3 +-- drivers/leds/leds-gpio.c | 2 +- drivers/leds/leds-max77650.c | 2 +- drivers/leds/leds-pwm.c | 3 +-- include/linux/led-class-flash.h | 15 ++++++++++----- include/linux/leds.h | 34 ++++++++++++++++++++++++---------- 8 files changed, 60 insertions(+), 37 deletions(-) (limited to 'drivers/leds/leds-max77650.c') diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c index 94980c654d89..60c3de5c6b9f 100644 --- a/drivers/leds/led-class-flash.c +++ b/drivers/leds/led-class-flash.c @@ -282,8 +282,9 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev) led_cdev->groups = flash_groups; } -int led_classdev_flash_register(struct device *parent, - struct led_classdev_flash *fled_cdev) +int led_classdev_flash_register_ext(struct device *parent, + struct led_classdev_flash *fled_cdev, + struct led_init_data *init_data) { struct led_classdev *led_cdev; const struct led_flash_ops *ops; @@ -309,13 +310,13 @@ int led_classdev_flash_register(struct device *parent, } /* Register led class device */ - ret = led_classdev_register(parent, led_cdev); + ret = led_classdev_register_ext(parent, led_cdev, init_data); if (ret < 0) return ret; return 0; } -EXPORT_SYMBOL_GPL(led_classdev_flash_register); +EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext); void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev) { diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4793e77808e2..242122f49333 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -242,14 +243,16 @@ 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]; int ret; @@ -266,7 +269,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np, 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->of_node = to_of_node(init_data->fwnode); if (ret) dev_warn(parent, "Led %s renamed to %s due to name collision", @@ -311,7 +315,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. @@ -356,14 +360,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 +377,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 +388,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) { diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index 0e4262462cb9..1c82152764d2 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) led->ldev.max_brightness = CR_MAX_BRIGHTNESS; led->ldev.brightness_set_blocking = cr0014114_set_sync; - ret = devm_of_led_classdev_register(priv->dev, np, - &led->ldev); + ret = devm_led_classdev_register(priv->dev, &led->ldev); if (ret) { dev_err(priv->dev, "failed to register LED device %s, err %d", diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index bdc98ddca1dc..8f463c912db8 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -108,7 +108,7 @@ static int create_gpio_led(const struct gpio_led *template, if (ret < 0) return ret; - return devm_of_led_classdev_register(parent, np, &led_dat->cdev); + return devm_led_classdev_register(parent, &led_dat->cdev); } struct gpio_leds_priv { diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 04738324b3e6..5a14f9775b0e 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -118,7 +118,7 @@ static int max77650_led_probe(struct platform_device *pdev) of_property_read_string(child, "linux,default-trigger", &led->cdev.default_trigger); - rv = devm_of_led_classdev_register(dev, child, &led->cdev); + rv = devm_led_classdev_register(dev, &led->cdev); if (rv) goto err_node_put; diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 48d068f80f11..d0e1f2710351 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -111,8 +111,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, if (!led_data->period && (led->pwm_period_ns > 0)) led_data->period = led->pwm_period_ns; - ret = devm_of_led_classdev_register(dev, to_of_node(fwnode), - &led_data->cdev); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret == 0) { priv->num_leds++; led_pwm_set(&led_data->cdev, led_data->cdev.brightness); diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h index f52713f0a269..1e824963af17 100644 --- a/include/linux/led-class-flash.h +++ b/include/linux/led-class-flash.h @@ -86,15 +86,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev( } /** - * led_classdev_flash_register - register a new object of led_classdev class - * with support for flash LEDs - * @parent: the flash LED to register + * led_classdev_flash_register_ext - register a new object of LED class with + * init data and with support for flash LEDs + * @parent: LED flash controller device this flash LED is driven by * @fled_cdev: the led_classdev_flash structure for this device + * @init_data: the LED class flash device initialization data * * Returns: 0 on success or negative error value on failure */ -extern int led_classdev_flash_register(struct device *parent, - struct led_classdev_flash *fled_cdev); +extern int led_classdev_flash_register_ext(struct device *parent, + struct led_classdev_flash *fled_cdev, + struct led_init_data *init_data); + +#define led_classdev_flash_register(parent, fled_cdev) \ + led_classdev_flash_register_ext(parent, fled_cdev, NULL) /** * led_classdev_flash_unregister - unregisters an object of led_classdev class diff --git a/include/linux/leds.h b/include/linux/leds.h index 9b2bf574a17a..2bbe8a38fe39 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -30,6 +30,11 @@ enum led_brightness { LED_FULL = 255, }; +struct led_init_data { + /* device fwnode handle */ + struct fwnode_handle *fwnode; +}; + struct led_classdev { const char *name; enum led_brightness brightness; @@ -125,16 +130,25 @@ struct led_classdev { struct mutex led_access; }; -extern int of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev); -#define led_classdev_register(parent, led_cdev) \ - of_led_classdev_register(parent, NULL, led_cdev) -extern int devm_of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev); -#define devm_led_classdev_register(parent, led_cdev) \ - devm_of_led_classdev_register(parent, NULL, led_cdev) +/** + * led_classdev_register_ext - register a new object of LED class with + * init data + * @parent: LED controller device this LED is driven by + * @led_cdev: the led_classdev structure for this device + * @init_data: the LED class device initialization data + * + * Returns: 0 on success or negative error value on failure + */ +extern int led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); +#define led_classdev_register(parent, led_cdev) \ + led_classdev_register_ext(parent, led_cdev, NULL) +extern int devm_led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); +#define devm_led_classdev_register(parent, led_cdev) \ + devm_led_classdev_register_ext(parent, led_cdev, NULL) extern void led_classdev_unregister(struct led_classdev *led_cdev); extern void devm_led_classdev_unregister(struct device *parent, struct led_classdev *led_cdev); -- cgit v1.2.3 From ae6c4c70dfd184f69a24342c09678fb161a7cb4c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Aug 2019 18:19:27 +0300 Subject: leds: max77650: Switch to fwnode property API Switch the max77650 from OF to the fwnode property API. Signed-off-by: Andy Shevchenko Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max77650.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/leds/leds-max77650.c') diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 5a14f9775b0e..4c2d0b3c6dad 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -62,7 +62,7 @@ static int max77650_led_brightness_set(struct led_classdev *cdev, static int max77650_led_probe(struct platform_device *pdev) { - struct device_node *of_node, *child; + struct fwnode_handle *child; struct max77650_led *leds, *led; struct device *dev; struct regmap *map; @@ -71,10 +71,6 @@ static int max77650_led_probe(struct platform_device *pdev) u32 reg; dev = &pdev->dev; - of_node = dev->of_node; - - if (!of_node) - return -ENODEV; leds = devm_kcalloc(dev, sizeof(*leds), MAX77650_LED_NUM_LEDS, GFP_KERNEL); @@ -85,12 +81,12 @@ static int max77650_led_probe(struct platform_device *pdev) if (!map) return -ENODEV; - num_leds = of_get_child_count(of_node); + num_leds = device_get_child_node_count(dev); if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS) return -ENODEV; - for_each_child_of_node(of_node, child) { - rv = of_property_read_u32(child, "reg", ®); + device_for_each_child_node(dev, child) { + rv = fwnode_property_read_u32(child, "reg", ®); if (rv || reg >= MAX77650_LED_NUM_LEDS) { rv = -EINVAL; goto err_node_put; @@ -103,8 +99,8 @@ static int max77650_led_probe(struct platform_device *pdev) led->cdev.brightness_set_blocking = max77650_led_brightness_set; led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS; - label = of_get_property(child, "label", NULL); - if (!label) { + rv = fwnode_property_read_string(child, "label", &label); + if (rv) { led->cdev.name = "max77650::"; } else { led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, @@ -115,8 +111,8 @@ static int max77650_led_probe(struct platform_device *pdev) } } - of_property_read_string(child, "linux,default-trigger", - &led->cdev.default_trigger); + fwnode_property_read_string(child, "linux,default-trigger", + &led->cdev.default_trigger); rv = devm_led_classdev_register(dev, &led->cdev); if (rv) @@ -135,7 +131,7 @@ static int max77650_led_probe(struct platform_device *pdev) MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); err_node_put: - of_node_put(child); + fwnode_handle_put(child); return rv; } -- cgit v1.2.3