pdev->dev.platform_data should not be overwritten by a driver. This patch fixes this issue by not using platform_get_pdata to get pdata. The DT routine can then simply return a pdata struct with those information. Without this patch the platform_data may be freed twice, by devres and the driver framework. Reported-by: Ingo Flaschberger <ingo.flaschberger@xxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Markus Pargmann <mpa@xxxxxxxxxxxxxx> --- Hi, Could you please try this patch? This essentially does not store anything to platform_data anymore so it should hopefully fix your issue. Best Regards, Markus drivers/w1/masters/w1-gpio.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index b99a932ad901..63e7b1d2785f 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -75,15 +75,18 @@ static struct of_device_id w1_gpio_dt_ids[] = { MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); #endif -static int w1_gpio_probe_dt(struct platform_device *pdev) +static struct w1_gpio_platform_data *w1_gpio_probe_dt(struct platform_device *pdev) { struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *np = pdev->dev.of_node; int gpio; + if (pdata) + return pdata; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) - return -ENOMEM; + return ERR_PTR(-ENOMEM); if (of_get_property(np, "linux,open-drain", NULL)) pdata->is_open_drain = 1; @@ -95,19 +98,17 @@ static int w1_gpio_probe_dt(struct platform_device *pdev) "Failed to parse gpio property for data pin (%d)\n", gpio); - return gpio; + return ERR_PTR(gpio); } pdata->pin = gpio; gpio = of_get_gpio(np, 1); if (gpio == -EPROBE_DEFER) - return gpio; + return ERR_PTR(gpio); /* ignore other errors as the pullup gpio is optional */ pdata->ext_pullup_enable_pin = gpio; - pdev->dev.platform_data = pdata; - - return 0; + return pdata; } static int w1_gpio_probe(struct platform_device *pdev) @@ -116,17 +117,16 @@ static int w1_gpio_probe(struct platform_device *pdev) struct w1_gpio_platform_data *pdata; int err; - if (of_have_populated_dt()) { - err = w1_gpio_probe_dt(pdev); - if (err < 0) - return err; - } - - pdata = dev_get_platdata(&pdev->dev); + if (of_have_populated_dt()) + pdata = w1_gpio_probe_dt(pdev); + else + pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "No configuration data\n"); - return -ENXIO; + if (IS_ERR_OR_NULL(pdata)) { + dev_err(&pdev->dev, "No configuration data or configuration failed\n"); + if (!pdata) + return -ENXIO; + return PTR_ERR(pdata); } master = devm_kzalloc(&pdev->dev, sizeof(struct w1_bus_master), @@ -185,7 +185,7 @@ static int w1_gpio_probe(struct platform_device *pdev) static int w1_gpio_remove(struct platform_device *pdev) { struct w1_bus_master *master = platform_get_drvdata(pdev); - struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct w1_gpio_platform_data *pdata = master->data; if (pdata->enable_external_pullup) pdata->enable_external_pullup(0); @@ -202,7 +202,8 @@ static int w1_gpio_remove(struct platform_device *pdev) static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state) { - struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct w1_bus_master *master = platform_get_drvdata(pdev); + struct w1_gpio_platform_data *pdata = master->data; if (pdata->enable_external_pullup) pdata->enable_external_pullup(0); @@ -212,7 +213,8 @@ static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state) static int w1_gpio_resume(struct platform_device *pdev) { - struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct w1_bus_master *master = platform_get_drvdata(pdev); + struct w1_gpio_platform_data *pdata = master->data; if (pdata->enable_external_pullup) pdata->enable_external_pullup(1); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html