aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-03-24 15:32:34 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-24 15:32:34 -0400
commit866b7cdf5f8e440c4921765b7f4e1fe102a7e089 (patch)
tree06ca0a0ed579d0e8aaab3a7b0f2921f3c9c20855
parentc27f0872a3448c46e561e226b5b97f77187b06d2 (diff)
parentcd11cf505318ff24e42f35145f9cdf8596fa1958 (diff)
Merge branch 'davinci_emac'
Christian Riesch says: ==================== net: davinci_emac: Fix interrupt requests and error handling since commit 6892b41d9701283085b655c6086fb57a5d63fa47 (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 6892b41d9701283085b655c6086fb57a5d63fa47 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 <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c4
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c53
2 files changed, 44 insertions, 13 deletions
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 364d0c7952c0..88ef27067bf2 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -355,7 +355,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
355 int i; 355 int i;
356 356
357 spin_lock_irqsave(&ctlr->lock, flags); 357 spin_lock_irqsave(&ctlr->lock, flags);
358 if (ctlr->state != CPDMA_STATE_ACTIVE) { 358 if (ctlr->state == CPDMA_STATE_TEARDOWN) {
359 spin_unlock_irqrestore(&ctlr->lock, flags); 359 spin_unlock_irqrestore(&ctlr->lock, flags);
360 return -EINVAL; 360 return -EINVAL;
361 } 361 }
@@ -891,7 +891,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
891 unsigned timeout; 891 unsigned timeout;
892 892
893 spin_lock_irqsave(&chan->lock, flags); 893 spin_lock_irqsave(&chan->lock, flags);
894 if (chan->state != CPDMA_STATE_ACTIVE) { 894 if (chan->state == CPDMA_STATE_TEARDOWN) {
895 spin_unlock_irqrestore(&chan->lock, flags); 895 spin_unlock_irqrestore(&chan->lock, flags);
896 return -EINVAL; 896 return -EINVAL;
897 } 897 }
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index cd9b164a0434..8f0e69ce07ca 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1532,9 +1532,9 @@ static int emac_dev_open(struct net_device *ndev)
1532 struct device *emac_dev = &ndev->dev; 1532 struct device *emac_dev = &ndev->dev;
1533 u32 cnt; 1533 u32 cnt;
1534 struct resource *res; 1534 struct resource *res;
1535 int ret; 1535 int q, m, ret;
1536 int res_num = 0, irq_num = 0;
1536 int i = 0; 1537 int i = 0;
1537 int k = 0;
1538 struct emac_priv *priv = netdev_priv(ndev); 1538 struct emac_priv *priv = netdev_priv(ndev);
1539 1539
1540 pm_runtime_get(&priv->pdev->dev); 1540 pm_runtime_get(&priv->pdev->dev);
@@ -1564,15 +1564,24 @@ static int emac_dev_open(struct net_device *ndev)
1564 } 1564 }
1565 1565
1566 /* Request IRQ */ 1566 /* 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;
1567 1576
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))
1572 goto rollback; 1577 goto rollback;
1578 }
1573 } 1579 }
1574 k++; 1580 res_num++;
1575 } 1581 }
1582 /* prepare counters for rollback in case of an error */
1583 res_num--;
1584 irq_num--;
1576 1585
1577 /* Start/Enable EMAC hardware */ 1586 /* Start/Enable EMAC hardware */
1578 emac_hw_enable(priv); 1587 emac_hw_enable(priv);
@@ -1639,11 +1648,23 @@ static int emac_dev_open(struct net_device *ndev)
1639 1648
1640 return 0; 1649 return 0;
1641 1650
1642rollback:
1643
1644 dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed");
1645 ret = -EBUSY;
1646err: 1651err:
1652 emac_int_disable(priv);
1653 napi_disable(&priv->napi);
1654
1655rollback:
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);
1647 pm_runtime_put(&priv->pdev->dev); 1668 pm_runtime_put(&priv->pdev->dev);
1648 return ret; 1669 return ret;
1649} 1670}
@@ -1659,6 +1680,9 @@ err:
1659 */ 1680 */
1660static int emac_dev_stop(struct net_device *ndev) 1681static int emac_dev_stop(struct net_device *ndev)
1661{ 1682{
1683 struct resource *res;
1684 int i = 0;
1685 int irq_num;
1662 struct emac_priv *priv = netdev_priv(ndev); 1686 struct emac_priv *priv = netdev_priv(ndev);
1663 struct device *emac_dev = &ndev->dev; 1687 struct device *emac_dev = &ndev->dev;
1664 1688
@@ -1674,6 +1698,13 @@ static int emac_dev_stop(struct net_device *ndev)
1674 if (priv->phydev) 1698 if (priv->phydev)
1675 phy_disconnect(priv->phydev); 1699 phy_disconnect(priv->phydev);
1676 1700
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
1677 if (netif_msg_drv(priv)) 1708 if (netif_msg_drv(priv))
1678 dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); 1709 dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
1679 1710