Message ID | 2ec3bb89-89db-48e8-b360-369545a2546f@mary.at.omicron.at (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Christian, Thanks for the patch. On Wed, Mar 5, 2014 at 3:55 PM, Christian Riesch <christian.riesch@omicron.at> wrote: > In commit 6892b41d9701283085b655c6086fb57a5d63fa47 > > Author: Lad, Prabhakar <prabhakar.csengg@gmail.com> > Date: Tue Jun 25 21:24:51 2013 +0530 > net: davinci: emac: Convert to devm_* api > > the call of request_irq is replaced by devm_request_irq and the call > of free_irq is removed. But since interrupts are requested in > emac_dev_open, doing ifconfig up/down on the board requests the > interrupts again each time, causing devm_request_irq to fail. > > This patch reverts said commit partially: It changes the driver back > to use request_irq instead of devm_request_irq, puts free_irq back in > place, but keeps the remaining changes of the original patch. > > Reported-by: Jon Ringle <jon@ringle.org> > Signed-off-by: Christian Riesch <christian.riesch@omicron.at> > Cc: Lad, Prabhakar <prabhakar.csengg@gmail.com> > Cc: <stable@vger.kernel.org> Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com> Regards, --Prabhakar lad
On Wednesday 05 March 2014 03:55 PM, Christian Riesch wrote: > In commit 6892b41d9701283085b655c6086fb57a5d63fa47 > > Author: Lad, Prabhakar <prabhakar.csengg@gmail.com> > Date: Tue Jun 25 21:24:51 2013 +0530 > net: davinci: emac: Convert to devm_* api > > the call of request_irq is replaced by devm_request_irq and the call > of free_irq is removed. But since interrupts are requested in > emac_dev_open, doing ifconfig up/down on the board requests the > interrupts again each time, causing devm_request_irq to fail. > > This patch reverts said commit partially: It changes the driver back > to use request_irq instead of devm_request_irq, puts free_irq back in > place, but keeps the remaining changes of the original patch. > > Reported-by: Jon Ringle <jon@ringle.org> > Signed-off-by: Christian Riesch <christian.riesch@omicron.at> > Cc: Lad, Prabhakar <prabhakar.csengg@gmail.com> > Cc: <stable@vger.kernel.org> Instead of moving back to request irq. can you move the devm interrupt request code from open to probe so that the issue is fixed, IRQ will be requested on module insert and IRQ will be free in module remove and there will not be any failures in devm request irq while repeating ifup/ifdown and also during module insert/remove. Regards Mugunthan V N
--On March 06, 2014 13:57 +0530 Mugunthan V N <mugunthanvnm@ti.com> wrote: > On Wednesday 05 March 2014 03:55 PM, Christian Riesch wrote: >> In commit 6892b41d9701283085b655c6086fb57a5d63fa47 >> >> Author: Lad, Prabhakar <prabhakar.csengg@gmail.com> >> Date: Tue Jun 25 21:24:51 2013 +0530 >> net: davinci: emac: Convert to devm_* api >> >> the call of request_irq is replaced by devm_request_irq and the call >> of free_irq is removed. But since interrupts are requested in >> emac_dev_open, doing ifconfig up/down on the board requests the >> interrupts again each time, causing devm_request_irq to fail. >> >> This patch reverts said commit partially: It changes the driver back >> to use request_irq instead of devm_request_irq, puts free_irq back in >> place, but keeps the remaining changes of the original patch. >> >> Reported-by: Jon Ringle <jon@ringle.org> >> Signed-off-by: Christian Riesch <christian.riesch@omicron.at> >> Cc: Lad, Prabhakar <prabhakar.csengg@gmail.com> >> Cc: <stable@vger.kernel.org> > > Instead of moving back to request irq. can you move the devm interrupt > request code from open to probe so that the issue is fixed, IRQ will be > requested on module insert and IRQ will be free in module remove and > there will not be any failures in devm request irq while repeating > ifup/ifdown and also during module insert/remove. This is exactly what I tried first, please have a look at my first patch and the discussion [1]. Florian Fainelli asked me to revert Prabhakar's patch instead to bring back the "usual situation", "just in case some uncontrolled interrupt bit triggers an interrupt while the interface is down for instance..." Florian Fainelli, Mugunthan VN, which solution is better? Regards, Christian [1] http://marc.info/?t=139394310200001&r=1&w=2 > > Regards > Mugunthan V N > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source@linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
2014-03-06 0:51 GMT-08:00 Christian Riesch <christian.riesch@omicron.at>: > --On March 06, 2014 13:57 +0530 Mugunthan V N <mugunthanvnm@ti.com> wrote: >> >> On Wednesday 05 March 2014 03:55 PM, Christian Riesch wrote: >>> >>> In commit 6892b41d9701283085b655c6086fb57a5d63fa47 >>> >>> Author: Lad, Prabhakar <prabhakar.csengg@gmail.com> >>> Date: Tue Jun 25 21:24:51 2013 +0530 >>> net: davinci: emac: Convert to devm_* api >>> >>> the call of request_irq is replaced by devm_request_irq and the call >>> of free_irq is removed. But since interrupts are requested in >>> emac_dev_open, doing ifconfig up/down on the board requests the >>> interrupts again each time, causing devm_request_irq to fail. >>> >>> This patch reverts said commit partially: It changes the driver back >>> to use request_irq instead of devm_request_irq, puts free_irq back in >>> place, but keeps the remaining changes of the original patch. >>> >>> Reported-by: Jon Ringle <jon@ringle.org> >>> Signed-off-by: Christian Riesch <christian.riesch@omicron.at> >>> Cc: Lad, Prabhakar <prabhakar.csengg@gmail.com> >>> Cc: <stable@vger.kernel.org> >> >> >> Instead of moving back to request irq. can you move the devm interrupt >> request code from open to probe so that the issue is fixed, IRQ will be >> requested on module insert and IRQ will be free in module remove and >> there will not be any failures in devm request irq while repeating >> ifup/ifdown and also during module insert/remove. > > > This is exactly what I tried first, please have a look at my first patch and > the discussion [1]. Florian Fainelli asked me to revert Prabhakar's patch > instead to bring back the "usual situation", "just in case some uncontrolled > interrupt bit triggers an interrupt while the interface is down for > instance..." > > Florian Fainelli, Mugunthan VN, which solution is better? I think the solution that does: - request_irq() in ndo_open() - free_irq() in ndo_stop() is the safest option because it ensure that the various interrupt lines are masked at the interrupt controller level, and not just at Ethernet MAC level, and as such gives you more control over what the hardware does. It also mimics what 99% of the Ethernet drivers do, which will help identifying those common patterns programmatically.
From: Christian Riesch <christian.riesch@omicron.at> Date: Wed, 5 Mar 2014 11:25:28 +0100 > @@ -1641,7 +1640,15 @@ static int emac_dev_open(struct net_device *ndev) > > rollback: > > - dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); > + dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); > + > + for (q = k; k >= 0; k--) { > + for (m = i; m >= res->start; m--) > + free_irq(m, ndev); > + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); > + m = res->end; > + } This final assignment in the loop of 'm' is unused? The inner for() loop always started with "m = i;"
On Thursday, March 6, 2014, David Miller <davem@davemloft.net> wrote: > From: Christian Riesch <christian.riesch@omicron.at <javascript:;>> > Date: Wed, 5 Mar 2014 11:25:28 +0100 > > > @@ -1641,7 +1640,15 @@ static int emac_dev_open(struct net_device *ndev) > > > > rollback: > > > > - dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); > > + dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); > > + > > + for (q = k; k >= 0; k--) { > > + for (m = i; m >= res->start; m--) > > + free_irq(m, ndev); > > + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, > k-1); > > + m = res->end; > > + } > > This final assignment in the loop of 'm' is unused? > > The inner for() loop always started with "m = i;" > > This should probably read i = res->end; I just took the old code, without thinking about it. Thanks for catching it. Christian
[Sent again, sorry for the HTML mail before.] --On March 06, 2014 16:57 -0500 David Miller <davem@davemloft.net> wrote: > From: Christian Riesch <christian.riesch@omicron.at> > Date: Wed, 5 Mar 2014 11:25:28 +0100 > >> @@ -1641,7 +1640,15 @@ static int emac_dev_open(struct net_device *ndev) >> >> rollback: >> >> - dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); >> + dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); >> + >> + for (q = k; k >= 0; k--) { >> + for (m = i; m >= res->start; m--) >> + free_irq(m, ndev); >> + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); >> + m = res->end; >> + } > > This final assignment in the loop of 'm' is unused? > > The inner for() loop always started with "m = i;" This should probably read i = res->end; I just took the old code without thinking about it. Thanks for catching it. Christian
Hi, --On March 06, 2014 16:57 -0500 David Miller <davem@davemloft.net> wrote: > From: Christian Riesch <christian.riesch@omicron.at> > Date: Wed, 5 Mar 2014 11:25:28 +0100 > >> @@ -1641,7 +1640,15 @@ static int emac_dev_open(struct net_device *ndev) >> >> rollback: >> >> - dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); >> + dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); >> + >> + for (q = k; k >= 0; k--) { >> + for (m = i; m >= res->start; m--) >> + free_irq(m, ndev); >> + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); >> + m = res->end; ^^^^ So this should definitely read "i = res->end;". >> + } > > This final assignment in the loop of 'm' is unused? > > The inner for() loop always started with "m = i;" But it is more than just that. The entire rollback mechanism of emac_dev_open is a mess. It just won't work. 1) Freeing the interrupts. Currently, the code tries to do a platform_get_resource(priv->pdev, IORESOURCE_IRQ, -1) in its last iteration. To make this work, the code should be something like for (q = k; q >= 0; q--) { res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); if (q != k) i = res->end; for (m = i; m >= res->start; m--) free_irq(m, ndev); } 2) Wrong order of err: and rollback: labels. Currently the function does something like this: pm_runtime_get request irq if requesting irqs fails, goto rollback setup phy if phy setup fails, goto err return 0 rollback: free irqs err: pm_runtime_put So if PHY initialization fails, the IRQs are never freed. So rollback and err must be exchanged, and some additonal code must be added to keep the correct values of k and i for rollback. 3) RX DMA descriptors are not freed in case of an error: Right before requesting the irqs, the function creates DMA descriptors for the RX channel. These RX descriptors are never freed when we jump to either rollback or err. And I think there is also no way to free them as long as cpdma_ctlr_start() has not been called (which is done between requesting irqs and phy setup in the code). Problems 1+2 are easy to solve. Prabhakar, Mugunthan, any ideas for 3? I think cpsw_ndo_start() in cpsw.c has the same problem. It will also try to call cpdma_ctlr_stop in error handling before cpdma_ctlr_start was called in some cases. Regards, Christian
On 03/06/2014 07:16 PM, Florian Fainelli wrote: > 2014-03-06 0:51 GMT-08:00 Christian Riesch <christian.riesch@omicron.at>: >> --On March 06, 2014 13:57 +0530 Mugunthan V N <mugunthanvnm@ti.com> wrote: >>> >>> On Wednesday 05 March 2014 03:55 PM, Christian Riesch wrote: >>>> >>>> In commit 6892b41d9701283085b655c6086fb57a5d63fa47 >>>> >>>> Author: Lad, Prabhakar <prabhakar.csengg@gmail.com> >>>> Date: Tue Jun 25 21:24:51 2013 +0530 >>>> net: davinci: emac: Convert to devm_* api >>>> >>>> the call of request_irq is replaced by devm_request_irq and the call >>>> of free_irq is removed. But since interrupts are requested in >>>> emac_dev_open, doing ifconfig up/down on the board requests the >>>> interrupts again each time, causing devm_request_irq to fail. >>>> >>>> This patch reverts said commit partially: It changes the driver back >>>> to use request_irq instead of devm_request_irq, puts free_irq back in >>>> place, but keeps the remaining changes of the original patch. >>>> >>>> Reported-by: Jon Ringle <jon@ringle.org> >>>> Signed-off-by: Christian Riesch <christian.riesch@omicron.at> >>>> Cc: Lad, Prabhakar <prabhakar.csengg@gmail.com> >>>> Cc: <stable@vger.kernel.org> >>> >>> >>> Instead of moving back to request irq. can you move the devm interrupt >>> request code from open to probe so that the issue is fixed, IRQ will be >>> requested on module insert and IRQ will be free in module remove and >>> there will not be any failures in devm request irq while repeating >>> ifup/ifdown and also during module insert/remove. >> >> >> This is exactly what I tried first, please have a look at my first patch and >> the discussion [1]. Florian Fainelli asked me to revert Prabhakar's patch >> instead to bring back the "usual situation", "just in case some uncontrolled >> interrupt bit triggers an interrupt while the interface is down for >> instance..." >> >> Florian Fainelli, Mugunthan VN, which solution is better? > > I think the solution that does: > > - request_irq() in ndo_open() > - free_irq() in ndo_stop() > > is the safest option because it ensure that the various interrupt > lines are masked at the interrupt controller level, and not just at > Ethernet MAC level, and as such gives you more control over what the > hardware does. It also mimics what 99% of the Ethernet drivers do, > which will help identifying those common patterns programmatically. > Why are you not using enable_irq()/disable_irq()? Also, IRQ_NOAUTOEN can be used irq_set_status_flags(IRQ_NOAUTOEN); before [devm_]request_irq(). The normal way is to request resources from .rpobe(), use them and free on .remove(). Actually, I've found at least one example - drivers/net/ethernet/apple/bmac.c Regards, - grygorii
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index cd9b164..2514304 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1532,7 +1532,7 @@ static int emac_dev_open(struct net_device *ndev) struct device *emac_dev = &ndev->dev; u32 cnt; struct resource *res; - int ret; + int q, m, ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -1567,8 +1567,7 @@ static int emac_dev_open(struct net_device *ndev) while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { for (i = res->start; i <= res->end; i++) { - if (devm_request_irq(&priv->pdev->dev, i, emac_irq, - 0, ndev->name, ndev)) + if (request_irq(i, emac_irq, 0, ndev->name, ndev)) goto rollback; } k++; @@ -1641,7 +1640,15 @@ static int emac_dev_open(struct net_device *ndev) rollback: - dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); + dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); + + for (q = k; k >= 0; k--) { + for (m = i; m >= res->start; m--) + free_irq(m, ndev); + res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); + m = res->end; + } + ret = -EBUSY; err: pm_runtime_put(&priv->pdev->dev); @@ -1659,6 +1666,9 @@ err: */ static int emac_dev_stop(struct net_device *ndev) { + struct resource *res; + int i = 0; + int irq_num; struct emac_priv *priv = netdev_priv(ndev); struct device *emac_dev = &ndev->dev; @@ -1674,6 +1684,13 @@ static int emac_dev_stop(struct net_device *ndev) if (priv->phydev) phy_disconnect(priv->phydev); + /* Free IRQ */ + while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) + free_irq(irq_num, priv->ndev); + i++; + } + if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
In commit 6892b41d9701283085b655c6086fb57a5d63fa47 Author: Lad, Prabhakar <prabhakar.csengg@gmail.com> Date: Tue Jun 25 21:24:51 2013 +0530 net: davinci: emac: Convert to devm_* api the call of request_irq is replaced by devm_request_irq and the call of free_irq is removed. But since interrupts are requested in emac_dev_open, doing ifconfig up/down on the board requests the interrupts again each time, causing devm_request_irq to fail. This patch reverts said commit partially: It changes the driver back to use request_irq instead of devm_request_irq, puts free_irq back in place, but keeps the remaining changes of the original patch. Reported-by: Jon Ringle <jon@ringle.org> Signed-off-by: Christian Riesch <christian.riesch@omicron.at> Cc: Lad, Prabhakar <prabhakar.csengg@gmail.com> Cc: <stable@vger.kernel.org> --- drivers/net/ethernet/ti/davinci_emac.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)