aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorSimon Guinot <simon.guinot@sequanux.org>2013-03-19 14:07:29 -0400
committerBryan Wu <cooloney@gmail.com>2013-04-01 14:04:52 -0400
commit3de1929ba61df87a0561c4f1fb7161c401fe3d04 (patch)
tree92d07b007a17379e26fc1d77851a260ea537b519 /drivers/leds
parentc971ff185f6443e834686f140ba6d6e341ced600 (diff)
leds: leds-ns2: fix oops at module removal
This patch fixes a regression introduced by commit 72052fcc10 ("leds: leds-ns2: add device tree binding"). When the driver is initialized with device tree data, platform_data pointer is NULL. This causes a kernel oops at removal. To fix this bug, num_leds is moved into driver_data and platform_data is not longer used from ns2_led_remove(). Signed-off-by: Simon Guinot <simon.guinot@sequanux.org> Signed-off-by: Bryan Wu <cooloney@gmail.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/leds-ns2.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index e02b3136273f..70137b1eecf5 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -308,10 +308,21 @@ static const struct of_device_id of_ns2_leds_match[] = {
308}; 308};
309#endif /* CONFIG_OF_GPIO */ 309#endif /* CONFIG_OF_GPIO */
310 310
311struct ns2_led_priv {
312 int num_leds;
313 struct ns2_led_data leds_data[];
314};
315
316static inline int sizeof_ns2_led_priv(int num_leds)
317{
318 return sizeof(struct ns2_led_priv) +
319 (sizeof(struct ns2_led_data) * num_leds);
320}
321
311static int ns2_led_probe(struct platform_device *pdev) 322static int ns2_led_probe(struct platform_device *pdev)
312{ 323{
313 struct ns2_led_platform_data *pdata = pdev->dev.platform_data; 324 struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
314 struct ns2_led_data *leds_data; 325 struct ns2_led_priv *priv;
315 int i; 326 int i;
316 int ret; 327 int ret;
317 328
@@ -332,21 +343,23 @@ static int ns2_led_probe(struct platform_device *pdev)
332 return -EINVAL; 343 return -EINVAL;
333#endif /* CONFIG_OF_GPIO */ 344#endif /* CONFIG_OF_GPIO */
334 345
335 leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) * 346 priv = devm_kzalloc(&pdev->dev,
336 pdata->num_leds, GFP_KERNEL); 347 sizeof_ns2_led_priv(pdata->num_leds), GFP_KERNEL);
337 if (!leds_data) 348 if (!priv)
338 return -ENOMEM; 349 return -ENOMEM;
350 priv->num_leds = pdata->num_leds;
339 351
340 for (i = 0; i < pdata->num_leds; i++) { 352 for (i = 0; i < priv->num_leds; i++) {
341 ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]); 353 ret = create_ns2_led(pdev, &priv->leds_data[i],
354 &pdata->leds[i]);
342 if (ret < 0) { 355 if (ret < 0) {
343 for (i = i - 1; i >= 0; i--) 356 for (i = i - 1; i >= 0; i--)
344 delete_ns2_led(&leds_data[i]); 357 delete_ns2_led(&priv->leds_data[i]);
345 return ret; 358 return ret;
346 } 359 }
347 } 360 }
348 361
349 platform_set_drvdata(pdev, leds_data); 362 platform_set_drvdata(pdev, priv);
350 363
351 return 0; 364 return 0;
352} 365}
@@ -354,13 +367,12 @@ static int ns2_led_probe(struct platform_device *pdev)
354static int ns2_led_remove(struct platform_device *pdev) 367static int ns2_led_remove(struct platform_device *pdev)
355{ 368{
356 int i; 369 int i;
357 struct ns2_led_platform_data *pdata = pdev->dev.platform_data; 370 struct ns2_led_priv *priv;
358 struct ns2_led_data *leds_data;
359 371
360 leds_data = platform_get_drvdata(pdev); 372 priv = platform_get_drvdata(pdev);
361 373
362 for (i = 0; i < pdata->num_leds; i++) 374 for (i = 0; i < priv->num_leds; i++)
363 delete_ns2_led(&leds_data[i]); 375 delete_ns2_led(&priv->leds_data[i]);
364 376
365 platform_set_drvdata(pdev, NULL); 377 platform_set_drvdata(pdev, NULL);
366 378