diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2005-12-09 11:35:03 -0800 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-12-12 15:27:21 -0500 |
commit | 13b97b74b964f9da9b5dab6c57708bccd3ada542 (patch) | |
tree | 568bb52919395e53eb70b186e16a98c5f37f5b5a /drivers/net/sky2.c | |
parent | 0e3ff6aab1ff2d093996bd7b8c9c06c3d823855c (diff) | |
download | lwn-13b97b74b964f9da9b5dab6c57708bccd3ada542.tar.gz lwn-13b97b74b964f9da9b5dab6c57708bccd3ada542.zip |
[PATCH] sky2: transmit complete index optimization
Change transmit complete handling to use the status values
in the poll list because they are in-cache, rather than reading
non-cached memory for chips status.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 8dfd27d4d6e5..ff6557dd079c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1274,7 +1274,7 @@ out: } /* Cleanup all untransmitted buffers, assume transmitter not running */ -static inline void sky2_tx_clean(struct sky2_port *sky2) +static void sky2_tx_clean(struct sky2_port *sky2) { sky2_tx_complete(sky2, sky2->tx_prod); } @@ -1714,14 +1714,16 @@ error: /* * Check for transmit complete */ -static inline void sky2_tx_check(struct sky2_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; +#define TX_NO_STATUS 0xffff - if (dev && netif_running(dev)) { - sky2_tx_complete(netdev_priv(dev), - sky2_read16(hw, port == 0 - ? STAT_TXA1_RIDX : STAT_TXA2_RIDX)); +static inline void sky2_tx_check(struct sky2_hw *hw, int port, u16 last) +{ + if (last != TX_NO_STATUS) { + struct net_device *dev = hw->dev[port]; + if (dev && netif_running(dev)) { + struct sky2_port *sky2 = netdev_priv(dev); + sky2_tx_complete(sky2, last); + } } } @@ -1735,6 +1737,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) unsigned int to_do = min(dev0->quota, *budget); unsigned int work_done = 0; u16 hwidx; + u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); hwidx = sky2_read16(hw, STAT_PUT_IDX); @@ -1806,7 +1809,10 @@ static int sky2_poll(struct net_device *dev0, int *budget) break; case OP_TXINDEXLE: - /* pick up transmit status later */ + /* TX index reports status for both ports */ + tx_done[0] = status & 0xffff; + tx_done[1] = ((status >> 24) & 0xff) + | (u16)(length & 0xf) << 8; break; default: @@ -1818,16 +1824,13 @@ static int sky2_poll(struct net_device *dev0, int *budget) } exit_loop: - sky2_tx_check(hw, 0); - sky2_tx_check(hw, 1); - mmiowb(); + sky2_tx_check(hw, 0, tx_done[0]); + sky2_tx_check(hw, 1, tx_done[1]); + if (work_done < to_do) { - /* - * Another chip workaround, need to restart TX timer if status - * LE was handled. WA_DEV_43_418 - */ + /* need to restart TX timer */ if (is_ec_a1(hw)) { sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); |