mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 00:08:50 +00:00
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>
This commit is contained in:
parent
c971ff185f
commit
3de1929ba6
@ -308,10 +308,21 @@ static const struct of_device_id of_ns2_leds_match[] = {
|
|||||||
};
|
};
|
||||||
#endif /* CONFIG_OF_GPIO */
|
#endif /* CONFIG_OF_GPIO */
|
||||||
|
|
||||||
|
struct ns2_led_priv {
|
||||||
|
int num_leds;
|
||||||
|
struct ns2_led_data leds_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int sizeof_ns2_led_priv(int num_leds)
|
||||||
|
{
|
||||||
|
return sizeof(struct ns2_led_priv) +
|
||||||
|
(sizeof(struct ns2_led_data) * num_leds);
|
||||||
|
}
|
||||||
|
|
||||||
static int ns2_led_probe(struct platform_device *pdev)
|
static int ns2_led_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
|
struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
|
||||||
struct ns2_led_data *leds_data;
|
struct ns2_led_priv *priv;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -332,21 +343,23 @@ static int ns2_led_probe(struct platform_device *pdev)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
#endif /* CONFIG_OF_GPIO */
|
#endif /* CONFIG_OF_GPIO */
|
||||||
|
|
||||||
leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) *
|
priv = devm_kzalloc(&pdev->dev,
|
||||||
pdata->num_leds, GFP_KERNEL);
|
sizeof_ns2_led_priv(pdata->num_leds), GFP_KERNEL);
|
||||||
if (!leds_data)
|
if (!priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
priv->num_leds = pdata->num_leds;
|
||||||
|
|
||||||
for (i = 0; i < pdata->num_leds; i++) {
|
for (i = 0; i < priv->num_leds; i++) {
|
||||||
ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]);
|
ret = create_ns2_led(pdev, &priv->leds_data[i],
|
||||||
|
&pdata->leds[i]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
for (i = i - 1; i >= 0; i--)
|
for (i = i - 1; i >= 0; i--)
|
||||||
delete_ns2_led(&leds_data[i]);
|
delete_ns2_led(&priv->leds_data[i]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, leds_data);
|
platform_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -354,13 +367,12 @@ static int ns2_led_probe(struct platform_device *pdev)
|
|||||||
static int ns2_led_remove(struct platform_device *pdev)
|
static int ns2_led_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
|
struct ns2_led_priv *priv;
|
||||||
struct ns2_led_data *leds_data;
|
|
||||||
|
|
||||||
leds_data = platform_get_drvdata(pdev);
|
priv = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
for (i = 0; i < pdata->num_leds; i++)
|
for (i = 0; i < priv->num_leds; i++)
|
||||||
delete_ns2_led(&leds_data[i]);
|
delete_ns2_led(&priv->leds_data[i]);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user