aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-07-12 18:23:48 -0400
committerJeff Garzik <jeff@garzik.org>2006-07-12 18:39:22 -0400
commit22e1170310ec6afa41e0dc7ac9dfac735d82dcab (patch)
treefc6df3250b682443b7f12072dbae259d25fee91b /drivers/net
parentafa195da458cb06f302c37f8d37b21b177060aed (diff)
[PATCH] sky2: optimize receive restart
When the driver handles multiple packets per NAPI poll, it is better to reload the receive ring, then tell the hardware. Otherwise, under packet storm with flow control, the driver/hardware will degrade down to one packet getting through per pause-exchange. Likewise on transmit, don't wakeup until a little more than minimum ring space is available. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sky2.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index e65689ebe147..d98f28c34e5c 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -65,6 +65,7 @@
65#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) 65#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
66#define RX_DEF_PENDING RX_MAX_PENDING 66#define RX_DEF_PENDING RX_MAX_PENDING
67#define RX_SKB_ALIGN 8 67#define RX_SKB_ALIGN 8
68#define RX_BUF_WRITE 16
68 69
69#define TX_RING_SIZE 512 70#define TX_RING_SIZE 512
70#define TX_DEF_PENDING (TX_RING_SIZE - 1) 71#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -1390,7 +1391,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1390 } 1391 }
1391 1392
1392 sky2->tx_cons = put; 1393 sky2->tx_cons = put;
1393 if (tx_avail(sky2) > MAX_SKB_TX_LE) 1394 if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
1394 netif_wake_queue(dev); 1395 netif_wake_queue(dev);
1395} 1396}
1396 1397
@@ -1889,9 +1890,6 @@ resubmit:
1889 re->skb->ip_summed = CHECKSUM_NONE; 1890 re->skb->ip_summed = CHECKSUM_NONE;
1890 sky2_rx_add(sky2, re->mapaddr); 1891 sky2_rx_add(sky2, re->mapaddr);
1891 1892
1892 /* Tell receiver about new buffers. */
1893 sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put);
1894
1895 return skb; 1893 return skb;
1896 1894
1897oversize: 1895oversize:
@@ -1938,7 +1936,9 @@ static inline int sky2_more_work(const struct sky2_hw *hw)
1938/* Process status response ring */ 1936/* Process status response ring */
1939static int sky2_status_intr(struct sky2_hw *hw, int to_do) 1937static int sky2_status_intr(struct sky2_hw *hw, int to_do)
1940{ 1938{
1939 struct sky2_port *sky2;
1941 int work_done = 0; 1940 int work_done = 0;
1941 unsigned buf_write[2] = { 0, 0 };
1942 u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); 1942 u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
1943 1943
1944 rmb(); 1944 rmb();
@@ -1946,7 +1946,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
1946 while (hw->st_idx != hwidx) { 1946 while (hw->st_idx != hwidx) {
1947 struct sky2_status_le *le = hw->st_le + hw->st_idx; 1947 struct sky2_status_le *le = hw->st_le + hw->st_idx;
1948 struct net_device *dev; 1948 struct net_device *dev;
1949 struct sky2_port *sky2;
1950 struct sk_buff *skb; 1949 struct sk_buff *skb;
1951 u32 status; 1950 u32 status;
1952 u16 length; 1951 u16 length;
@@ -1979,6 +1978,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
1979#endif 1978#endif
1980 netif_receive_skb(skb); 1979 netif_receive_skb(skb);
1981 1980
1981 /* Update receiver after 16 frames */
1982 if (++buf_write[le->link] == RX_BUF_WRITE) {
1983 sky2_put_idx(hw, rxqaddr[le->link],
1984 sky2->rx_put);
1985 buf_write[le->link] = 0;
1986 }
1987
1988 /* Stop after net poll weight */
1982 if (++work_done >= to_do) 1989 if (++work_done >= to_do)
1983 goto exit_loop; 1990 goto exit_loop;
1984 break; 1991 break;
@@ -2017,6 +2024,16 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2017 } 2024 }
2018 2025
2019exit_loop: 2026exit_loop:
2027 if (buf_write[0]) {
2028 sky2 = netdev_priv(hw->dev[0]);
2029 sky2_put_idx(hw, Q_R1, sky2->rx_put);
2030 }
2031
2032 if (buf_write[1]) {
2033 sky2 = netdev_priv(hw->dev[1]);
2034 sky2_put_idx(hw, Q_R2, sky2->rx_put);
2035 }
2036
2020 return work_done; 2037 return work_done;
2021} 2038}
2022 2039