From da0806e4e886a58ad258720042cb5b1fe32de728 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Fri, 20 Sep 2024 10:45:14 +0800 Subject: [PATCH 01/46] leds: rgb: leds-group-multicolor: Correct the typo 'acccess' There is a spelling mistake of 'acccess' which should be instead of 'access'. Signed-off-by: WangYuli Acked-by: Thomas Zimmermann Link: https://lore.kernel.org/r/B586A1E6EA476B68+20240920024514.1182292-1-wangyuli@uniontech.com Signed-off-by: Lee Jones --- drivers/leds/rgb/leds-group-multicolor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c index b6c7679015fd..548c7dd63ba1 100644 --- a/drivers/leds/rgb/leds-group-multicolor.c +++ b/drivers/leds/rgb/leds-group-multicolor.c @@ -55,7 +55,7 @@ static void restore_sysfs_write_access(void *data) { struct led_classdev *led_cdev = data; - /* Restore the write acccess to the LED */ + /* Restore the write access to the LED */ mutex_lock(&led_cdev->led_access); led_sysfs_enable(led_cdev); mutex_unlock(&led_cdev->led_access); From 73b03b27736e440e3009fe1319cbc82d2cd1290c Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:52 +0200 Subject: [PATCH 02/46] leds: flash: mt6360: Fix device_for_each_child_node() refcounting in error paths The device_for_each_child_node() macro requires explicit calls to fwnode_handle_put() upon early exits to avoid memory leaks, and in this case the error paths are handled after jumping to 'out_flash_realease', which misses that required call to to decrement the refcount of the child node. A more elegant and robust solution is using the scoped variant of the loop, which automatically handles such early exits. Fix the child node refcounting in the error paths by using device_for_each_child_node_scoped(). Cc: stable@vger.kernel.org Fixes: 679f8652064b ("leds: Add mt6360 driver") Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-1-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/flash/leds-mt6360.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c index 4c74f1cf01f0..676236c19ec4 100644 --- a/drivers/leds/flash/leds-mt6360.c +++ b/drivers/leds/flash/leds-mt6360.c @@ -784,7 +784,6 @@ static void mt6360_v4l2_flash_release(struct mt6360_priv *priv) static int mt6360_led_probe(struct platform_device *pdev) { struct mt6360_priv *priv; - struct fwnode_handle *child; size_t count; int i = 0, ret; @@ -811,7 +810,7 @@ static int mt6360_led_probe(struct platform_device *pdev) return -ENODEV; } - device_for_each_child_node(&pdev->dev, child) { + device_for_each_child_node_scoped(&pdev->dev, child) { struct mt6360_led *led = priv->leds + i; struct led_init_data init_data = { .fwnode = child, }; u32 reg, led_color; From 19d1cc765e7d477070ddda02c9a07a1ebcdf4b2d Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:53 +0200 Subject: [PATCH 03/46] leds: flash: mt6370: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-2-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/flash/leds-mt6370-flash.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/leds/flash/leds-mt6370-flash.c b/drivers/leds/flash/leds-mt6370-flash.c index 912d9d622320..dbdbe92309db 100644 --- a/drivers/leds/flash/leds-mt6370-flash.c +++ b/drivers/leds/flash/leds-mt6370-flash.c @@ -509,7 +509,6 @@ static int mt6370_led_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mt6370_priv *priv; - struct fwnode_handle *child; size_t count; int i = 0, ret; @@ -529,22 +528,18 @@ static int mt6370_led_probe(struct platform_device *pdev) if (!priv->regmap) return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct mt6370_led *led = priv->leds + i; led->priv = priv; ret = mt6370_init_flash_properties(dev, led, child); - if (ret) { - fwnode_handle_put(child); + if (ret) return ret; - } ret = mt6370_led_register(dev, led, child); - if (ret) { - fwnode_handle_put(child); + if (ret) return ret; - } i++; } From f64dd42a4f939fb5acc3f3568ef2118487617996 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:54 +0200 Subject: [PATCH 04/46] leds: flash: leds-qcom-flash: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-3-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/flash/leds-qcom-flash.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c index 41ce034f700e..ab848c5acd2d 100644 --- a/drivers/leds/flash/leds-qcom-flash.c +++ b/drivers/leds/flash/leds-qcom-flash.c @@ -812,7 +812,6 @@ static int qcom_flash_led_probe(struct platform_device *pdev) { struct qcom_flash_data *flash_data; struct qcom_flash_led *led; - struct fwnode_handle *child; struct device *dev = &pdev->dev; struct regmap *regmap; struct reg_field *regs; @@ -896,7 +895,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev) if (!flash_data->v4l2_flash) return -ENOMEM; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); if (!led) { rc = -ENOMEM; @@ -914,7 +913,6 @@ static int qcom_flash_led_probe(struct platform_device *pdev) return 0; release: - fwnode_handle_put(child); while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count) v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]); return rc; From a361af3c1622d4b8ede54493fa88633fb12201d0 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:55 +0200 Subject: [PATCH 05/46] leds: aw200xx: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-4-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-aw200xx.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/leds/leds-aw200xx.c b/drivers/leds/leds-aw200xx.c index f9d9844e0273..08cca128458c 100644 --- a/drivers/leds/leds-aw200xx.c +++ b/drivers/leds/leds-aw200xx.c @@ -409,7 +409,6 @@ static int aw200xx_probe_get_display_rows(struct device *dev, static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip) { - struct fwnode_handle *child; u32 current_min, current_max, min_uA; int ret; int i; @@ -424,7 +423,7 @@ static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip) min_uA = UINT_MAX; i = 0; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct led_init_data init_data = {}; struct aw200xx_led *led; u32 source, imax; @@ -468,10 +467,8 @@ static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip) ret = devm_led_classdev_register_ext(dev, &led->cdev, &init_data); - if (ret) { - fwnode_handle_put(child); + if (ret) break; - } i++; } From 65135e2ccf5ad0853c1df0ffeefc372066a62909 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:56 +0200 Subject: [PATCH 06/46] leds: cr0014114: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-5-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-cr0014114.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index c9914fc51f20..7e51c374edd4 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -181,11 +181,10 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) { size_t i = 0; struct cr0014114_led *led; - struct fwnode_handle *child; struct led_init_data init_data = {}; int ret; - device_for_each_child_node(priv->dev, child) { + device_for_each_child_node_scoped(priv->dev, child) { led = &priv->leds[i]; led->priv = priv; @@ -201,7 +200,6 @@ static int cr0014114_probe_dt(struct cr0014114 *priv) if (ret) { dev_err(priv->dev, "failed to register LED device, err %d", ret); - fwnode_handle_put(child); return ret; } From 9e445e28ae0c6fe24369127cf2302cd4f3a1b42b Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:57 +0200 Subject: [PATCH 07/46] leds: el15203000: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'err_child_out', as an immediate return is possible. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-6-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-el15203000.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c index d40194a3029f..e26d1654bd0d 100644 --- a/drivers/leds/leds-el15203000.c +++ b/drivers/leds/leds-el15203000.c @@ -237,22 +237,20 @@ static int el15203000_pattern_clear(struct led_classdev *ldev) static int el15203000_probe_dt(struct el15203000 *priv) { struct el15203000_led *led = priv->leds; - struct fwnode_handle *child; int ret; - device_for_each_child_node(priv->dev, child) { + device_for_each_child_node_scoped(priv->dev, child) { struct led_init_data init_data = {}; ret = fwnode_property_read_u32(child, "reg", &led->reg); if (ret) { dev_err(priv->dev, "LED without ID number"); - goto err_child_out; + return ret; } if (led->reg > U8_MAX) { dev_err(priv->dev, "LED value %d is invalid", led->reg); - ret = -EINVAL; - goto err_child_out; + return -EINVAL; } led->priv = priv; @@ -274,17 +272,13 @@ static int el15203000_probe_dt(struct el15203000 *priv) dev_err(priv->dev, "failed to register LED device %s, err %d", led->ldev.name, ret); - goto err_child_out; + return ret; } led++; } return 0; - -err_child_out: - fwnode_handle_put(child); - return ret; } static int el15203000_probe(struct spi_device *spi) From 42b49671602f9badb14fd2c32e6791a24d8cbf02 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:58 +0200 Subject: [PATCH 08/46] leds: gpio: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-7-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-gpio.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 4d1612d557c8..7d4488191241 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -148,7 +148,6 @@ struct gpio_leds_priv { static struct gpio_leds_priv *gpio_leds_create(struct device *dev) { - struct fwnode_handle *child; struct gpio_leds_priv *priv; int count, used, ret; @@ -162,7 +161,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev) priv->num_leds = count; used = 0; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct gpio_led_data *led_dat = &priv->leds[used]; struct gpio_led led = {}; @@ -176,7 +175,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev) if (IS_ERR(led.gpiod)) { dev_err_probe(dev, PTR_ERR(led.gpiod), "Failed to get GPIO '%pfw'\n", child); - fwnode_handle_put(child); return ERR_CAST(led.gpiod); } @@ -192,10 +190,9 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev) led.panic_indicator = 1; ret = create_gpio_led(&led, led_dat, dev, child, NULL); - if (ret < 0) { - fwnode_handle_put(child); + if (ret < 0) return ERR_PTR(ret); - } + /* Set gpiod label to match the corresponding LED name. */ gpiod_set_consumer_name(led_dat->gpiod, led_dat->cdev.dev->kobj.name); From 7bd4b9277b9831d115f14d26000c0ba32c83d109 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:20:59 +0200 Subject: [PATCH 09/46] leds: lm3532: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'child_out', as an immediate return is possible. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-8-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-lm3532.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 54b5650877f7..24dc8ad27bb3 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -551,7 +551,6 @@ static void gpio_set_low_action(void *data) static int lm3532_parse_node(struct lm3532_data *priv) { - struct fwnode_handle *child = NULL; struct lm3532_led *led; int control_bank; u32 ramp_time; @@ -587,7 +586,7 @@ static int lm3532_parse_node(struct lm3532_data *priv) else priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time); - device_for_each_child_node(priv->dev, child) { + device_for_each_child_node_scoped(priv->dev, child) { struct led_init_data idata = { .fwnode = child, .default_label = ":", @@ -599,7 +598,7 @@ static int lm3532_parse_node(struct lm3532_data *priv) ret = fwnode_property_read_u32(child, "reg", &control_bank); if (ret) { dev_err(&priv->client->dev, "reg property missing\n"); - goto child_out; + return ret; } if (control_bank > LM3532_CONTROL_C) { @@ -613,7 +612,7 @@ static int lm3532_parse_node(struct lm3532_data *priv) &led->mode); if (ret) { dev_err(&priv->client->dev, "ti,led-mode property missing\n"); - goto child_out; + return ret; } if (fwnode_property_present(child, "led-max-microamp") && @@ -647,7 +646,7 @@ static int lm3532_parse_node(struct lm3532_data *priv) led->num_leds); if (ret) { dev_err(&priv->client->dev, "led-sources property missing\n"); - goto child_out; + return ret; } led->priv = priv; @@ -657,23 +656,20 @@ static int lm3532_parse_node(struct lm3532_data *priv) if (ret) { dev_err(&priv->client->dev, "led register err: %d\n", ret); - goto child_out; + return ret; } ret = lm3532_init_registers(led); if (ret) { dev_err(&priv->client->dev, "register init err: %d\n", ret); - goto child_out; + return ret; } i++; } - return 0; -child_out: - fwnode_handle_put(child); - return ret; + return 0; } static int lm3532_probe(struct i2c_client *client) From 6e2d1d83b70bd736228529fd1cb4f98e0ab77eb8 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:00 +0200 Subject: [PATCH 10/46] leds: lm3697: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'child_out', as an immediate return is possible. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-9-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-lm3697.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 99de2a331727..7ad232780a31 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -202,7 +202,6 @@ out: static int lm3697_probe_dt(struct lm3697 *priv) { - struct fwnode_handle *child = NULL; struct device *dev = priv->dev; struct lm3697_led *led; int ret = -EINVAL; @@ -220,19 +219,18 @@ static int lm3697_probe_dt(struct lm3697 *priv) if (IS_ERR(priv->regulator)) priv->regulator = NULL; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct led_init_data init_data = {}; ret = fwnode_property_read_u32(child, "reg", &control_bank); if (ret) { dev_err(dev, "reg property missing\n"); - goto child_out; + return ret; } if (control_bank > LM3697_CONTROL_B) { dev_err(dev, "reg property is invalid\n"); - ret = -EINVAL; - goto child_out; + return -EINVAL; } led = &priv->leds[i]; @@ -262,7 +260,7 @@ static int lm3697_probe_dt(struct lm3697 *priv) led->num_leds); if (ret) { dev_err(dev, "led-sources property missing\n"); - goto child_out; + return ret; } for (j = 0; j < led->num_leds; j++) @@ -286,17 +284,13 @@ static int lm3697_probe_dt(struct lm3697 *priv) &init_data); if (ret) { dev_err(dev, "led register err: %d\n", ret); - goto child_out; + return ret; } i++; } - return ret; - -child_out: - fwnode_handle_put(child); - return ret; + return 0; } static int lm3697_probe(struct i2c_client *client) From ba35b9a4c1b074218880c47ca09d19a3c69f904d Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:01 +0200 Subject: [PATCH 11/46] leds: lp50xx: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'child_out', as an immediate return is possible. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-10-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-lp50xx.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c index 175d4b06659b..32ca45aec76c 100644 --- a/drivers/leds/leds-lp50xx.c +++ b/drivers/leds/leds-lp50xx.c @@ -434,7 +434,6 @@ static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv, static int lp50xx_probe_dt(struct lp50xx *priv) { - struct fwnode_handle *child = NULL; struct fwnode_handle *led_node = NULL; struct led_init_data init_data = {}; struct led_classdev *led_cdev; @@ -454,17 +453,17 @@ static int lp50xx_probe_dt(struct lp50xx *priv) if (IS_ERR(priv->regulator)) priv->regulator = NULL; - device_for_each_child_node(priv->dev, child) { + device_for_each_child_node_scoped(priv->dev, child) { led = &priv->leds[i]; ret = fwnode_property_count_u32(child, "reg"); if (ret < 0) { dev_err(priv->dev, "reg property is invalid\n"); - goto child_out; + return ret; } ret = lp50xx_probe_leds(child, priv, led, ret); if (ret) - goto child_out; + return ret; init_data.fwnode = child; num_colors = 0; @@ -475,10 +474,8 @@ static int lp50xx_probe_dt(struct lp50xx *priv) */ mc_led_info = devm_kcalloc(priv->dev, LP50XX_LEDS_PER_MODULE, sizeof(*mc_led_info), GFP_KERNEL); - if (!mc_led_info) { - ret = -ENOMEM; - goto child_out; - } + if (!mc_led_info) + return -ENOMEM; fwnode_for_each_child_node(child, led_node) { ret = fwnode_property_read_u32(led_node, "color", @@ -486,7 +483,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv) if (ret) { fwnode_handle_put(led_node); dev_err(priv->dev, "Cannot read color\n"); - goto child_out; + return ret; } mc_led_info[num_colors].color_index = color_id; @@ -504,16 +501,12 @@ static int lp50xx_probe_dt(struct lp50xx *priv) &init_data); if (ret) { dev_err(priv->dev, "led register err: %d\n", ret); - goto child_out; + return ret; } i++; } return 0; - -child_out: - fwnode_handle_put(child); - return ret; } static int lp50xx_probe(struct i2c_client *client) From 4ab3ae432da1706b5e1624ecea3c670faaec39d7 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:02 +0200 Subject: [PATCH 12/46] leds: max77650: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'err_node_out', as an immediate return is possible. Signed-off-by: Javier Carrasco Acked-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-11-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-max77650.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c index 1eeac56b0014..f8c47078a3bb 100644 --- a/drivers/leds/leds-max77650.c +++ b/drivers/leds/leds-max77650.c @@ -62,7 +62,6 @@ static int max77650_led_brightness_set(struct led_classdev *cdev, static int max77650_led_probe(struct platform_device *pdev) { - struct fwnode_handle *child; struct max77650_led *leds, *led; struct device *dev; struct regmap *map; @@ -84,14 +83,12 @@ static int max77650_led_probe(struct platform_device *pdev) if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS) return -ENODEV; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct led_init_data init_data = {}; rv = fwnode_property_read_u32(child, "reg", ®); - if (rv || reg >= MAX77650_LED_NUM_LEDS) { - rv = -EINVAL; - goto err_node_put; - } + if (rv || reg >= MAX77650_LED_NUM_LEDS) + return -EINVAL; led = &leds[reg]; led->map = map; @@ -108,23 +105,20 @@ static int max77650_led_probe(struct platform_device *pdev) rv = devm_led_classdev_register_ext(dev, &led->cdev, &init_data); if (rv) - goto err_node_put; + return rv; rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT); if (rv) - goto err_node_put; + return rv; rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT); if (rv) - goto err_node_put; + return rv; } return regmap_write(map, MAX77650_REG_CNFG_LED_TOP, MAX77650_LED_TOP_DEFAULT); -err_node_put: - fwnode_handle_put(child); - return rv; } static const struct of_device_id max77650_led_of_match[] = { From 5b5d936db0d2fb9e81d240ed91d062b8c8f0d224 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:03 +0200 Subject: [PATCH 13/46] leds: ns2: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error path. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-12-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-ns2.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index f3010c472bbd..4c6f04a5bd87 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -238,7 +238,6 @@ static int ns2_led_register(struct device *dev, struct fwnode_handle *node, static int ns2_led_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct fwnode_handle *child; struct ns2_led *leds; int count; int ret; @@ -251,12 +250,10 @@ static int ns2_led_probe(struct platform_device *pdev) if (!leds) return -ENOMEM; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { ret = ns2_led_register(dev, child, leds++); - if (ret) { - fwnode_handle_put(child); + if (ret) return ret; - } } return 0; From dea90acb09324efe640ab69766c12d8d387ee97f Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:04 +0200 Subject: [PATCH 14/46] leds: pca963x: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'err', as an immediate return is possible. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-13-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-pca963x.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c index b53905da3592..050e93b04884 100644 --- a/drivers/leds/leds-pca963x.c +++ b/drivers/leds/leds-pca963x.c @@ -306,7 +306,6 @@ static int pca963x_register_leds(struct i2c_client *client, struct pca963x_chipdef *chipdef = chip->chipdef; struct pca963x_led *led = chip->leds; struct device *dev = &client->dev; - struct fwnode_handle *child; bool hw_blink; s32 mode2; u32 reg; @@ -338,7 +337,7 @@ static int pca963x_register_leds(struct i2c_client *client, if (ret < 0) return ret; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct led_init_data init_data = {}; char default_label[32]; @@ -346,8 +345,7 @@ static int pca963x_register_leds(struct i2c_client *client, if (ret || reg >= chipdef->n_leds) { dev_err(dev, "Invalid 'reg' property for node %pfw\n", child); - ret = -EINVAL; - goto err; + return -EINVAL; } led->led_num = reg; @@ -369,16 +367,13 @@ static int pca963x_register_leds(struct i2c_client *client, if (ret) { dev_err(dev, "Failed to register LED for node %pfw\n", child); - goto err; + return ret; } ++led; } return 0; -err: - fwnode_handle_put(child); - return ret; } static int pca963x_suspend(struct device *dev) From e3456071853597229012622c97b76109c0fa8754 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:05 +0200 Subject: [PATCH 15/46] leds: pwm: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'err_child_out', as an immediate return is possible. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-14-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-pwm.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index e1b414b40353..7961dca0db2f 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -140,21 +140,18 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) { - struct fwnode_handle *fwnode; struct led_pwm led; int ret; - device_for_each_child_node(dev, fwnode) { + device_for_each_child_node_scoped(dev, fwnode) { memset(&led, 0, sizeof(led)); ret = fwnode_property_read_string(fwnode, "label", &led.name); if (ret && is_of_node(fwnode)) led.name = to_of_node(fwnode)->name; - if (!led.name) { - ret = -EINVAL; - goto err_child_out; - } + if (!led.name) + return -EINVAL; led.active_low = fwnode_property_read_bool(fwnode, "active-low"); @@ -165,14 +162,10 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) ret = led_pwm_add(dev, priv, &led, fwnode); if (ret) - goto err_child_out; + return ret; } return 0; - -err_child_out: - fwnode_handle_put(fwnode); - return ret; } static int led_pwm_probe(struct platform_device *pdev) From 8cf103de9a002fb02125491c06d9cd60762d70e5 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:06 +0200 Subject: [PATCH 16/46] leds: sun50i-a100: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). The error handling after 'err_put_child' has been moved to the only goto that jumps to it (second device_for_each_child_node()), and the call to fwnode_handle_put() has been removed accordingly. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-15-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-sun50i-a100.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/leds/leds-sun50i-a100.c b/drivers/leds/leds-sun50i-a100.c index 4c468d487486..03f1b6424692 100644 --- a/drivers/leds/leds-sun50i-a100.c +++ b/drivers/leds/leds-sun50i-a100.c @@ -392,7 +392,6 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev) struct sun50i_a100_ledc_led *led; struct device *dev = &pdev->dev; struct sun50i_a100_ledc *priv; - struct fwnode_handle *child; struct resource *mem; u32 max_addr = 0; u32 num_leds = 0; @@ -402,21 +401,17 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev) * The maximum LED address must be known in sun50i_a100_ledc_resume() before * class device registration, so parse and validate the subnodes up front. */ - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { u32 addr, color; ret = fwnode_property_read_u32(child, "reg", &addr); - if (ret || addr >= LEDC_MAX_LEDS) { - fwnode_handle_put(child); + if (ret || addr >= LEDC_MAX_LEDS) return dev_err_probe(dev, -EINVAL, "'reg' must be between 0 and %d\n", LEDC_MAX_LEDS - 1); - } ret = fwnode_property_read_u32(child, "color", &color); - if (ret || color != LED_COLOR_ID_RGB) { - fwnode_handle_put(child); + if (ret || color != LED_COLOR_ID_RGB) return dev_err_probe(dev, -EINVAL, "'color' must be LED_COLOR_ID_RGB\n"); - } max_addr = max(max_addr, addr); num_leds++; @@ -502,7 +497,7 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev) return ret; led = priv->leds; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct led_classdev *cdev; /* The node was already validated above. */ @@ -527,7 +522,11 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev) ret = led_classdev_multicolor_register_ext(dev, &led->mc_cdev, &init_data); if (ret) { dev_err_probe(dev, ret, "Failed to register multicolor LED %u", led->addr); - goto err_put_child; + while (led-- > priv->leds) + led_classdev_multicolor_unregister(&led->mc_cdev); + sun50i_a100_ledc_suspend(&pdev->dev); + + return ret; } led++; @@ -536,14 +535,6 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev) dev_info(dev, "Registered %u LEDs\n", num_leds); return 0; - -err_put_child: - fwnode_handle_put(child); - while (led-- > priv->leds) - led_classdev_multicolor_unregister(&led->mc_cdev); - sun50i_a100_ledc_suspend(&pdev->dev); - - return ret; } static void sun50i_a100_ledc_remove(struct platform_device *pdev) From 01728d041986a6992d0b2499e88db4569e65a535 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:07 +0200 Subject: [PATCH 17/46] leds: tca6507: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error path. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-16-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-tca6507.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index 4f22f4224946..acbd8169723c 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c @@ -658,7 +658,6 @@ static struct tca6507_platform_data * tca6507_led_dt_init(struct device *dev) { struct tca6507_platform_data *pdata; - struct fwnode_handle *child; struct led_info *tca_leds; int count; @@ -671,7 +670,7 @@ tca6507_led_dt_init(struct device *dev) if (!tca_leds) return ERR_PTR(-ENOMEM); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct led_info led; u32 reg; int ret; @@ -688,10 +687,8 @@ tca6507_led_dt_init(struct device *dev) led.flags |= TCA6507_MAKE_GPIO; ret = fwnode_property_read_u32(child, "reg", ®); - if (ret || reg >= NUM_LEDS) { - fwnode_handle_put(child); + if (ret || reg >= NUM_LEDS) return ERR_PTR(ret ? : -EINVAL); - } tca_leds[reg] = led; } From 48259638fe5986afe8ed2a49e35f0641d953c311 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:08 +0200 Subject: [PATCH 18/46] leds: rgb: ktd202x: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error path. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-17-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/rgb/leds-ktd202x.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/leds/rgb/leds-ktd202x.c b/drivers/leds/rgb/leds-ktd202x.c index d5c442163c46..04e62faa3a00 100644 --- a/drivers/leds/rgb/leds-ktd202x.c +++ b/drivers/leds/rgb/leds-ktd202x.c @@ -495,7 +495,6 @@ static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, u static int ktd202x_probe_fw(struct ktd202x *chip) { - struct fwnode_handle *child; struct device *dev = chip->dev; int count; int i = 0; @@ -509,13 +508,12 @@ static int ktd202x_probe_fw(struct ktd202x *chip) /* Allow the device to execute the complete reset */ usleep_range(200, 300); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { int ret = ktd202x_add_led(chip, child, i); - if (ret) { - fwnode_handle_put(child); + if (ret) return ret; - } + i++; } From bf3fba727695dcd1ac3f9d17d88845223f56c14f Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 01:21:09 +0200 Subject: [PATCH 19/46] leds: rgb: mt6370: Switch to device_for_each_child_node_scoped() Switch to device_for_each_child_node_scoped() to simplify the code by removing the need for calls to fwnode_handle_put() in the error paths. This also prevents possible memory leaks if new error paths are added without the required call to fwnode_handle_put(). After switching to the scoped variant, there is no longer need for a jump to 'fwnode_release', as an immediate return is possible. Given that the loop is called in the probe function, and it already uses dev_err_probe(), the common "dev_err() + return" has been updated as well. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-18-95c0614b38c8@gmail.com Signed-off-by: Lee Jones --- drivers/leds/rgb/leds-mt6370-rgb.c | 37 +++++++++--------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/leds/rgb/leds-mt6370-rgb.c b/drivers/leds/rgb/leds-mt6370-rgb.c index 359ef00498b4..fe76e8e27f9c 100644 --- a/drivers/leds/rgb/leds-mt6370-rgb.c +++ b/drivers/leds/rgb/leds-mt6370-rgb.c @@ -905,7 +905,6 @@ static int mt6370_leds_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mt6370_priv *priv; - struct fwnode_handle *child; size_t count; unsigned int i = 0; int ret; @@ -936,37 +935,27 @@ static int mt6370_leds_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "Failed to allocate regmap field\n"); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct mt6370_led *led = priv->leds + i++; struct led_init_data init_data = { .fwnode = child }; u32 reg, color; ret = fwnode_property_read_u32(child, "reg", ®); - if (ret) { - dev_err(dev, "Failed to parse reg property\n"); - goto fwnode_release; - } + if (ret) + dev_err_probe(dev, ret, "Failed to parse reg property\n"); - if (reg >= MT6370_MAX_LEDS) { - ret = -EINVAL; - dev_err(dev, "Error reg property number\n"); - goto fwnode_release; - } + if (reg >= MT6370_MAX_LEDS) + return dev_err_probe(dev, -EINVAL, "Error reg property number\n"); ret = fwnode_property_read_u32(child, "color", &color); - if (ret) { - dev_err(dev, "Failed to parse color property\n"); - goto fwnode_release; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to parse color property\n"); if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI) reg = MT6370_VIRTUAL_MULTICOLOR; - if (priv->leds_active & BIT(reg)) { - ret = -EINVAL; - dev_err(dev, "Duplicate reg property\n"); - goto fwnode_release; - } + if (priv->leds_active & BIT(reg)) + return dev_err_probe(dev, -EINVAL, "Duplicate reg property\n"); priv->leds_active |= BIT(reg); @@ -975,18 +964,14 @@ static int mt6370_leds_probe(struct platform_device *pdev) ret = mt6370_init_led_properties(dev, led, &init_data); if (ret) - goto fwnode_release; + return ret; ret = mt6370_led_register(dev, led, &init_data); if (ret) - goto fwnode_release; + return ret; } return 0; - -fwnode_release: - fwnode_handle_put(child); - return ret; } static const struct of_device_id mt6370_rgbled_device_table[] = { From 827a0a3724c5e516b7c0dbfd3f0d907dc947a10b Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 23:37:40 +0200 Subject: [PATCH 20/46] leds: flash: Remove unused local leds.h This driver does not require any element from the local leds.h. Drop unused header. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_unused_leds_h-v1-1-46fbf41ed4ae@gmail.com Signed-off-by: Lee Jones --- drivers/leds/led-class-flash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c index 6fe9d700dfef..f4e26ce84862 100644 --- a/drivers/leds/led-class-flash.c +++ b/drivers/leds/led-class-flash.c @@ -12,7 +12,6 @@ #include #include #include -#include "leds.h" #define has_flash_op(fled_cdev, op) \ (fled_cdev && fled_cdev->ops->op) From 026432e7c26484eb613d8224c98e554c7bc7d768 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 23:37:41 +0200 Subject: [PATCH 21/46] leds: multicolor: Remove unused local leds.h This driver does not require any element from the local leds.h. Drop unused header. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_unused_leds_h-v1-2-46fbf41ed4ae@gmail.com Signed-off-by: Lee Jones --- drivers/leds/led-class-multicolor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/leds/led-class-multicolor.c b/drivers/leds/led-class-multicolor.c index 30c1ecb5f361..b2a87c994816 100644 --- a/drivers/leds/led-class-multicolor.c +++ b/drivers/leds/led-class-multicolor.c @@ -11,8 +11,6 @@ #include #include -#include "leds.h" - int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev, enum led_brightness brightness) { From e7160d5ee369c016418ba239516d24f086130aa4 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 23:37:42 +0200 Subject: [PATCH 22/46] leds: gpio: Remove unused local leds.h Commit 156a5bb89ca6 ("leds: Move led_init_default_state_get() to the global header") moved the only element leds-gpio required from the local leds.h to its global counterpart. Drop the inclusion of the local leds.h as it is no longer used. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_unused_leds_h-v1-3-46fbf41ed4ae@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-gpio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 7d4488191241..0d59b0bbc002 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -21,8 +21,6 @@ #include #include -#include "leds.h" - struct gpio_led_data { struct led_classdev cdev; struct gpio_desc *gpiod; From d1aa93196ca601472f4300bed103ce74ff2e8a2b Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 23:37:43 +0200 Subject: [PATCH 23/46] leds: lp50xx: Remove unused local leds.h This driver does not require any element from the local leds.h. Drop unused header. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_unused_leds_h-v1-4-46fbf41ed4ae@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-lp50xx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c index 32ca45aec76c..02cb1565a9fb 100644 --- a/drivers/leds/leds-lp50xx.c +++ b/drivers/leds/leds-lp50xx.c @@ -16,8 +16,6 @@ #include -#include "leds.h" - #define LP50XX_DEV_CFG0 0x00 #define LP50XX_DEV_CFG1 0x01 #define LP50XX_LED_CFG0 0x02 From 9fd316962a2089f25db286c1042eeba3f08a2bed Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 23:37:44 +0200 Subject: [PATCH 24/46] leds: pwm: Remove unused local leds.h Commit 156a5bb89ca6 ("leds: Move led_init_default_state_get() to the global header") moved the only element leds-gpio required from the local leds.h to its global counterpart. Drop the inclusion of the local leds.h as it is no longer used. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_unused_leds_h-v1-5-46fbf41ed4ae@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-pwm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 7961dca0db2f..34a03ef82007 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -17,7 +17,6 @@ #include #include #include -#include "leds.h" struct led_pwm { const char *name; From 3cfd6ad3e1d9ea4ae2e13d384c3c95726593dae2 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Fri, 27 Sep 2024 23:37:45 +0200 Subject: [PATCH 25/46] leds: turris-omnia: Remove unused local leds.h This driver does not require any element from the local leds.h. Drop unused header. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240927-leds_unused_leds_h-v1-6-46fbf41ed4ae@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-turris-omnia.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c index 4cff8c4b020c..2de825ac08b3 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -10,7 +10,6 @@ #include #include #include -#include "leds.h" #define OMNIA_BOARD_LEDS 12 #define OMNIA_LED_NUM_CHANNELS 3 From 267f1ad6fa0c45ba39d60c33949605820f791ae7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 7 Oct 2024 22:53:15 +0200 Subject: [PATCH 26/46] dt-bindings: leds: Document "rc-feedback" trigger Document the "rc-feedback" trigger which is used to control LEDs by remote control device activity. This is an existing trigger used in existing DTs, document it so validation of those DTs would pass. It was originally introduced into the Linux kernel in 2013 with commit 153a60bb0fac ("[media] rc: add feedback led trigger for rc keypresses") Signed-off-by: Heiko Stuebner Acked-by: Pavel Machek Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20241007205315.2477060-1-heiko@sntech.de Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/leds/common.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml index bf9a101e4d42..9cd89f30fa7c 100644 --- a/Documentation/devicetree/bindings/leds/common.yaml +++ b/Documentation/devicetree/bindings/leds/common.yaml @@ -118,6 +118,8 @@ properties: # No trigger assigned to the LED. This is the default mode # if trigger is absent - none + # LED indicates remote control feedback + - rc-feedback # LED indicates camera torch state - torch # LED indicates USB gadget activity From 42507413bb32666dcbb19a876e4b73419b05a0d1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Sep 2024 13:20:53 +0200 Subject: [PATCH 27/46] leds: leds-gpio-register: Reorganize kerneldoc parameter names Reorganize kerneldoc parameter names to match the parameter order in the function header. Problems identified using Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20240930112121.95324-8-Julia.Lawall@inria.fr Signed-off-by: Lee Jones --- drivers/leds/leds-gpio-register.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-gpio-register.c b/drivers/leds/leds-gpio-register.c index de3f12c2b80d..ccc01fa72e6f 100644 --- a/drivers/leds/leds-gpio-register.c +++ b/drivers/leds/leds-gpio-register.c @@ -10,8 +10,8 @@ /** * gpio_led_register_device - register a gpio-led device - * @pdata: the platform data used for the new device * @id: platform ID + * @pdata: the platform data used for the new device * * Makes a copy of pdata and pdata->leds and registers a new leds-gpio device * with the result. This allows to have pdata and pdata-leds in .init.rodata From d19261ffd077609e5d348f1c12894997807a64a8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Oct 2024 16:10:50 +0200 Subject: [PATCH 28/46] dt-bindings: leds: bcm63138: Add shift register bits The BCM63138 family of serial LED controllers has a register where we can set up bits for the shift registers. These are the number of rounds the bits need to be shifted before all bits have been shifted through the external shift registers. Signed-off-by: Linus Walleij Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20241010-bcm63138-leds-v4-1-cdb80780a555@linaro.org Signed-off-by: Lee Jones --- .../devicetree/bindings/leds/leds-bcm63138.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml b/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml index bb20394fca5c..62326507c1aa 100644 --- a/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml +++ b/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml @@ -41,6 +41,16 @@ properties: "#size-cells": const: 0 + brcm,serial-shift-bits: + minimum: 1 + maximum: 32 + description: + This describes the number of 8-bit serial shifters connected to the LED + controller block. The hardware is typically using 8-bit shift registers + with 8 LEDs per shift register, so 4 shifters results in 32 LEDs or 2 + shifters give 16 LEDs etc, but the hardware supports any odd number of + registers. If left unspecified, the hardware boot-time default is used. + patternProperties: "^led@[a-f0-9]+$": type: object @@ -71,6 +81,7 @@ examples: leds@ff800800 { compatible = "brcm,bcm4908-leds", "brcm,bcm63138-leds"; reg = <0xff800800 0xdc>; + brcm,serial-shift-bits = <16>; #address-cells = <1>; #size-cells = <0>; From 61574073e15cbaaab3fa1b2ad7df3ffe21e48509 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Oct 2024 16:10:51 +0200 Subject: [PATCH 29/46] leds: bcm63138: Use scopes and guards Use scoped helpers and guards to handle DT node iterations and spinlocks. This cuts some lines of code and eliminates common mistakes (such as the missing of_node_put()). Signed-off-by: Linus Walleij Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20241010-bcm63138-leds-v4-2-cdb80780a555@linaro.org Signed-off-by: Lee Jones --- drivers/leds/blink/leds-bcm63138.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/leds/blink/leds-bcm63138.c b/drivers/leds/blink/leds-bcm63138.c index 3a5e0b98bfbc..374f68f4f277 100644 --- a/drivers/leds/blink/leds-bcm63138.c +++ b/drivers/leds/blink/leds-bcm63138.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2021 Rafał Miłecki */ +#include #include #include #include @@ -125,17 +126,14 @@ static void bcm63138_leds_brightness_set(struct led_classdev *led_cdev, { struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev); struct bcm63138_leds *leds = led->leds; - unsigned long flags; - spin_lock_irqsave(&leds->lock, flags); + guard(spinlock_irqsave)(&leds->lock); bcm63138_leds_enable_led(leds, led, value); if (!value) bcm63138_leds_set_flash_rate(leds, led, 0); else bcm63138_leds_set_bright(leds, led, value); - - spin_unlock_irqrestore(&leds->lock, flags); } static int bcm63138_leds_blink_set(struct led_classdev *led_cdev, @@ -144,7 +142,6 @@ static int bcm63138_leds_blink_set(struct led_classdev *led_cdev, { struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev); struct bcm63138_leds *leds = led->leds; - unsigned long flags; u8 value; if (!*delay_on && !*delay_off) { @@ -179,13 +176,11 @@ static int bcm63138_leds_blink_set(struct led_classdev *led_cdev, return -EINVAL; } - spin_lock_irqsave(&leds->lock, flags); + guard(spinlock_irqsave)(&leds->lock); bcm63138_leds_enable_led(leds, led, BCM63138_MAX_BRIGHTNESS); bcm63138_leds_set_flash_rate(leds, led, value); - spin_unlock_irqrestore(&leds->lock, flags); - return 0; } @@ -259,7 +254,6 @@ static int bcm63138_leds_probe(struct platform_device *pdev) struct device_node *np = dev_of_node(&pdev->dev); struct device *dev = &pdev->dev; struct bcm63138_leds *leds; - struct device_node *child; leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL); if (!leds) @@ -280,7 +274,7 @@ static int bcm63138_leds_probe(struct platform_device *pdev) bcm63138_leds_write(leds, BCM63138_SERIAL_LED_POLARITY, 0); bcm63138_leds_write(leds, BCM63138_PARALLEL_LED_POLARITY, 0); - for_each_available_child_of_node(np, child) { + for_each_available_child_of_node_scoped(np, child) { bcm63138_leds_create_led(leds, child); } From 5f312fdace9cee3fb8a7964469546fb4d8624ff7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Oct 2024 16:10:52 +0200 Subject: [PATCH 30/46] leds: bcm63138: Handle shift register config This adds code to optionally read the width of the shift register chain from the device tree and use it to set up the register controlling the shifter hardware. If the property is not present, the boot-time default is used so existing device trees keep working as this is what they assume. Signed-off-by: Linus Walleij Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20241010-bcm63138-leds-v4-3-cdb80780a555@linaro.org Signed-off-by: Lee Jones --- drivers/leds/blink/leds-bcm63138.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/leds/blink/leds-bcm63138.c b/drivers/leds/blink/leds-bcm63138.c index 374f68f4f277..9fe1af156c80 100644 --- a/drivers/leds/blink/leds-bcm63138.c +++ b/drivers/leds/blink/leds-bcm63138.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2021 Rafał Miłecki */ +#include #include #include #include @@ -254,6 +255,7 @@ static int bcm63138_leds_probe(struct platform_device *pdev) struct device_node *np = dev_of_node(&pdev->dev); struct device *dev = &pdev->dev; struct bcm63138_leds *leds; + u32 shift_bits; leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL); if (!leds) @@ -267,6 +269,12 @@ static int bcm63138_leds_probe(struct platform_device *pdev) spin_lock_init(&leds->lock); + /* If this property is not present, we use boot defaults */ + if (!of_property_read_u32(np, "brcm,serial-shift-bits", &shift_bits)) { + bcm63138_leds_write(leds, BCM63138_SERIAL_LED_SHIFT_SEL, + GENMASK(shift_bits - 1, 0)); + } + bcm63138_leds_write(leds, BCM63138_GLB_CTRL, BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL | BCM63138_GLB_CTRL_SERIAL_LED_EN_POL); From def9c8b7bc0d9d7436cf29eb0106698e356f006d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Oct 2024 16:10:53 +0200 Subject: [PATCH 31/46] leds: bcm63138: Add some register defines The Power LUT (Look-up Table) register base was missing, also add the bit define for sending serial LED data in reverse order, and use the BIT() macro to define the bits in the control register. Signed-off-by: Linus Walleij Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20241010-bcm63138-leds-v4-4-cdb80780a555@linaro.org Signed-off-by: Lee Jones --- drivers/leds/blink/leds-bcm63138.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/leds/blink/leds-bcm63138.c b/drivers/leds/blink/leds-bcm63138.c index 9fe1af156c80..ef2e511438cc 100644 --- a/drivers/leds/blink/leds-bcm63138.c +++ b/drivers/leds/blink/leds-bcm63138.c @@ -21,8 +21,10 @@ #define BCM63138_LEDS_PER_REG (32 / BCM63138_LED_BITS) /* 8 */ #define BCM63138_GLB_CTRL 0x00 -#define BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL 0x00000002 -#define BCM63138_GLB_CTRL_SERIAL_LED_EN_POL 0x00000008 +#define BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL BIT(1) +#define BCM63138_GLB_CTRL_SERIAL_LED_CLK_POL BIT(2) +#define BCM63138_GLB_CTRL_SERIAL_LED_EN_POL BIT(3) +#define BCM63138_GLB_CTRL_SERIAL_LED_MSB_FIRST BIT(4) #define BCM63138_MASK 0x04 #define BCM63138_HW_LED_EN 0x08 #define BCM63138_SERIAL_LED_SHIFT_SEL 0x0c @@ -35,6 +37,7 @@ #define BCM63138_BRIGHT_CTRL3 0x28 #define BCM63138_BRIGHT_CTRL4 0x2c #define BCM63138_POWER_LED_CFG 0x30 +#define BCM63138_POWER_LUT_BASE0 0x34 /* -> b0 */ #define BCM63138_HW_POLARITY 0xb4 #define BCM63138_SW_DATA 0xb8 #define BCM63138_SW_POLARITY 0xbc From 6bdc6d4a374fa5a4fbed7d913f0c6d11d08bb867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 10 Oct 2024 22:36:23 +0200 Subject: [PATCH 32/46] leds: Switch back to struct platform_driver::remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 0edb555a65d1 ("platform: Make platform_driver::remove() return void") .remove() is (again) the right callback to implement for platform drivers. Convert all platform drivers below drivers/leds/ to use .remove(), with the eventual goal to drop struct platform_driver::remove_new(). As .remove() and .remove_new() have the same prototypes, conversion is done by just changing the structure member name in the driver initializer. While touching these files, make indention of the struct initializer consistent in several files. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20241010203622.839625-5-u.kleine-koenig@baylibre.com Signed-off-by: Lee Jones --- drivers/leds/blink/leds-lgm-sso.c | 2 +- drivers/leds/flash/leds-aat1290.c | 2 +- drivers/leds/flash/leds-ktd2692.c | 2 +- drivers/leds/flash/leds-max77693.c | 2 +- drivers/leds/flash/leds-mt6360.c | 2 +- drivers/leds/flash/leds-qcom-flash.c | 2 +- drivers/leds/flash/leds-rt8515.c | 2 +- drivers/leds/flash/leds-sgm3140.c | 2 +- drivers/leds/leds-88pm860x.c | 2 +- drivers/leds/leds-adp5520.c | 2 +- drivers/leds/leds-cht-wcove.c | 2 +- drivers/leds/leds-clevo-mail.c | 2 +- drivers/leds/leds-da903x.c | 2 +- drivers/leds/leds-da9052.c | 2 +- drivers/leds/leds-lm3533.c | 2 +- drivers/leds/leds-mc13783.c | 2 +- drivers/leds/leds-mt6323.c | 2 +- drivers/leds/leds-powernv.c | 4 ++-- drivers/leds/leds-rb532.c | 2 +- drivers/leds/leds-regulator.c | 2 +- drivers/leds/leds-sc27xx-bltc.c | 2 +- drivers/leds/leds-sun50i-a100.c | 2 +- drivers/leds/leds-sunfire.c | 4 ++-- drivers/leds/leds-wm831x-status.c | 2 +- drivers/leds/leds-wm8350.c | 2 +- drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c | 2 +- drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c | 2 +- drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c | 2 +- 28 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index 7b04ea146260..effaaaf302b5 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -861,7 +861,7 @@ MODULE_DEVICE_TABLE(of, of_sso_led_match); static struct platform_driver intel_sso_led_driver = { .probe = intel_sso_led_probe, - .remove_new = intel_sso_led_remove, + .remove = intel_sso_led_remove, .driver = { .name = "lgm-ssoled", .of_match_table = of_sso_led_match, diff --git a/drivers/leds/flash/leds-aat1290.c b/drivers/leds/flash/leds-aat1290.c index c7b6a1f01288..49251cfd3350 100644 --- a/drivers/leds/flash/leds-aat1290.c +++ b/drivers/leds/flash/leds-aat1290.c @@ -536,7 +536,7 @@ MODULE_DEVICE_TABLE(of, aat1290_led_dt_match); static struct platform_driver aat1290_led_driver = { .probe = aat1290_led_probe, - .remove_new = aat1290_led_remove, + .remove = aat1290_led_remove, .driver = { .name = "aat1290", .of_match_table = aat1290_led_dt_match, diff --git a/drivers/leds/flash/leds-ktd2692.c b/drivers/leds/flash/leds-ktd2692.c index 16a01a200c0b..2e42f845df28 100644 --- a/drivers/leds/flash/leds-ktd2692.c +++ b/drivers/leds/flash/leds-ktd2692.c @@ -343,7 +343,7 @@ static struct platform_driver ktd2692_driver = { .of_match_table = ktd2692_match, }, .probe = ktd2692_probe, - .remove_new = ktd2692_remove, + .remove = ktd2692_remove, }; module_platform_driver(ktd2692_driver); diff --git a/drivers/leds/flash/leds-max77693.c b/drivers/leds/flash/leds-max77693.c index 90d78b3d22f8..daee10986108 100644 --- a/drivers/leds/flash/leds-max77693.c +++ b/drivers/leds/flash/leds-max77693.c @@ -1042,7 +1042,7 @@ MODULE_DEVICE_TABLE(of, max77693_led_dt_match); static struct platform_driver max77693_led_driver = { .probe = max77693_led_probe, - .remove_new = max77693_led_remove, + .remove = max77693_led_remove, .driver = { .name = "max77693-led", .of_match_table = max77693_led_dt_match, diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c index 676236c19ec4..462a902f54e0 100644 --- a/drivers/leds/flash/leds-mt6360.c +++ b/drivers/leds/flash/leds-mt6360.c @@ -886,7 +886,7 @@ static struct platform_driver mt6360_led_driver = { .of_match_table = mt6360_led_of_id, }, .probe = mt6360_led_probe, - .remove_new = mt6360_led_remove, + .remove = mt6360_led_remove, }; module_platform_driver(mt6360_led_driver); diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c index ab848c5acd2d..b4c19be51c4d 100644 --- a/drivers/leds/flash/leds-qcom-flash.c +++ b/drivers/leds/flash/leds-qcom-flash.c @@ -940,7 +940,7 @@ static struct platform_driver qcom_flash_led_driver = { .of_match_table = qcom_flash_led_match_table, }, .probe = qcom_flash_led_probe, - .remove_new = qcom_flash_led_remove, + .remove = qcom_flash_led_remove, }; module_platform_driver(qcom_flash_led_driver); diff --git a/drivers/leds/flash/leds-rt8515.c b/drivers/leds/flash/leds-rt8515.c index eef426924eaf..6b051f182b72 100644 --- a/drivers/leds/flash/leds-rt8515.c +++ b/drivers/leds/flash/leds-rt8515.c @@ -388,7 +388,7 @@ static struct platform_driver rt8515_driver = { .of_match_table = rt8515_match, }, .probe = rt8515_probe, - .remove_new = rt8515_remove, + .remove = rt8515_remove, }; module_platform_driver(rt8515_driver); diff --git a/drivers/leds/flash/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c index db0ac6641954..3c01739c0b46 100644 --- a/drivers/leds/flash/leds-sgm3140.c +++ b/drivers/leds/flash/leds-sgm3140.c @@ -300,7 +300,7 @@ MODULE_DEVICE_TABLE(of, sgm3140_dt_match); static struct platform_driver sgm3140_driver = { .probe = sgm3140_probe, - .remove_new = sgm3140_remove, + .remove = sgm3140_remove, .driver = { .name = "sgm3140", .of_match_table = sgm3140_dt_match, diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 81238376484b..ef5c6c4667ab 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -226,7 +226,7 @@ static struct platform_driver pm860x_led_driver = { .name = "88pm860x-led", }, .probe = pm860x_led_probe, - .remove_new = pm860x_led_remove, + .remove = pm860x_led_remove, }; module_platform_driver(pm860x_led_driver); diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index d89a4dca50ae..13e5bc80e56e 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c @@ -184,7 +184,7 @@ static struct platform_driver adp5520_led_driver = { .name = "adp5520-led", }, .probe = adp5520_led_probe, - .remove_new = adp5520_led_remove, + .remove = adp5520_led_remove, }; module_platform_driver(adp5520_led_driver); diff --git a/drivers/leds/leds-cht-wcove.c b/drivers/leds/leds-cht-wcove.c index b4998402b8c6..8246f048edcb 100644 --- a/drivers/leds/leds-cht-wcove.c +++ b/drivers/leds/leds-cht-wcove.c @@ -461,7 +461,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cht_wc_leds_pm, cht_wc_leds_suspend, cht_wc_leds static struct platform_driver cht_wc_leds_driver = { .probe = cht_wc_leds_probe, - .remove_new = cht_wc_leds_remove, + .remove = cht_wc_leds_remove, .shutdown = cht_wc_leds_disable, .driver = { .name = "cht_wcove_leds", diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c index 82da0fe688ad..f00b16ac1586 100644 --- a/drivers/leds/leds-clevo-mail.c +++ b/drivers/leds/leds-clevo-mail.c @@ -165,7 +165,7 @@ static void clevo_mail_led_remove(struct platform_device *pdev) } static struct platform_driver clevo_mail_led_driver = { - .remove_new = clevo_mail_led_remove, + .remove = clevo_mail_led_remove, .driver = { .name = KBUILD_MODNAME, }, diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index f067a5f4d3c4..71209b3c8f1e 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c @@ -133,7 +133,7 @@ static struct platform_driver da903x_led_driver = { .name = "da903x-led", }, .probe = da903x_led_probe, - .remove_new = da903x_led_remove, + .remove = da903x_led_remove, }; module_platform_driver(da903x_led_driver); diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c index 64679d62076b..7c9051184a59 100644 --- a/drivers/leds/leds-da9052.c +++ b/drivers/leds/leds-da9052.c @@ -179,7 +179,7 @@ static struct platform_driver da9052_led_driver = { .name = "da9052-leds", }, .probe = da9052_led_probe, - .remove_new = da9052_led_remove, + .remove = da9052_led_remove, }; module_platform_driver(da9052_led_driver); diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c index a3d33165d262..45795f2a1042 100644 --- a/drivers/leds/leds-lm3533.c +++ b/drivers/leds/leds-lm3533.c @@ -744,7 +744,7 @@ static struct platform_driver lm3533_led_driver = { .name = "lm3533-leds", }, .probe = lm3533_led_probe, - .remove_new = lm3533_led_remove, + .remove = lm3533_led_remove, .shutdown = lm3533_led_shutdown, }; module_platform_driver(lm3533_led_driver); diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index da99d114bfb2..e22f09d13798 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c @@ -301,7 +301,7 @@ static struct platform_driver mc13xxx_led_driver = { .driver = { .name = "mc13xxx-led", }, - .remove_new = mc13xxx_led_remove, + .remove = mc13xxx_led_remove, .id_table = mc13xxx_led_id_table, }; module_platform_driver_probe(mc13xxx_led_driver, mc13xxx_led_probe); diff --git a/drivers/leds/leds-mt6323.c b/drivers/leds/leds-mt6323.c index a19e8e0b6d1b..dbdc221c3828 100644 --- a/drivers/leds/leds-mt6323.c +++ b/drivers/leds/leds-mt6323.c @@ -713,7 +713,7 @@ MODULE_DEVICE_TABLE(of, mt6323_led_dt_match); static struct platform_driver mt6323_led_driver = { .probe = mt6323_led_probe, - .remove_new = mt6323_led_remove, + .remove = mt6323_led_remove, .driver = { .name = "mt6323-led", .of_match_table = mt6323_led_dt_match, diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c index 49ab8c9a3f29..3a38578ce8e4 100644 --- a/drivers/leds/leds-powernv.c +++ b/drivers/leds/leds-powernv.c @@ -323,8 +323,8 @@ static const struct of_device_id powernv_led_match[] = { MODULE_DEVICE_TABLE(of, powernv_led_match); static struct platform_driver powernv_led_driver = { - .probe = powernv_led_probe, - .remove_new = powernv_led_remove, + .probe = powernv_led_probe, + .remove = powernv_led_remove, .driver = { .name = "powernv-led-driver", .of_match_table = powernv_led_match, diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c index e66f73879c8e..782e1c11ee44 100644 --- a/drivers/leds/leds-rb532.c +++ b/drivers/leds/leds-rb532.c @@ -49,7 +49,7 @@ static void rb532_led_remove(struct platform_device *pdev) static struct platform_driver rb532_led_driver = { .probe = rb532_led_probe, - .remove_new = rb532_led_remove, + .remove = rb532_led_remove, .driver = { .name = "rb532-led", }, diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c index 848e929c4a61..ade64629431a 100644 --- a/drivers/leds/leds-regulator.c +++ b/drivers/leds/leds-regulator.c @@ -193,7 +193,7 @@ static struct platform_driver regulator_led_driver = { .of_match_table = regulator_led_of_match, }, .probe = regulator_led_probe, - .remove_new = regulator_led_remove, + .remove = regulator_led_remove, }; module_platform_driver(regulator_led_driver); diff --git a/drivers/leds/leds-sc27xx-bltc.c b/drivers/leds/leds-sc27xx-bltc.c index cca98c644aa6..0c5169773949 100644 --- a/drivers/leds/leds-sc27xx-bltc.c +++ b/drivers/leds/leds-sc27xx-bltc.c @@ -344,7 +344,7 @@ static struct platform_driver sc27xx_led_driver = { .of_match_table = sc27xx_led_of_match, }, .probe = sc27xx_led_probe, - .remove_new = sc27xx_led_remove, + .remove = sc27xx_led_remove, }; module_platform_driver(sc27xx_led_driver); diff --git a/drivers/leds/leds-sun50i-a100.c b/drivers/leds/leds-sun50i-a100.c index 03f1b6424692..2c9bd360ab81 100644 --- a/drivers/leds/leds-sun50i-a100.c +++ b/drivers/leds/leds-sun50i-a100.c @@ -558,7 +558,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sun50i_a100_ledc_pm, static struct platform_driver sun50i_a100_ledc_driver = { .probe = sun50i_a100_ledc_probe, - .remove_new = sun50i_a100_ledc_remove, + .remove = sun50i_a100_ledc_remove, .shutdown = sun50i_a100_ledc_remove, .driver = { .name = "sun50i-a100-ledc", diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c index a621e5e5c75c..bd24e7f5947a 100644 --- a/drivers/leds/leds-sunfire.c +++ b/drivers/leds/leds-sunfire.c @@ -219,7 +219,7 @@ MODULE_ALIAS("platform:sunfire-fhc-leds"); static struct platform_driver sunfire_clockboard_led_driver = { .probe = sunfire_clockboard_led_probe, - .remove_new = sunfire_led_generic_remove, + .remove = sunfire_led_generic_remove, .driver = { .name = "sunfire-clockboard-leds", }, @@ -227,7 +227,7 @@ static struct platform_driver sunfire_clockboard_led_driver = { static struct platform_driver sunfire_fhc_led_driver = { .probe = sunfire_fhc_led_probe, - .remove_new = sunfire_led_generic_remove, + .remove = sunfire_led_generic_remove, .driver = { .name = "sunfire-fhc-leds", }, diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c index 70b32d80f960..05930e9e8887 100644 --- a/drivers/leds/leds-wm831x-status.c +++ b/drivers/leds/leds-wm831x-status.c @@ -292,7 +292,7 @@ static struct platform_driver wm831x_status_driver = { .name = "wm831x-status", }, .probe = wm831x_status_probe, - .remove_new = wm831x_status_remove, + .remove = wm831x_status_remove, }; module_platform_driver(wm831x_status_driver); diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index 61cbefa05710..87e60ea927b9 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c @@ -255,7 +255,7 @@ static struct platform_driver wm8350_led_driver = { .name = "wm8350-led", }, .probe = wm8350_led_probe, - .remove_new = wm8350_led_remove, + .remove = wm8350_led_remove, .shutdown = wm8350_led_shutdown, }; diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c index 726c186391af..c98c370687c2 100644 --- a/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c @@ -53,7 +53,7 @@ static void simatic_ipc_leds_gpio_apollolake_remove(struct platform_device *pdev static struct platform_driver simatic_ipc_led_gpio_apollolake_driver = { .probe = simatic_ipc_leds_gpio_apollolake_probe, - .remove_new = simatic_ipc_leds_gpio_apollolake_remove, + .remove = simatic_ipc_leds_gpio_apollolake_remove, .driver = { .name = KBUILD_MODNAME, }, diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c index 3fec96c549c1..7f7cff275448 100644 --- a/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c @@ -43,7 +43,7 @@ static void simatic_ipc_leds_gpio_elkhartlake_remove(struct platform_device *pde static struct platform_driver simatic_ipc_led_gpio_elkhartlake_driver = { .probe = simatic_ipc_leds_gpio_elkhartlake_probe, - .remove_new = simatic_ipc_leds_gpio_elkhartlake_remove, + .remove = simatic_ipc_leds_gpio_elkhartlake_remove, .driver = { .name = KBUILD_MODNAME, }, diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c index a1f10952513c..bc23d701bcb7 100644 --- a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c @@ -93,7 +93,7 @@ static void simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev) static struct platform_driver simatic_ipc_led_gpio_driver = { .probe = simatic_ipc_leds_gpio_f7188x_probe, - .remove_new = simatic_ipc_leds_gpio_f7188x_remove, + .remove = simatic_ipc_leds_gpio_f7188x_remove, .driver = { .name = KBUILD_MODNAME, }, From c161656b48ee22e51804d26fcc11bbcd2486d697 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Thu, 10 Oct 2024 13:53:36 +0100 Subject: [PATCH 33/46] dt-bindings: leds: Add 'active-high' property Other than described in commit c94d1783136e ("dt-bindings: net: phy: Make LED active-low property common") the absence of the 'active-low' property means not to touch the polarity settings which are inherited from reset defaults, the bootloader or bootstrap configuration. Hence, in order to override a LED pin being active-high in case of the default, bootloader or bootstrap setting being active-low an additional property 'active-high' is required. Document that property and make it mutually exclusive to the existing 'active-low' property. Signed-off-by: Daniel Golle Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/e9b15613a81129ceecb07ec51f71bbe75425ad2e.1728558223.git.daniel@makrotopia.org Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/leds/common.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml index 9cd89f30fa7c..3e8319e44339 100644 --- a/Documentation/devicetree/bindings/leds/common.yaml +++ b/Documentation/devicetree/bindings/leds/common.yaml @@ -204,6 +204,12 @@ properties: #trigger-source-cells property in the source node. $ref: /schemas/types.yaml#/definitions/phandle-array + active-high: + type: boolean + description: + Makes LED active high. To turn the LED ON, line needs to be + set to high voltage instead of low. + active-low: type: boolean description: @@ -227,6 +233,14 @@ properties: Maximum timeout in microseconds after which the flash LED is turned off. Required for flash LED nodes with configurable timeout. +allOf: + - if: + required: + - active-low + then: + properties: + active-high: false + additionalProperties: true examples: From 681d5fa6440cf0fd3f561638c598db18aa77e641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= Date: Wed, 9 Oct 2024 11:56:35 +0200 Subject: [PATCH 34/46] leds: lp5562: Add multicolor brightness control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The framework for multicolor brightness control is already in place in the lp55xx-common code but the function to control the multicolor brightness for this particular chip is still missing. Implement the multicolor_brightness_fn function to allow multicolor brightness control of LEDs connected to the LP5562 LED driver. Signed-off-by: Michal Vokáč Link: https://lore.kernel.org/r/20241009095635.2790613-1-michal.vokac@ysoft.com Signed-off-by: Lee Jones --- drivers/leds/leds-lp5562.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index b26bcc81d079..14a4af361b26 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -161,6 +161,30 @@ static int lp5562_post_init_device(struct lp55xx_chip *chip) return 0; } +static int lp5562_multicolor_brightness(struct lp55xx_led *led) +{ + struct lp55xx_chip *chip = led->chip; + static const u8 addr[] = { + LP5562_REG_R_PWM, + LP5562_REG_G_PWM, + LP5562_REG_B_PWM, + LP5562_REG_W_PWM, + }; + int ret; + int i; + + guard(mutex)(&chip->lock); + for (i = 0; i < led->mc_cdev.num_colors; i++) { + ret = lp55xx_write(chip, + addr[led->mc_cdev.subled_info[i].channel], + led->mc_cdev.subled_info[i].brightness); + if (ret) + break; + } + + return ret; +} + static int lp5562_led_brightness(struct lp55xx_led *led) { struct lp55xx_chip *chip = led->chip; @@ -364,6 +388,7 @@ static struct lp55xx_device_config lp5562_cfg = { .post_init_device = lp5562_post_init_device, .set_led_current = lp5562_set_led_current, .brightness_fn = lp5562_led_brightness, + .multicolor_brightness_fn = lp5562_multicolor_brightness, .run_engine = lp5562_run_engine, .firmware_cb = lp55xx_firmware_loaded_cb, .dev_attr_group = &lp5562_group, From 6cbf5c99541ac681cf5c6155b582dfbcd879eae3 Mon Sep 17 00:00:00 2001 From: Suraj Sonawane Date: Wed, 16 Oct 2024 09:51:42 +0530 Subject: [PATCH 35/46] leds: rgb: leds-mt6370-rgb: Fix uninitialized variable 'ret' in mt6370_mc_pattern_clear Fix the uninitialized symbol 'ret' in the function mt6370_mc_pattern_clear to resolve the following warning: drivers/leds/rgb/leds-mt6370-rgb.c:604 mt6370_mc_pattern_clear() error: uninitialized symbol 'ret'. Initialize 'ret' to 0 to prevent undefined behavior from uninitialized access. Signed-off-by: Suraj Sonawane Link: https://lore.kernel.org/r/20241016042142.8088-1-surajsonawane0215@gmail.com Signed-off-by: Lee Jones --- drivers/leds/rgb/leds-mt6370-rgb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/rgb/leds-mt6370-rgb.c b/drivers/leds/rgb/leds-mt6370-rgb.c index fe76e8e27f9c..eafdfcf98e41 100644 --- a/drivers/leds/rgb/leds-mt6370-rgb.c +++ b/drivers/leds/rgb/leds-mt6370-rgb.c @@ -587,7 +587,7 @@ static inline int mt6370_mc_pattern_clear(struct led_classdev *lcdev) struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); struct mt6370_priv *priv = led->priv; struct mc_subled *subled; - int i, ret; + int i, ret = 0; mutex_lock(&led->priv->lock); From f92d2e9334171d07b47189397f222f64dcb77617 Mon Sep 17 00:00:00 2001 From: Ricky CX Wu Date: Wed, 16 Oct 2024 17:38:55 +0800 Subject: [PATCH 36/46] dt-bindings: leds: pca955x: Convert text bindings to YAML Convert the text bindings of pca955x to YAML so it could be used to validate the DTS. Signed-off-by: Ricky CX Wu Signed-off-by: Delphine CC Chiu Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20241016093857.925467-1-Delphine_CC_Chiu@wiwynn.com Signed-off-by: Lee Jones --- .../devicetree/bindings/leds/leds-pca955x.txt | 89 ---------- .../devicetree/bindings/leds/nxp,pca955x.yaml | 158 ++++++++++++++++++ 2 files changed, 158 insertions(+), 89 deletions(-) delete mode 100644 Documentation/devicetree/bindings/leds/leds-pca955x.txt create mode 100644 Documentation/devicetree/bindings/leds/nxp,pca955x.yaml diff --git a/Documentation/devicetree/bindings/leds/leds-pca955x.txt b/Documentation/devicetree/bindings/leds/leds-pca955x.txt deleted file mode 100644 index 817f460f3a72..000000000000 --- a/Documentation/devicetree/bindings/leds/leds-pca955x.txt +++ /dev/null @@ -1,89 +0,0 @@ -* NXP - pca955x LED driver - -The PCA955x family of chips are I2C LED blinkers whose pins not used -to control LEDs can be used as general purpose I/Os. The GPIO pins can -be input or output, and output pins can also be pulse-width controlled. - -Required properties: -- compatible : should be one of : - "nxp,pca9550" - "nxp,pca9551" - "nxp,pca9552" - "ibm,pca9552" - "nxp,pca9553" -- #address-cells: must be 1 -- #size-cells: must be 0 -- reg: I2C slave address. depends on the model. - -Optional properties: -- gpio-controller: allows pins to be used as GPIOs. -- #gpio-cells: must be 2. -- gpio-line-names: define the names of the GPIO lines - -LED sub-node properties: -- reg : number of LED line. - from 0 to 1 for the pca9550 - from 0 to 7 for the pca9551 - from 0 to 15 for the pca9552 - from 0 to 3 for the pca9553 -- type: (optional) either - PCA955X_TYPE_NONE - PCA955X_TYPE_LED - PCA955X_TYPE_GPIO - see dt-bindings/leds/leds-pca955x.h (default to LED) -- label : (optional) - see Documentation/devicetree/bindings/leds/common.txt -- linux,default-trigger : (optional) - see Documentation/devicetree/bindings/leds/common.txt - -Examples: - -pca9552: pca9552@60 { - compatible = "nxp,pca9552"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x60>; - - gpio-controller; - #gpio-cells = <2>; - gpio-line-names = "GPIO12", "GPIO13", "GPIO14", "GPIO15"; - - gpio@12 { - reg = <12>; - type = ; - }; - gpio@13 { - reg = <13>; - type = ; - }; - gpio@14 { - reg = <14>; - type = ; - }; - gpio@15 { - reg = <15>; - type = ; - }; - - led@0 { - label = "red:power"; - linux,default-trigger = "default-on"; - reg = <0>; - type = ; - }; - led@1 { - label = "green:power"; - reg = <1>; - type = ; - }; - led@2 { - label = "pca9552:yellow"; - reg = <2>; - type = ; - }; - led@3 { - label = "pca9552:white"; - reg = <3>; - type = ; - }; -}; diff --git a/Documentation/devicetree/bindings/leds/nxp,pca955x.yaml b/Documentation/devicetree/bindings/leds/nxp,pca955x.yaml new file mode 100644 index 000000000000..ae7384cc760c --- /dev/null +++ b/Documentation/devicetree/bindings/leds/nxp,pca955x.yaml @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/nxp,pca955x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP PCA955X LED controllers + +maintainers: + - Nate Case + +description: | + The PCA955x family of chips are I2C LED blinkers whose pins not used + to control LEDs can be used as general purpose I/Os. The GPIO pins can + be input or output, and output pins can also be pulse-width controlled. + + For more product information please see the link below: + - https://www.nxp.com/docs/en/data-sheet/PCA9552.pdf + +properties: + compatible: + enum: + - nxp,pca9550 + - nxp,pca9551 + - nxp,pca9552 + - ibm,pca9552 + - nxp,pca9553 + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + gpio-controller: true + + gpio-line-names: + minItems: 1 + maxItems: 16 + + "#gpio-cells": + const: 2 + +patternProperties: + "^led@[0-9a-f]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + maxItems: 1 + type: + description: | + Output configuration, see include/dt-bindings/leds/leds-pca955x.h + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + minimum: 0 + maximum: 2 + + required: + - reg + +allOf: + - if: + properties: + compatible: + contains: + enum: + - nxp,pca9550 + then: + patternProperties: + "^led@[0-9a-f]$": + properties: + reg: + maximum: 1 + - if: + properties: + compatible: + contains: + enum: + - nxp,pca9551 + then: + patternProperties: + "^led@[0-9a-f]$": + properties: + reg: + maximum: 7 + - if: + properties: + compatible: + contains: + enum: + - nxp,pca9552 + - ibm,pca9552 + then: + patternProperties: + "^led@[0-9a-f]$": + properties: + reg: + maximum: 15 + - if: + properties: + compatible: + contains: + enum: + - nxp,pca9553 + then: + patternProperties: + "^led@[0-9a-f]$": + properties: + reg: + maximum: 3 + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + led-controller@60 { + compatible = "nxp,pca9552"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + label = "red:power"; + linux,default-trigger = "default-on"; + type = ; + }; + led@1 { + reg = <1>; + label = "green:power"; + type = ; + }; + led@2 { + reg = <2>; + label = "pca9552:yellow"; + type = ; + }; + led@3 { + reg = <3>; + label = "pca9552:white"; + type = ; + }; + }; + }; + +... From 09b1ef9813a0742674f7efe26104403ca94a1b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vok=C3=A1=C4=8D?= Date: Thu, 17 Oct 2024 17:08:12 +0200 Subject: [PATCH 37/46] leds: lp55xx: Remove redundant test for invalid channel number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 92a81562e695 ("leds: lp55xx: Add multicolor framework support to lp55xx") there are two subsequent tests if the chan_nr (reg property) is in valid range. One in the lp55xx_init_led() function and one in the lp55xx_parse_common_child() function that was added with the mentioned commit. There are two issues with that. First is in the lp55xx_parse_common_child() function where the reg property is tested right after it is read from the device tree. Test for the upper range is not correct though. Valid reg values are 0 to (max_channel - 1) so it should be >=. Second issue is that in case the parsed value is out of the range the probe just fails and no error message is shown as the code never reaches the second test that prints and error message. Remove the test form lp55xx_parse_common_child() function completely and keep the one in lp55xx_init_led() function to deal with it. Fixes: 92a81562e695 ("leds: lp55xx: Add multicolor framework support to lp55xx") Cc: stable@vger.kernel.org Signed-off-by: Michal Vokáč Link: https://lore.kernel.org/r/20241017150812.3563629-1-michal.vokac@ysoft.com Signed-off-by: Lee Jones --- drivers/leds/leds-lp55xx-common.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index 5a2e259679cf..e71456a56ab8 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -1132,9 +1132,6 @@ static int lp55xx_parse_common_child(struct device_node *np, if (ret) return ret; - if (*chan_nr < 0 || *chan_nr > cfg->max_channel) - return -EINVAL; - return 0; } From 99d36eed05e735105e89e0a18877518c08618e52 Mon Sep 17 00:00:00 2001 From: Dipendra Khadka Date: Sat, 19 Oct 2024 07:33:01 +0000 Subject: [PATCH 38/46] leds: bcm6328: Replace divide condition with comparison for shift value Fixes the following Smatch warnings: drivers/leds/leds-bcm6328.c:116 bcm6328_led_mode() warn: replace divide condition 'shift / 16' with 'shift >= 16' drivers/leds/leds-bcm6328.c:360 bcm6328_led() warn: replace divide condition 'shift / 16' with 'shift >= 16' Signed-off-by: Dipendra Khadka Reviewed-by: Pavel Machek Link: https://lore.kernel.org/r/20241019073302.35499-1-kdipendra88@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-bcm6328.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index 29f5bad61796..592bbf4b7e35 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -113,7 +113,7 @@ static void bcm6328_led_mode(struct bcm6328_led *led, unsigned long value) unsigned long val, shift; shift = bcm6328_pin2shift(led->pin); - if (shift / 16) + if (shift >= 16) mode = led->mem + BCM6328_REG_MODE_HI; else mode = led->mem + BCM6328_REG_MODE_LO; @@ -357,7 +357,7 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg, break; case LEDS_DEFSTATE_KEEP: shift = bcm6328_pin2shift(led->pin); - if (shift / 16) + if (shift >= 16) mode = mem + BCM6328_REG_MODE_HI; else mode = mem + BCM6328_REG_MODE_LO; From 64dd44a658065ab5595bbfe2cb4d8fd30c9e34a2 Mon Sep 17 00:00:00 2001 From: Benedikt Niedermayr Date: Mon, 28 Oct 2024 12:23:59 +0100 Subject: [PATCH 39/46] MAINTAINERS: Replace Siemens IPC related bouncing maintainers Since complaints about bouncing maintainers raised [1] we have now a replacement for maintainers that stepped away from their duties. [1] https://www.spinics.net/lists/platform-driver-x86/msg47105.html Signed-off-by: Benedikt Niedermayr Link: https://lore.kernel.org/r/20241028112359.3333152-2-benedikt.niedermayr@siemens.com Signed-off-by: Lee Jones --- MAINTAINERS | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c27f3190737f..eee81532993a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21108,16 +21108,16 @@ F: drivers/media/usb/siano/ F: drivers/media/usb/siano/ SIEMENS IPC LED DRIVERS -M: Gerd Haeussler -M: Xing Tong Wu +M: Bao Cheng Su +M: Benedikt Niedermayr M: Tobias Schaffner L: linux-leds@vger.kernel.org S: Maintained F: drivers/leds/simple/ SIEMENS IPC PLATFORM DRIVERS -M: Gerd Haeussler -M: Xing Tong Wu +M: Bao Cheng Su +M: Benedikt Niedermayr M: Tobias Schaffner L: platform-driver-x86@vger.kernel.org S: Maintained @@ -21126,8 +21126,8 @@ F: include/linux/platform_data/x86/simatic-ipc-base.h F: include/linux/platform_data/x86/simatic-ipc.h SIEMENS IPC WATCHDOG DRIVERS -M: Gerd Haeussler -M: Xing Tong Wu +M: Bao Cheng Su +M: Benedikt Niedermayr M: Tobias Schaffner L: linux-watchdog@vger.kernel.org S: Maintained From 32360bf6a5d4016669c3545e7b0ec939937f5331 Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Wed, 4 Sep 2024 01:39:30 +0300 Subject: [PATCH 40/46] leds: Introduce ordered workqueue for LEDs events instead of system_wq This allows to setup ordered workqueue for LEDs events. This may be useful, because default 'system_wq' does not guarantee execution order of each work_struct, thus for several brightness update requests (for multiple LEDs), real brightness switch could be in random order. Yes, for sysfs-based LEDs we have flush_work() call inside brightness_store() operation, but it's blocking call, so userspace caller can be blocked at a long time, which means LEDs animation stream can be broken. Ordered workqueue has the same behaviour as system_wq + flush_work(), but all scheduled works are async and userspace caller is not blocked, which it better for userspace animation scheduling. Signed-off-by: Alexey Romanov Signed-off-by: Dmitry Rokosov Link: https://lore.kernel.org/r/20240903223936.21292-1-ddrokosov@salutedevices.com [Lee: Couple of style fix-ups] Signed-off-by: Lee Jones --- drivers/leds/led-class.c | 12 +++++++++++- drivers/leds/led-core.c | 6 +++--- include/linux/leds.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 06b97fd49ad9..83e512df47dc 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -25,6 +25,8 @@ 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) { @@ -57,7 +59,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: @@ -549,6 +550,8 @@ 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 @@ -667,12 +670,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); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 001c290bc07b..f6c46d2e5276 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -273,7 +273,7 @@ void led_blink_set_nosleep(struct led_classdev *led_cdev, unsigned long delay_on led_cdev->delayed_delay_on = delay_on; led_cdev->delayed_delay_off = delay_off; set_bit(LED_SET_BLINK, &led_cdev->work_flags); - schedule_work(&led_cdev->set_brightness_work); + queue_work(led_cdev->wq, &led_cdev->set_brightness_work); return; } @@ -304,7 +304,7 @@ void led_set_brightness(struct led_classdev *led_cdev, unsigned int brightness) */ if (!brightness) { set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags); - schedule_work(&led_cdev->set_brightness_work); + queue_work(led_cdev->wq, &led_cdev->set_brightness_work); } else { set_bit(LED_BLINK_BRIGHTNESS_CHANGE, &led_cdev->work_flags); @@ -340,7 +340,7 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value) set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags); } - schedule_work(&led_cdev->set_brightness_work); + queue_work(led_cdev->wq, &led_cdev->set_brightness_work); } EXPORT_SYMBOL_GPL(led_set_brightness_nopm); diff --git a/include/linux/leds.h b/include/linux/leds.h index e5968c3ed4ae..9f34b9facaad 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -171,6 +171,7 @@ struct led_classdev { int new_blink_brightness; void (*flash_resume)(struct led_classdev *led_cdev); + struct workqueue_struct *wq; /* LED workqueue */ struct work_struct set_brightness_work; int delayed_set_value; unsigned long delayed_delay_on; From 02f58f97419c828f58e30f24f54395ac9be159c0 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Thu, 31 Oct 2024 17:30:30 +0100 Subject: [PATCH 41/46] leds: max5970: Fix unreleased fwnode_handle in probe function An object initialized via device_get_named_child_node() requires calls to fwnode_handle_put() when it is no longer required to avoid leaking memory. Add the automatic cleanup facility for 'led_node' to ensure that fwnode_handle_put() is called in all execution paths. Fixes: 736214b4b02a ("leds: max5970: Add support for max5970") Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20241031-max5970-of_node_put-v2-1-0ffe1f1d3bc9@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-max5970.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-max5970.c b/drivers/leds/leds-max5970.c index 56a584311581..285074c53b23 100644 --- a/drivers/leds/leds-max5970.c +++ b/drivers/leds/leds-max5970.c @@ -45,7 +45,7 @@ static int max5970_led_set_brightness(struct led_classdev *cdev, static int max5970_led_probe(struct platform_device *pdev) { - struct fwnode_handle *led_node, *child; + struct fwnode_handle *child; struct device *dev = &pdev->dev; struct regmap *regmap; struct max5970_led *ddata; @@ -55,7 +55,8 @@ static int max5970_led_probe(struct platform_device *pdev) if (!regmap) return -ENODEV; - led_node = device_get_named_child_node(dev->parent, "leds"); + struct fwnode_handle *led_node __free(fwnode_handle) = + device_get_named_child_node(dev->parent, "leds"); if (!led_node) return -ENODEV; From 95c65546f03f888481eda98b499947252e1f3b20 Mon Sep 17 00:00:00 2001 From: Raymond Hackley Date: Sun, 3 Nov 2024 08:35:16 +0000 Subject: [PATCH 42/46] leds: ktd2692: Set missing timing properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit props.timing is not set after commit b5a8c50e5c18 ("leds: ktd2692: Convert to use ExpressWire library"). Set it with ktd2692_timing. Fixes: b5a8c50e5c18 ("leds: ktd2692: Convert to use ExpressWire library") Signed-off-by: Raymond Hackley Acked-by: Duje Mihanović Link: https://lore.kernel.org/r/20241103083505.49648-1-raymondhackley@protonmail.com Signed-off-by: Lee Jones --- drivers/leds/flash/leds-ktd2692.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/flash/leds-ktd2692.c b/drivers/leds/flash/leds-ktd2692.c index 2e42f845df28..743830a10f99 100644 --- a/drivers/leds/flash/leds-ktd2692.c +++ b/drivers/leds/flash/leds-ktd2692.c @@ -292,6 +292,7 @@ static int ktd2692_probe(struct platform_device *pdev) fled_cdev = &led->fled_cdev; led_cdev = &fled_cdev->led_cdev; + led->props.timing = ktd2692_timing; ret = ktd2692_parse_dt(led, &pdev->dev, &led_cfg); if (ret) From 4ca7cd938725a4050dcd62ae9472e931d603118d Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Sun, 3 Nov 2024 21:35:27 +0530 Subject: [PATCH 43/46] leds: class: Protect brightness_show() with led_cdev->led_access mutex There is NULL pointer issue observed if from Process A where hid device being added which results in adding a led_cdev addition and later a another call to access of led_cdev attribute from Process B can result in NULL pointer issue. Use mutex led_cdev->led_access to protect access to led->cdev and its attribute inside brightness_show() and max_brightness_show() and also update the comment for mutex that it should be used to protect the led class device fields. Process A Process B kthread+0x114 worker_thread+0x244 process_scheduled_works+0x248 uhid_device_add_worker+0x24 hid_add_device+0x120 device_add+0x268 bus_probe_device+0x94 device_initial_probe+0x14 __device_attach+0xfc bus_for_each_drv+0x10c __device_attach_driver+0x14c driver_probe_device+0x3c __driver_probe_device+0xa0 really_probe+0x190 hid_device_probe+0x130 ps_probe+0x990 ps_led_register+0x94 devm_led_classdev_register_ext+0x58 led_classdev_register_ext+0x1f8 device_create_with_groups+0x48 device_create_groups_vargs+0xc8 device_add+0x244 kobject_uevent+0x14 kobject_uevent_env[jt]+0x224 mutex_unlock[jt]+0xc4 __mutex_unlock_slowpath+0xd4 wake_up_q+0x70 try_to_wake_up[jt]+0x48c preempt_schedule_common+0x28 __schedule+0x628 __switch_to+0x174 el0t_64_sync+0x1a8/0x1ac el0t_64_sync_handler+0x68/0xbc el0_svc+0x38/0x68 do_el0_svc+0x1c/0x28 el0_svc_common+0x80/0xe0 invoke_syscall+0x58/0x114 __arm64_sys_read+0x1c/0x2c ksys_read+0x78/0xe8 vfs_read+0x1e0/0x2c8 kernfs_fop_read_iter+0x68/0x1b4 seq_read_iter+0x158/0x4ec kernfs_seq_show+0x44/0x54 sysfs_kf_seq_show+0xb4/0x130 dev_attr_show+0x38/0x74 brightness_show+0x20/0x4c dualshock4_led_get_brightness+0xc/0x74 [ 3313.874295][ T4013] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000060 [ 3313.874301][ T4013] Mem abort info: [ 3313.874303][ T4013] ESR = 0x0000000096000006 [ 3313.874305][ T4013] EC = 0x25: DABT (current EL), IL = 32 bits [ 3313.874307][ T4013] SET = 0, FnV = 0 [ 3313.874309][ T4013] EA = 0, S1PTW = 0 [ 3313.874311][ T4013] FSC = 0x06: level 2 translation fault [ 3313.874313][ T4013] Data abort info: [ 3313.874314][ T4013] ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000 [ 3313.874316][ T4013] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 [ 3313.874318][ T4013] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [ 3313.874320][ T4013] user pgtable: 4k pages, 39-bit VAs, pgdp=00000008f2b0a000 .. [ 3313.874332][ T4013] Dumping ftrace buffer: [ 3313.874334][ T4013] (ftrace buffer empty) .. .. [ dd3313.874639][ T4013] CPU: 6 PID: 4013 Comm: InputReader [ 3313.874648][ T4013] pc : dualshock4_led_get_brightness+0xc/0x74 [ 3313.874653][ T4013] lr : led_update_brightness+0x38/0x60 [ 3313.874656][ T4013] sp : ffffffc0b910bbd0 .. .. [ 3313.874685][ T4013] Call trace: [ 3313.874687][ T4013] dualshock4_led_get_brightness+0xc/0x74 [ 3313.874690][ T4013] brightness_show+0x20/0x4c [ 3313.874692][ T4013] dev_attr_show+0x38/0x74 [ 3313.874696][ T4013] sysfs_kf_seq_show+0xb4/0x130 [ 3313.874700][ T4013] kernfs_seq_show+0x44/0x54 [ 3313.874703][ T4013] seq_read_iter+0x158/0x4ec [ 3313.874705][ T4013] kernfs_fop_read_iter+0x68/0x1b4 [ 3313.874708][ T4013] vfs_read+0x1e0/0x2c8 [ 3313.874711][ T4013] ksys_read+0x78/0xe8 [ 3313.874714][ T4013] __arm64_sys_read+0x1c/0x2c [ 3313.874718][ T4013] invoke_syscall+0x58/0x114 [ 3313.874721][ T4013] el0_svc_common+0x80/0xe0 [ 3313.874724][ T4013] do_el0_svc+0x1c/0x28 [ 3313.874727][ T4013] el0_svc+0x38/0x68 [ 3313.874730][ T4013] el0t_64_sync_handler+0x68/0xbc [ 3313.874732][ T4013] el0t_64_sync+0x1a8/0x1ac Signed-off-by: Mukesh Ojha Reviewed-by: Anish Kumar Link: https://lore.kernel.org/r/20241103160527.82487-1-quic_mojha@quicinc.com Signed-off-by: Lee Jones --- drivers/leds/led-class.c | 14 +++++++++++--- include/linux/leds.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 83e512df47dc..2a04ac61574d 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -31,11 +31,14 @@ 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, @@ -71,8 +74,13 @@ 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; - return sprintf(buf, "%u\n", led_cdev->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", max_brightness); } static DEVICE_ATTR_RO(max_brightness); diff --git a/include/linux/leds.h b/include/linux/leds.h index 9f34b9facaad..98f9719c924c 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -239,7 +239,7 @@ struct led_classdev { struct kernfs_node *brightness_hw_changed_kn; #endif - /* Ensures consistent access to the LED Flash Class device */ + /* Ensures consistent access to the LED class device */ struct mutex led_access; }; From 44e04fb8d69fa7fa4ec9a20762834eab1e7945af Mon Sep 17 00:00:00 2001 From: George Stark Date: Tue, 5 Nov 2024 21:50:05 +0300 Subject: [PATCH 44/46] dt-bindings: leds: pwm: Add default-brightness property Optional default-brightness property specifies brightness value to be used if default LED state is on. Signed-off-by: George Stark Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20241105185006.1380166-2-gnstark@salutedevices.com Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/leds/leds-pwm.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.yaml b/Documentation/devicetree/bindings/leds/leds-pwm.yaml index 113b7c218303..61b97e8bc36d 100644 --- a/Documentation/devicetree/bindings/leds/leds-pwm.yaml +++ b/Documentation/devicetree/bindings/leds/leds-pwm.yaml @@ -34,6 +34,12 @@ patternProperties: Maximum brightness possible for the LED $ref: /schemas/types.yaml#/definitions/uint32 + default-brightness: + description: + Brightness to be set if LED's default state is on. Used only during + initialization. If the option is not set then max brightness is used. + $ref: /schemas/types.yaml#/definitions/uint32 + required: - pwms - max-brightness From 8cb08101835d98fd69cfa2a2b06146eddc057df6 Mon Sep 17 00:00:00 2001 From: George Stark Date: Tue, 5 Nov 2024 21:50:06 +0300 Subject: [PATCH 45/46] leds: pwm: Add optional DT property default-brightness When probing if default LED state is on then default brightness will be applied instead of max brightness. Signed-off-by: George Stark Link: https://lore.kernel.org/r/20241105185006.1380166-3-gnstark@salutedevices.com Signed-off-by: Lee Jones --- drivers/leds/leds-pwm.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 34a03ef82007..c73134e7b951 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -62,6 +62,20 @@ static int led_pwm_set(struct led_classdev *led_cdev, return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate); } +static int led_pwm_default_brightness_get(struct fwnode_handle *fwnode, + int max_brightness) +{ + unsigned int default_brightness; + int ret; + + ret = fwnode_property_read_u32(fwnode, "default-brightness", + &default_brightness); + if (ret < 0 || default_brightness > max_brightness) + default_brightness = max_brightness; + + return default_brightness; +} + __attribute__((nonnull)) static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, struct led_pwm *led, struct fwnode_handle *fwnode) @@ -103,7 +117,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, /* set brightness */ switch (led->default_state) { case LEDS_DEFSTATE_ON: - led_data->cdev.brightness = led->max_brightness; + led_data->cdev.brightness = + led_pwm_default_brightness_get(fwnode, led->max_brightness); break; case LEDS_DEFSTATE_KEEP: { From e8501858035b1f95468da525e7357c8c33811b88 Mon Sep 17 00:00:00 2001 From: Zhu Jun Date: Sun, 10 Nov 2024 22:58:09 -0800 Subject: [PATCH 46/46] leds: ss4200: Fix the wrong format specifier for 'blinking' The format specifier of "signed int" in sprintf() should be "%d", not "%u". Signed-off-by: Zhu Jun Link: https://lore.kernel.org/r/20241111065809.3814-1-zhujun2@cmss.chinamobile.com Signed-off-by: Lee Jones --- drivers/leds/leds-ss4200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index 2ef9fc7371bd..f24ca75c7cb1 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c @@ -451,7 +451,7 @@ static ssize_t blink_show(struct device *dev, int blinking = 0; if (nasgpio_led_get_attr(led, GPO_BLINK)) blinking = 1; - return sprintf(buf, "%u\n", blinking); + return sprintf(buf, "%d\n", blinking); } static ssize_t blink_store(struct device *dev,