aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2005-11-04 11:53:48 -0500
committerJohn W. Linville <linville@tuxdriver.com>2005-11-05 21:00:03 -0500
commitf4e418f7f3286f854883f9f7e3bbf7005340d2de (patch)
tree655a1c3c3ea012e0521b83728034b7a675ae8e5f
parente3648b3d8de3b37fae7acbb57db1e001a19cd3b7 (diff)
[PATCH] bnx2: refine bnx2_poll
Refine bnx2_poll() logic to write back the most up-to-date status tag when all work has been processed. This eliminates some occasional extra interrupts when a older status tag is written even though all work has been processed. The idea is to read the status tag just before exiting bnx2_poll() and then check again for any new work. If no new work is pending, the status tag written back will not generate any extra interrupt. This logic is similar to the changes David Miller did to tg3_poll(). Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/bnx2.c55
-rw-r--r--drivers/net/bnx2.h3
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)
1533static void 1533static void
1534bnx2_tx_int(struct bnx2 *bp) 1534bnx2_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,
1636static int 1639static int
1637bnx2_rx_int(struct bnx2 *bp, int budget) 1640bnx2_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
1843static inline int
1844bnx2_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
1830static int 1859static int
1831bnx2_poll(struct net_device *dev, int *budget) 1860bnx2_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