diff options
author | Simon Guinot <simon.guinot@sequanux.org> | 2013-03-19 14:07:29 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@gmail.com> | 2013-04-01 14:04:52 -0400 |
commit | 3de1929ba61df87a0561c4f1fb7161c401fe3d04 (patch) | |
tree | 92d07b007a17379e26fc1d77851a260ea537b519 /drivers/leds/leds-ns2.c | |
parent | c971ff185f6443e834686f140ba6d6e341ced600 (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/leds-ns2.c')
-rw-r--r-- | drivers/leds/leds-ns2.c | 38 |
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 | ||
311 | struct ns2_led_priv { | ||
312 | int num_leds; | ||
313 | struct ns2_led_data leds_data[]; | ||
314 | }; | ||
315 | |||
316 | static 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 | |||
311 | static int ns2_led_probe(struct platform_device *pdev) | 322 | static 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) | |||
354 | static int ns2_led_remove(struct platform_device *pdev) | 367 | static 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 | ||