diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 287155ea9ce1..c99915740779 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -96,6 +96,7 @@ static char mv643xx_eth_driver_version[] = "1.0"; | |||
96 | #define TX_BW_MTU(p) (0x0458 + ((p) << 10)) | 96 | #define TX_BW_MTU(p) (0x0458 + ((p) << 10)) |
97 | #define TX_BW_BURST(p) (0x045c + ((p) << 10)) | 97 | #define TX_BW_BURST(p) (0x045c + ((p) << 10)) |
98 | #define INT_CAUSE(p) (0x0460 + ((p) << 10)) | 98 | #define INT_CAUSE(p) (0x0460 + ((p) << 10)) |
99 | #define INT_TX_END 0x07f80000 | ||
99 | #define INT_RX 0x0007fbfc | 100 | #define INT_RX 0x0007fbfc |
100 | #define INT_EXT 0x00000002 | 101 | #define INT_EXT 0x00000002 |
101 | #define INT_CAUSE_EXT(p) (0x0464 + ((p) << 10)) | 102 | #define INT_CAUSE_EXT(p) (0x0464 + ((p) << 10)) |
@@ -619,7 +620,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) | |||
619 | netif_rx_complete(mp->dev, napi); | 620 | netif_rx_complete(mp->dev, napi); |
620 | wrl(mp, INT_CAUSE(mp->port_num), 0); | 621 | wrl(mp, INT_CAUSE(mp->port_num), 0); |
621 | wrl(mp, INT_CAUSE_EXT(mp->port_num), 0); | 622 | wrl(mp, INT_CAUSE_EXT(mp->port_num), 0); |
622 | wrl(mp, INT_MASK(mp->port_num), INT_RX | INT_EXT); | 623 | wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); |
623 | } | 624 | } |
624 | 625 | ||
625 | return rx; | 626 | return rx; |
@@ -1622,8 +1623,10 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) | |||
1622 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1623 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1623 | u32 int_cause; | 1624 | u32 int_cause; |
1624 | u32 int_cause_ext; | 1625 | u32 int_cause_ext; |
1626 | u32 txq_active; | ||
1625 | 1627 | ||
1626 | int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & (INT_RX | INT_EXT); | 1628 | int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & |
1629 | (INT_TX_END | INT_RX | INT_EXT); | ||
1627 | if (int_cause == 0) | 1630 | if (int_cause == 0) |
1628 | return IRQ_NONE; | 1631 | return IRQ_NONE; |
1629 | 1632 | ||
@@ -1675,6 +1678,8 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) | |||
1675 | } | 1678 | } |
1676 | #endif | 1679 | #endif |
1677 | 1680 | ||
1681 | txq_active = rdl(mp, TXQ_COMMAND(mp->port_num)); | ||
1682 | |||
1678 | /* | 1683 | /* |
1679 | * TxBuffer or TxError set for any of the 8 queues? | 1684 | * TxBuffer or TxError set for any of the 8 queues? |
1680 | */ | 1685 | */ |
@@ -1684,8 +1689,28 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) | |||
1684 | for (i = 0; i < 8; i++) | 1689 | for (i = 0; i < 8; i++) |
1685 | if (mp->txq_mask & (1 << i)) | 1690 | if (mp->txq_mask & (1 << i)) |
1686 | txq_reclaim(mp->txq + i, 0); | 1691 | txq_reclaim(mp->txq + i, 0); |
1692 | } | ||
1687 | 1693 | ||
1688 | __txq_maybe_wake(mp->txq + mp->txq_primary); | 1694 | /* |
1695 | * Any TxEnd interrupts? | ||
1696 | */ | ||
1697 | if (int_cause & INT_TX_END) { | ||
1698 | int i; | ||
1699 | |||
1700 | wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END)); | ||
1701 | for (i = 0; i < 8; i++) { | ||
1702 | struct tx_queue *txq = mp->txq + i; | ||
1703 | if (txq->tx_desc_count && !((txq_active >> i) & 1)) | ||
1704 | txq_enable(txq); | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | /* | ||
1709 | * Enough space again in the primary TX queue for a full packet? | ||
1710 | */ | ||
1711 | if (int_cause_ext & INT_EXT_TX) { | ||
1712 | struct tx_queue *txq = mp->txq + mp->txq_primary; | ||
1713 | __txq_maybe_wake(txq); | ||
1689 | } | 1714 | } |
1690 | 1715 | ||
1691 | return IRQ_HANDLED; | 1716 | return IRQ_HANDLED; |
@@ -1869,7 +1894,7 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
1869 | wrl(mp, INT_MASK_EXT(mp->port_num), | 1894 | wrl(mp, INT_MASK_EXT(mp->port_num), |
1870 | INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX); | 1895 | INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX); |
1871 | 1896 | ||
1872 | wrl(mp, INT_MASK(mp->port_num), INT_RX | INT_EXT); | 1897 | wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); |
1873 | 1898 | ||
1874 | return 0; | 1899 | return 0; |
1875 | 1900 | ||
@@ -2005,7 +2030,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev) | |||
2005 | 2030 | ||
2006 | mv643xx_eth_irq(dev->irq, dev); | 2031 | mv643xx_eth_irq(dev->irq, dev); |
2007 | 2032 | ||
2008 | wrl(mp, INT_MASK(mp->port_num), INT_RX | INT_CAUSE_EXT); | 2033 | wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_CAUSE_EXT); |
2009 | } | 2034 | } |
2010 | #endif | 2035 | #endif |
2011 | 2036 | ||