Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds:lp55xx: use the private data instead of updating I2C device platform data

Currently, lp55xx_of_populate_pdata() allocates lp55xx_platform_data if
it's null. And it parses the DT and copies values into the
'client->dev.platform_data'. This may have architectural issue.
Platform data is configurable through the DT or I2C board info inside the
platform area. However, lp55xx common driver changes this configuration
when it is loaded. So 'client->dev.platform_data' is not null anymore.
Eventually, the driver initialization is not identical when it's unloaded
and loaded again.
The lp55xx common driver should use the private data, 'lp55xx_chip->pdata'
instead of changing the original platform data.

So, lp55xx_of_populate_pdata() is modified as follows.
* Do not update 'dev->platform_data'. Return the pointer of new allocated
lp55xx_platform_data. Then the driver points it to private data,
'lp55xx_chip->pdata'.
* Each lp55xx driver checks the pointer and handles an error case.

Then, original platform data configuration will be kept regardless of
loading or unloading the driver.
The driver allocates the memory and copies them from the DT if it's NULL.
After the driver is loaded again, 'client->dev.platform_data' is same as
initial load, so the driver is initialized identically.

Cc: Toshi Kikuchi <toshik@chromium.org>
Cc: linux-leds@vger.kernel.org
Signed-off-by: Milo Kim <milo.kim@ti.com>
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>

authored by

Milo Kim and committed by
Jacek Anaszewski
ed133352 991a3f61

+28 -33
+5 -6
drivers/leds/leds-lp5521.c
··· 514 514 int ret; 515 515 struct lp55xx_chip *chip; 516 516 struct lp55xx_led *led; 517 - struct lp55xx_platform_data *pdata; 517 + struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 518 518 struct device_node *np = client->dev.of_node; 519 519 520 - if (!dev_get_platdata(&client->dev)) { 520 + if (!pdata) { 521 521 if (np) { 522 - ret = lp55xx_of_populate_pdata(&client->dev, np); 523 - if (ret < 0) 524 - return ret; 522 + pdata = lp55xx_of_populate_pdata(&client->dev, np); 523 + if (IS_ERR(pdata)) 524 + return PTR_ERR(pdata); 525 525 } else { 526 526 dev_err(&client->dev, "no platform data\n"); 527 527 return -EINVAL; 528 528 } 529 529 } 530 - pdata = dev_get_platdata(&client->dev); 531 530 532 531 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 533 532 if (!chip)
+5 -6
drivers/leds/leds-lp5523.c
··· 880 880 int ret; 881 881 struct lp55xx_chip *chip; 882 882 struct lp55xx_led *led; 883 - struct lp55xx_platform_data *pdata; 883 + struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 884 884 struct device_node *np = client->dev.of_node; 885 885 886 - if (!dev_get_platdata(&client->dev)) { 886 + if (!pdata) { 887 887 if (np) { 888 - ret = lp55xx_of_populate_pdata(&client->dev, np); 889 - if (ret < 0) 890 - return ret; 888 + pdata = lp55xx_of_populate_pdata(&client->dev, np); 889 + if (IS_ERR(pdata)) 890 + return PTR_ERR(pdata); 891 891 } else { 892 892 dev_err(&client->dev, "no platform data\n"); 893 893 return -EINVAL; 894 894 } 895 895 } 896 - pdata = dev_get_platdata(&client->dev); 897 896 898 897 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 899 898 if (!chip)
+5 -6
drivers/leds/leds-lp5562.c
··· 515 515 int ret; 516 516 struct lp55xx_chip *chip; 517 517 struct lp55xx_led *led; 518 - struct lp55xx_platform_data *pdata; 518 + struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 519 519 struct device_node *np = client->dev.of_node; 520 520 521 - if (!dev_get_platdata(&client->dev)) { 521 + if (!pdata) { 522 522 if (np) { 523 - ret = lp55xx_of_populate_pdata(&client->dev, np); 524 - if (ret < 0) 525 - return ret; 523 + pdata = lp55xx_of_populate_pdata(&client->dev, np); 524 + if (IS_ERR(pdata)) 525 + return PTR_ERR(pdata); 526 526 } else { 527 527 dev_err(&client->dev, "no platform data\n"); 528 528 return -EINVAL; 529 529 } 530 530 } 531 - pdata = dev_get_platdata(&client->dev); 532 531 533 532 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 534 533 if (!chip)
+6 -7
drivers/leds/leds-lp55xx-common.c
··· 543 543 } 544 544 EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs); 545 545 546 - int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np) 546 + struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev, 547 + struct device_node *np) 547 548 { 548 549 struct device_node *child; 549 550 struct lp55xx_platform_data *pdata; ··· 554 553 555 554 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 556 555 if (!pdata) 557 - return -ENOMEM; 556 + return ERR_PTR(-ENOMEM); 558 557 559 558 num_channels = of_get_child_count(np); 560 559 if (num_channels == 0) { 561 560 dev_err(dev, "no LED channels\n"); 562 - return -EINVAL; 561 + return ERR_PTR(-EINVAL); 563 562 } 564 563 565 564 cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL); 566 565 if (!cfg) 567 - return -ENOMEM; 566 + return ERR_PTR(-ENOMEM); 568 567 569 568 pdata->led_config = &cfg[0]; 570 569 pdata->num_channels = num_channels; ··· 589 588 /* LP8501 specific */ 590 589 of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel); 591 590 592 - dev->platform_data = pdata; 593 - 594 - return 0; 591 + return pdata; 595 592 } 596 593 EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata); 597 594
+2 -2
drivers/leds/leds-lp55xx-common.h
··· 202 202 extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip); 203 203 204 204 /* common device tree population function */ 205 - extern int lp55xx_of_populate_pdata(struct device *dev, 206 - struct device_node *np); 205 + extern struct lp55xx_platform_data 206 + *lp55xx_of_populate_pdata(struct device *dev, struct device_node *np); 207 207 208 208 #endif /* _LEDS_LP55XX_COMMON_H */
+5 -6
drivers/leds/leds-lp8501.c
··· 308 308 int ret; 309 309 struct lp55xx_chip *chip; 310 310 struct lp55xx_led *led; 311 - struct lp55xx_platform_data *pdata; 311 + struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 312 312 struct device_node *np = client->dev.of_node; 313 313 314 - if (!dev_get_platdata(&client->dev)) { 314 + if (!pdata) { 315 315 if (np) { 316 - ret = lp55xx_of_populate_pdata(&client->dev, np); 317 - if (ret < 0) 318 - return ret; 316 + pdata = lp55xx_of_populate_pdata(&client->dev, np); 317 + if (IS_ERR(pdata)) 318 + return PTR_ERR(pdata); 319 319 } else { 320 320 dev_err(&client->dev, "no platform data\n"); 321 321 return -EINVAL; 322 322 } 323 323 } 324 - pdata = dev_get_platdata(&client->dev); 325 324 326 325 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 327 326 if (!chip)