śr., 10 lip 2019 o 11:37 Phil Reid <preid@xxxxxxxxxxxxxxxxx> napisał(a): > > G'day Bartosz, > > One comment below > > On 10/07/2019 17:08, Bartosz Golaszewski wrote: > > From: Bartosz Golaszewski <bgolaszewski@xxxxxxxxxxxx> > > > > In commit 8764c4ca5049 ("gpio: em: use the managed version of > > gpiochip_add_data()") we implicitly altered the ordering of resource > > freeing: since gpiochip_remove() calls gpiochip_irqchip_remove() > > internally, we now can potentially use the irq_domain after it was > > destroyed in the remove() callback (as devm resources are freed after > > remove() has returned). > > > > Use devm_add_action() to keep the ordering right and entirely kill > > the remove() callback in the driver. > > > > Reported-by: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> > > Fixes: 8764c4ca5049 ("gpio: em: use the managed version of gpiochip_add_data()") > > Cc: stable@xxxxxxxxxxxxxxx > > Signed-off-by: Bartosz Golaszewski <bgolaszewski@xxxxxxxxxxxx> > > --- > > drivers/gpio/gpio-em.c | 35 +++++++++++++++++------------------ > > 1 file changed, 17 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c > > index b6af705a4e5f..c88028ac66f2 100644 > > --- a/drivers/gpio/gpio-em.c > > +++ b/drivers/gpio/gpio-em.c > > @@ -259,6 +259,13 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = { > > .xlate = irq_domain_xlate_twocell, > > }; > > > > +static void em_gio_irq_domain_remove(void *data) > > +{ > > + struct irq_domain *domain = data; > > + > > + irq_domain_remove(domain); > > +} > > + > > static int em_gio_probe(struct platform_device *pdev) > > { > > struct em_gio_priv *p; > > @@ -333,39 +340,32 @@ static int em_gio_probe(struct platform_device *pdev) > > return -ENXIO; > > } > > > > + ret = devm_add_action(&pdev->dev, > > + em_gio_irq_domain_remove, p->irq_domain); > > Could devm_add_action_or_reset be used? > Of course it could and it should. :) I'll resend tomorrow to not spam the mailing list. Thanks, Bart > > + if (ret) { > > + irq_domain_remove(p->irq_domain); > > + return ret; > > + } > > + > > if (devm_request_irq(&pdev->dev, irq[0]->start, > > em_gio_irq_handler, 0, name, p)) { > > dev_err(&pdev->dev, "failed to request low IRQ\n"); > > - ret = -ENOENT; > > - goto err1; > > + return -ENOENT; > > } > > > > if (devm_request_irq(&pdev->dev, irq[1]->start, > > em_gio_irq_handler, 0, name, p)) { > > dev_err(&pdev->dev, "failed to request high IRQ\n"); > > - ret = -ENOENT; > > - goto err1; > > + return -ENOENT; > > } > > > > ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p); > > if (ret) { > > dev_err(&pdev->dev, "failed to add GPIO controller\n"); > > - goto err1; > > + return ret; > > } > > > > return 0; > > - > > -err1: > > - irq_domain_remove(p->irq_domain); > > - return ret; > > -} > > - > > -static int em_gio_remove(struct platform_device *pdev) > > -{ > > - struct em_gio_priv *p = platform_get_drvdata(pdev); > > - > > - irq_domain_remove(p->irq_domain); > > - return 0; > > } > > > > static const struct of_device_id em_gio_dt_ids[] = { > > @@ -376,7 +376,6 @@ MODULE_DEVICE_TABLE(of, em_gio_dt_ids); > > > > static struct platform_driver em_gio_device_driver = { > > .probe = em_gio_probe, > > - .remove = em_gio_remove, > > .driver = { > > .name = "em_gio", > > .of_match_table = em_gio_dt_ids, > > > > > -- > Regards > Phil Reid >