Commit e52fec7c authored by Federico Vaga's avatar Federico Vaga

sw:drv: do not use devm_*

It looks like there is a bug somewhere that make the system panic
on resource releasing. I can't provide any evidence that devm_* is
related to the issue, but removing it seems to solve the problem
(or at least is not as frequent as before: I can load/unload 100 times
without problems).

The problem was mitigated also by introducing delays (mdelay/printk)
in the fcl/gpio remove functions.

My guess is that MFD removal and devres clean up conflicts at some
point. MFD uses platform_unregister() which does resource_release(),
and because of devres, only after that we will release all resources
that we took on probe(). The flow does not sound right, we should
release resources we took **before** platform releases/remove the
resource from the system (not viceversa).
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 392c01eb
...@@ -519,7 +519,7 @@ static int gn412x_fcl_probe(struct platform_device *pdev) ...@@ -519,7 +519,7 @@ static int gn412x_fcl_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
int err; int err;
gn412x = devm_kzalloc(&pdev->dev, sizeof(*gn412x), GFP_KERNEL); gn412x = kzalloc(sizeof(*gn412x), GFP_KERNEL);
if (!gn412x) if (!gn412x)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, gn412x); platform_set_drvdata(pdev, gn412x);
...@@ -530,7 +530,7 @@ static int gn412x_fcl_probe(struct platform_device *pdev) ...@@ -530,7 +530,7 @@ static int gn412x_fcl_probe(struct platform_device *pdev)
err = -EINVAL; err = -EINVAL;
goto err_res_mem; goto err_res_mem;
} }
gn412x->mem = devm_ioremap(&pdev->dev, r->start, resource_size(r)); gn412x->mem = ioremap(r->start, resource_size(r));
if (!gn412x->mem) { if (!gn412x->mem) {
err = -EADDRNOTAVAIL; err = -EADDRNOTAVAIL;
goto err_map; goto err_map;
...@@ -558,10 +558,10 @@ err_fpga_reg: ...@@ -558,10 +558,10 @@ err_fpga_reg:
compat_fpga_mgr_free(gn412x->mgr); compat_fpga_mgr_free(gn412x->mgr);
err_fpga_create: err_fpga_create:
gn4124_dbg_exit(pdev); gn4124_dbg_exit(pdev);
devm_iounmap(&pdev->dev, gn412x->mem); iounmap(gn412x->mem);
err_map: err_map:
err_res_mem: err_res_mem:
devm_kfree(&pdev->dev, gn412x); kfree(gn412x);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
return err; return err;
...@@ -571,15 +571,19 @@ static int gn412x_fcl_remove(struct platform_device *pdev) ...@@ -571,15 +571,19 @@ static int gn412x_fcl_remove(struct platform_device *pdev)
{ {
struct gn412x_fcl_dev *gn412x = platform_get_drvdata(pdev); struct gn412x_fcl_dev *gn412x = platform_get_drvdata(pdev);
gn4124_dbg_exit(pdev);
if (!gn412x->mgr) if (!gn412x->mgr)
return -ENODEV; return -ENODEV;
compat_fpga_mgr_unregister(gn412x->mgr); compat_fpga_mgr_unregister(gn412x->mgr);
compat_fpga_mgr_free(gn412x->mgr); compat_fpga_mgr_free(gn412x->mgr);
gn4124_dbg_exit(pdev);
iounmap(gn412x->mem);
kfree(gn412x);
platform_set_drvdata(pdev, NULL);
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
return 0; return 0;
} }
......
...@@ -476,7 +476,7 @@ static int gn412x_gpio_probe(struct platform_device *pdev) ...@@ -476,7 +476,7 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
int err; int err;
gn412x = devm_kzalloc(&pdev->dev, sizeof(*gn412x), GFP_KERNEL); gn412x = kzalloc(sizeof(*gn412x), GFP_KERNEL);
if (!gn412x) if (!gn412x)
return -ENOMEM; return -ENOMEM;
...@@ -488,7 +488,7 @@ static int gn412x_gpio_probe(struct platform_device *pdev) ...@@ -488,7 +488,7 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
err = -EINVAL; err = -EINVAL;
goto err_res_mem; goto err_res_mem;
} }
gn412x->mem = devm_ioremap(&pdev->dev, r->start, resource_size(r)); gn412x->mem = ioremap(r->start, resource_size(r));
if (!gn412x->mem) { if (!gn412x->mem) {
err = -EADDRNOTAVAIL; err = -EADDRNOTAVAIL;
goto err_map; goto err_map;
...@@ -552,10 +552,10 @@ err_req: ...@@ -552,10 +552,10 @@ err_req:
err_add_irq: err_add_irq:
gpiochip_remove(&gn412x->gpiochip); gpiochip_remove(&gn412x->gpiochip);
err_add: err_add:
devm_iounmap(&pdev->dev, gn412x->mem); iounmap(gn412x->mem);
err_map: err_map:
err_res_mem: err_res_mem:
devm_kfree(&pdev->dev, gn412x); kfree(gn412x);
return err; return err;
} }
...@@ -563,6 +563,7 @@ static int gn412x_gpio_remove(struct platform_device *pdev) ...@@ -563,6 +563,7 @@ static int gn412x_gpio_remove(struct platform_device *pdev)
{ {
struct gn412x_gpio_dev *gn412x = platform_get_drvdata(pdev); struct gn412x_gpio_dev *gn412x = platform_get_drvdata(pdev);
gn412x_dbg_exit(gn412x); gn412x_dbg_exit(gn412x);
gn412x_gpio_int_cfg_disable(gn412x); gn412x_gpio_int_cfg_disable(gn412x);
...@@ -570,6 +571,8 @@ static int gn412x_gpio_remove(struct platform_device *pdev) ...@@ -570,6 +571,8 @@ static int gn412x_gpio_remove(struct platform_device *pdev)
free_irq(platform_get_irq(pdev, 0), gn412x); free_irq(platform_get_irq(pdev, 0), gn412x);
gn412x_gpio_irq_set_nested_thread_all(gn412x, false); gn412x_gpio_irq_set_nested_thread_all(gn412x, false);
gpiochip_remove(&gn412x->gpiochip); gpiochip_remove(&gn412x->gpiochip);
iounmap(gn412x->mem);
kfree(gn412x);
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
return 0; return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment