Commit 3de1929ba61df87a0561c4f1fb7161c401fe3d04

Authored by Simon Guinot
Committed by Bryan Wu
1 parent c971ff185f

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>

Showing 1 changed file with 25 additions and 13 deletions Side-by-side Diff

drivers/leds/leds-ns2.c
... ... @@ -308,10 +308,21 @@
308 308 };
309 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 322 static int ns2_led_probe(struct platform_device *pdev)
312 323 {
313 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 326 int i;
316 327 int ret;
317 328  
318 329  
319 330  
320 331  
321 332  
... ... @@ -332,21 +343,23 @@
332 343 return -EINVAL;
333 344 #endif /* CONFIG_OF_GPIO */
334 345  
335   - leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) *
336   - pdata->num_leds, GFP_KERNEL);
337   - if (!leds_data)
  346 + priv = devm_kzalloc(&pdev->dev,
  347 + sizeof_ns2_led_priv(pdata->num_leds), GFP_KERNEL);
  348 + if (!priv)
338 349 return -ENOMEM;
  350 + priv->num_leds = pdata->num_leds;
339 351  
340   - for (i = 0; i < pdata->num_leds; i++) {
341   - ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]);
  352 + for (i = 0; i < priv->num_leds; i++) {
  353 + ret = create_ns2_led(pdev, &priv->leds_data[i],
  354 + &pdata->leds[i]);
342 355 if (ret < 0) {
343 356 for (i = i - 1; i >= 0; i--)
344   - delete_ns2_led(&leds_data[i]);
  357 + delete_ns2_led(&priv->leds_data[i]);
345 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 364 return 0;
352 365 }
353 366  
354 367  
... ... @@ -354,13 +367,12 @@
354 367 static int ns2_led_remove(struct platform_device *pdev)
355 368 {
356 369 int i;
357   - struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
358   - struct ns2_led_data *leds_data;
  370 + struct ns2_led_priv *priv;
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++)
363   - delete_ns2_led(&leds_data[i]);
  374 + for (i = 0; i < priv->num_leds; i++)
  375 + delete_ns2_led(&priv->leds_data[i]);
364 376  
365 377 platform_set_drvdata(pdev, NULL);
366 378