aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r--drivers/net/mv643xx_eth.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 8a97a0066a88..910920e21259 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -96,6 +96,7 @@ static char mv643xx_eth_driver_version[] = "1.1";
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_0 0x00080000
99#define INT_TX_END 0x07f80000 100#define INT_TX_END 0x07f80000
100#define INT_RX 0x0007fbfc 101#define INT_RX 0x0007fbfc
101#define INT_EXT 0x00000002 102#define INT_EXT 0x00000002
@@ -706,6 +707,7 @@ static inline __be16 sum16_as_be(__sum16 sum)
706 707
707static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) 708static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
708{ 709{
710 struct mv643xx_eth_private *mp = txq_to_mp(txq);
709 int nr_frags = skb_shinfo(skb)->nr_frags; 711 int nr_frags = skb_shinfo(skb)->nr_frags;
710 int tx_index; 712 int tx_index;
711 struct tx_desc *desc; 713 struct tx_desc *desc;
@@ -759,6 +761,10 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
759 wmb(); 761 wmb();
760 desc->cmd_sts = cmd_sts; 762 desc->cmd_sts = cmd_sts;
761 763
764 /* clear TX_END interrupt status */
765 wrl(mp, INT_CAUSE(mp->port_num), ~(INT_TX_END_0 << txq->index));
766 rdl(mp, INT_CAUSE(mp->port_num));
767
762 /* ensure all descriptors are written before poking hardware */ 768 /* ensure all descriptors are written before poking hardware */
763 wmb(); 769 wmb();
764 txq_enable(txq); 770 txq_enable(txq);
@@ -1684,7 +1690,6 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
1684 struct mv643xx_eth_private *mp = netdev_priv(dev); 1690 struct mv643xx_eth_private *mp = netdev_priv(dev);
1685 u32 int_cause; 1691 u32 int_cause;
1686 u32 int_cause_ext; 1692 u32 int_cause_ext;
1687 u32 txq_active;
1688 1693
1689 int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & 1694 int_cause = rdl(mp, INT_CAUSE(mp->port_num)) &
1690 (INT_TX_END | INT_RX | INT_EXT); 1695 (INT_TX_END | INT_RX | INT_EXT);
@@ -1743,8 +1748,6 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
1743 } 1748 }
1744#endif 1749#endif
1745 1750
1746 txq_active = rdl(mp, TXQ_COMMAND(mp->port_num));
1747
1748 /* 1751 /*
1749 * TxBuffer or TxError set for any of the 8 queues? 1752 * TxBuffer or TxError set for any of the 8 queues?
1750 */ 1753 */
@@ -1754,6 +1757,14 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
1754 for (i = 0; i < 8; i++) 1757 for (i = 0; i < 8; i++)
1755 if (mp->txq_mask & (1 << i)) 1758 if (mp->txq_mask & (1 << i))
1756 txq_reclaim(mp->txq + i, 0); 1759 txq_reclaim(mp->txq + i, 0);
1760
1761 /*
1762 * Enough space again in the primary TX queue for a
1763 * full packet?
1764 */
1765 spin_lock(&mp->lock);
1766 __txq_maybe_wake(mp->txq + mp->txq_primary);
1767 spin_unlock(&mp->lock);
1757 } 1768 }
1758 1769
1759 /* 1770 /*
@@ -1763,19 +1774,25 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
1763 int i; 1774 int i;
1764 1775
1765 wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END)); 1776 wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END));
1777
1778 spin_lock(&mp->lock);
1766 for (i = 0; i < 8; i++) { 1779 for (i = 0; i < 8; i++) {
1767 struct tx_queue *txq = mp->txq + i; 1780 struct tx_queue *txq = mp->txq + i;
1768 if (txq->tx_desc_count && !((txq_active >> i) & 1)) 1781 u32 hw_desc_ptr;
1782 u32 expected_ptr;
1783
1784 if ((int_cause & (INT_TX_END_0 << i)) == 0)
1785 continue;
1786
1787 hw_desc_ptr =
1788 rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, i));
1789 expected_ptr = (u32)txq->tx_desc_dma +
1790 txq->tx_curr_desc * sizeof(struct tx_desc);
1791
1792 if (hw_desc_ptr != expected_ptr)
1769 txq_enable(txq); 1793 txq_enable(txq);
1770 } 1794 }
1771 } 1795 spin_unlock(&mp->lock);
1772
1773 /*
1774 * Enough space again in the primary TX queue for a full packet?
1775 */
1776 if (int_cause_ext & INT_EXT_TX) {
1777 struct tx_queue *txq = mp->txq + mp->txq_primary;
1778 __txq_maybe_wake(txq);
1779 } 1796 }
1780 1797
1781 return IRQ_HANDLED; 1798 return IRQ_HANDLED;