diff options
| -rw-r--r-- | drivers/net/ethernet/ti/davinci_cpdma.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/ti/davinci_emac.c | 53 |
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 | ||
| 1642 | rollback: | ||
| 1643 | |||
| 1644 | dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); | ||
| 1645 | ret = -EBUSY; | ||
| 1646 | err: | 1651 | 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); | ||
| 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 | */ |
| 1660 | static int emac_dev_stop(struct net_device *ndev) | 1681 | static 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 | ||
