Skip to content

Commit 866b7cd

Browse files
committed
Merge branch 'davinci_emac'
Christian Riesch says: ==================== net: davinci_emac: Fix interrupt requests and error handling since commit 6892b41 (Linux 3.11) the davinci_emac driver is broken. After doing ifconfig down, ifconfig up, requesting the interrupts for the driver fails. The interface remains dead until the board is rebooted. The first patch in this patchset reverts commit 6892b41 partially and makes the driver useable again. During the work on the first patch, a number of bugs in the error handling of the driver's ndo_open code were found. The second patch fixes these bugs. I believe the first patch meets the rules for stable kernels, I therefore added the stable tag to this patch. The second patch is just cleanup, the code that is fixed by this patch is only executed in case of an error. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents c27f087 + cd11cf5 commit 866b7cd

File tree

2 files changed

+44
-13
lines changed

2 files changed

+44
-13
lines changed

drivers/net/ethernet/ti/davinci_cpdma.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
355355
int i;
356356

357357
spin_lock_irqsave(&ctlr->lock, flags);
358-
if (ctlr->state != CPDMA_STATE_ACTIVE) {
358+
if (ctlr->state == CPDMA_STATE_TEARDOWN) {
359359
spin_unlock_irqrestore(&ctlr->lock, flags);
360360
return -EINVAL;
361361
}
@@ -891,7 +891,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
891891
unsigned timeout;
892892

893893
spin_lock_irqsave(&chan->lock, flags);
894-
if (chan->state != CPDMA_STATE_ACTIVE) {
894+
if (chan->state == CPDMA_STATE_TEARDOWN) {
895895
spin_unlock_irqrestore(&chan->lock, flags);
896896
return -EINVAL;
897897
}

drivers/net/ethernet/ti/davinci_emac.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,9 +1532,9 @@ static int emac_dev_open(struct net_device *ndev)
15321532
struct device *emac_dev = &ndev->dev;
15331533
u32 cnt;
15341534
struct resource *res;
1535-
int ret;
1535+
int q, m, ret;
1536+
int res_num = 0, irq_num = 0;
15361537
int i = 0;
1537-
int k = 0;
15381538
struct emac_priv *priv = netdev_priv(ndev);
15391539

15401540
pm_runtime_get(&priv->pdev->dev);
@@ -1564,15 +1564,24 @@ static int emac_dev_open(struct net_device *ndev)
15641564
}
15651565

15661566
/* Request IRQ */
1567+
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ,
1568+
res_num))) {
1569+
for (irq_num = res->start; irq_num <= res->end; irq_num++) {
1570+
dev_err(emac_dev, "Request IRQ %d\n", irq_num);
1571+
if (request_irq(irq_num, emac_irq, 0, ndev->name,
1572+
ndev)) {
1573+
dev_err(emac_dev,
1574+
"DaVinci EMAC: request_irq() failed\n");
1575+
ret = -EBUSY;
15671576

1568-
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
1569-
for (i = res->start; i <= res->end; i++) {
1570-
if (devm_request_irq(&priv->pdev->dev, i, emac_irq,
1571-
0, ndev->name, ndev))
15721577
goto rollback;
1578+
}
15731579
}
1574-
k++;
1580+
res_num++;
15751581
}
1582+
/* prepare counters for rollback in case of an error */
1583+
res_num--;
1584+
irq_num--;
15761585

15771586
/* Start/Enable EMAC hardware */
15781587
emac_hw_enable(priv);
@@ -1639,11 +1648,23 @@ static int emac_dev_open(struct net_device *ndev)
16391648

16401649
return 0;
16411650

1642-
rollback:
1643-
1644-
dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed");
1645-
ret = -EBUSY;
16461651
err:
1652+
emac_int_disable(priv);
1653+
napi_disable(&priv->napi);
1654+
1655+
rollback:
1656+
for (q = res_num; q >= 0; q--) {
1657+
res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, q);
1658+
/* at the first iteration, irq_num is already set to the
1659+
* right value
1660+
*/
1661+
if (q != res_num)
1662+
irq_num = res->end;
1663+
1664+
for (m = irq_num; m >= res->start; m--)
1665+
free_irq(m, ndev);
1666+
}
1667+
cpdma_ctlr_stop(priv->dma);
16471668
pm_runtime_put(&priv->pdev->dev);
16481669
return ret;
16491670
}
@@ -1659,6 +1680,9 @@ static int emac_dev_open(struct net_device *ndev)
16591680
*/
16601681
static int emac_dev_stop(struct net_device *ndev)
16611682
{
1683+
struct resource *res;
1684+
int i = 0;
1685+
int irq_num;
16621686
struct emac_priv *priv = netdev_priv(ndev);
16631687
struct device *emac_dev = &ndev->dev;
16641688

@@ -1674,6 +1698,13 @@ static int emac_dev_stop(struct net_device *ndev)
16741698
if (priv->phydev)
16751699
phy_disconnect(priv->phydev);
16761700

1701+
/* Free IRQ */
1702+
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) {
1703+
for (irq_num = res->start; irq_num <= res->end; irq_num++)
1704+
free_irq(irq_num, priv->ndev);
1705+
i++;
1706+
}
1707+
16771708
if (netif_msg_drv(priv))
16781709
dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
16791710

0 commit comments

Comments
 (0)