diff options
-rw-r--r-- | drivers/net/bnx2.c | 55 | ||||
-rw-r--r-- | drivers/net/bnx2.h | 3 |
2 files changed, 43 insertions, 15 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index affb67372e02..aa6d30e0d829 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -1533,10 +1533,11 @@ bnx2_phy_int(struct bnx2 *bp) | |||
1533 | static void | 1533 | static void |
1534 | bnx2_tx_int(struct bnx2 *bp) | 1534 | bnx2_tx_int(struct bnx2 *bp) |
1535 | { | 1535 | { |
1536 | struct status_block *sblk = bp->status_blk; | ||
1536 | u16 hw_cons, sw_cons, sw_ring_cons; | 1537 | u16 hw_cons, sw_cons, sw_ring_cons; |
1537 | int tx_free_bd = 0; | 1538 | int tx_free_bd = 0; |
1538 | 1539 | ||
1539 | hw_cons = bp->status_blk->status_tx_quick_consumer_index0; | 1540 | hw_cons = bp->hw_tx_cons = sblk->status_tx_quick_consumer_index0; |
1540 | if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { | 1541 | if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { |
1541 | hw_cons++; | 1542 | hw_cons++; |
1542 | } | 1543 | } |
@@ -1591,7 +1592,9 @@ bnx2_tx_int(struct bnx2 *bp) | |||
1591 | 1592 | ||
1592 | dev_kfree_skb_irq(skb); | 1593 | dev_kfree_skb_irq(skb); |
1593 | 1594 | ||
1594 | hw_cons = bp->status_blk->status_tx_quick_consumer_index0; | 1595 | hw_cons = bp->hw_tx_cons = |
1596 | sblk->status_tx_quick_consumer_index0; | ||
1597 | |||
1595 | if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { | 1598 | if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { |
1596 | hw_cons++; | 1599 | hw_cons++; |
1597 | } | 1600 | } |
@@ -1636,11 +1639,12 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, | |||
1636 | static int | 1639 | static int |
1637 | bnx2_rx_int(struct bnx2 *bp, int budget) | 1640 | bnx2_rx_int(struct bnx2 *bp, int budget) |
1638 | { | 1641 | { |
1642 | struct status_block *sblk = bp->status_blk; | ||
1639 | u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; | 1643 | u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; |
1640 | struct l2_fhdr *rx_hdr; | 1644 | struct l2_fhdr *rx_hdr; |
1641 | int rx_pkt = 0; | 1645 | int rx_pkt = 0; |
1642 | 1646 | ||
1643 | hw_cons = bp->status_blk->status_rx_quick_consumer_index0; | 1647 | hw_cons = bp->hw_rx_cons = sblk->status_rx_quick_consumer_index0; |
1644 | if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) { | 1648 | if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) { |
1645 | hw_cons++; | 1649 | hw_cons++; |
1646 | } | 1650 | } |
@@ -1760,6 +1764,15 @@ next_rx: | |||
1760 | 1764 | ||
1761 | if ((rx_pkt == budget)) | 1765 | if ((rx_pkt == budget)) |
1762 | break; | 1766 | break; |
1767 | |||
1768 | /* Refresh hw_cons to see if there is new work */ | ||
1769 | if (sw_cons == hw_cons) { | ||
1770 | hw_cons = bp->hw_rx_cons = | ||
1771 | sblk->status_rx_quick_consumer_index0; | ||
1772 | if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) | ||
1773 | hw_cons++; | ||
1774 | rmb(); | ||
1775 | } | ||
1763 | } | 1776 | } |
1764 | bp->rx_cons = sw_cons; | 1777 | bp->rx_cons = sw_cons; |
1765 | bp->rx_prod = sw_prod; | 1778 | bp->rx_prod = sw_prod; |
@@ -1827,15 +1840,27 @@ bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs) | |||
1827 | return IRQ_HANDLED; | 1840 | return IRQ_HANDLED; |
1828 | } | 1841 | } |
1829 | 1842 | ||
1843 | static inline int | ||
1844 | bnx2_has_work(struct bnx2 *bp) | ||
1845 | { | ||
1846 | struct status_block *sblk = bp->status_blk; | ||
1847 | |||
1848 | if ((sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) || | ||
1849 | (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) | ||
1850 | return 1; | ||
1851 | |||
1852 | if (((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) != | ||
1853 | bp->link_up) | ||
1854 | return 1; | ||
1855 | |||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1830 | static int | 1859 | static int |
1831 | bnx2_poll(struct net_device *dev, int *budget) | 1860 | bnx2_poll(struct net_device *dev, int *budget) |
1832 | { | 1861 | { |
1833 | struct bnx2 *bp = dev->priv; | 1862 | struct bnx2 *bp = dev->priv; |
1834 | int rx_done = 1; | ||
1835 | |||
1836 | bp->last_status_idx = bp->status_blk->status_idx; | ||
1837 | 1863 | ||
1838 | rmb(); | ||
1839 | if ((bp->status_blk->status_attn_bits & | 1864 | if ((bp->status_blk->status_attn_bits & |
1840 | STATUS_ATTN_BITS_LINK_STATE) != | 1865 | STATUS_ATTN_BITS_LINK_STATE) != |
1841 | (bp->status_blk->status_attn_bits_ack & | 1866 | (bp->status_blk->status_attn_bits_ack & |
@@ -1846,11 +1871,10 @@ bnx2_poll(struct net_device *dev, int *budget) | |||
1846 | spin_unlock(&bp->phy_lock); | 1871 | spin_unlock(&bp->phy_lock); |
1847 | } | 1872 | } |
1848 | 1873 | ||
1849 | if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) { | 1874 | if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) |
1850 | bnx2_tx_int(bp); | 1875 | bnx2_tx_int(bp); |
1851 | } | ||
1852 | 1876 | ||
1853 | if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) { | 1877 | if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) { |
1854 | int orig_budget = *budget; | 1878 | int orig_budget = *budget; |
1855 | int work_done; | 1879 | int work_done; |
1856 | 1880 | ||
@@ -1860,13 +1884,12 @@ bnx2_poll(struct net_device *dev, int *budget) | |||
1860 | work_done = bnx2_rx_int(bp, orig_budget); | 1884 | work_done = bnx2_rx_int(bp, orig_budget); |
1861 | *budget -= work_done; | 1885 | *budget -= work_done; |
1862 | dev->quota -= work_done; | 1886 | dev->quota -= work_done; |
1863 | |||
1864 | if (work_done >= orig_budget) { | ||
1865 | rx_done = 0; | ||
1866 | } | ||
1867 | } | 1887 | } |
1868 | 1888 | ||
1869 | if (rx_done) { | 1889 | bp->last_status_idx = bp->status_blk->status_idx; |
1890 | rmb(); | ||
1891 | |||
1892 | if (!bnx2_has_work(bp)) { | ||
1870 | netif_rx_complete(dev); | 1893 | netif_rx_complete(dev); |
1871 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, | 1894 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, |
1872 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | | 1895 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | |
@@ -3222,6 +3245,7 @@ bnx2_init_tx_ring(struct bnx2 *bp) | |||
3222 | 3245 | ||
3223 | bp->tx_prod = 0; | 3246 | bp->tx_prod = 0; |
3224 | bp->tx_cons = 0; | 3247 | bp->tx_cons = 0; |
3248 | bp->hw_tx_cons = 0; | ||
3225 | bp->tx_prod_bseq = 0; | 3249 | bp->tx_prod_bseq = 0; |
3226 | 3250 | ||
3227 | val = BNX2_L2CTX_TYPE_TYPE_L2; | 3251 | val = BNX2_L2CTX_TYPE_TYPE_L2; |
@@ -3254,6 +3278,7 @@ bnx2_init_rx_ring(struct bnx2 *bp) | |||
3254 | 3278 | ||
3255 | ring_prod = prod = bp->rx_prod = 0; | 3279 | ring_prod = prod = bp->rx_prod = 0; |
3256 | bp->rx_cons = 0; | 3280 | bp->rx_cons = 0; |
3281 | bp->hw_rx_cons = 0; | ||
3257 | bp->rx_prod_bseq = 0; | 3282 | bp->rx_prod_bseq = 0; |
3258 | 3283 | ||
3259 | rxbd = &bp->rx_desc_ring[0]; | 3284 | rxbd = &bp->rx_desc_ring[0]; |
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 012586e4ba0b..76bb5f1a250b 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h | |||
@@ -3914,6 +3914,9 @@ struct bnx2 { | |||
3914 | u16 tx_cons; | 3914 | u16 tx_cons; |
3915 | int tx_ring_size; | 3915 | int tx_ring_size; |
3916 | 3916 | ||
3917 | u16 hw_tx_cons; | ||
3918 | u16 hw_rx_cons; | ||
3919 | |||
3917 | #ifdef BCM_VLAN | 3920 | #ifdef BCM_VLAN |
3918 | struct vlan_group *vlgrp; | 3921 | struct vlan_group *vlgrp; |
3919 | #endif | 3922 | #endif |