aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-12-09 14:35:03 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-12-12 15:27:21 -0500
commit13b97b74b964f9da9b5dab6c57708bccd3ada542 (patch)
tree568bb52919395e53eb70b186e16a98c5f37f5b5a /drivers/net
parent0e3ff6aab1ff2d093996bd7b8c9c06c3d823855c (diff)
[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')
-rw-r--r--drivers/net/sky2.c35
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:
1274} 1274}
1275 1275
1276/* Cleanup all untransmitted buffers, assume transmitter not running */ 1276/* Cleanup all untransmitted buffers, assume transmitter not running */
1277static inline void sky2_tx_clean(struct sky2_port *sky2) 1277static void sky2_tx_clean(struct sky2_port *sky2)
1278{ 1278{
1279 sky2_tx_complete(sky2, sky2->tx_prod); 1279 sky2_tx_complete(sky2, sky2->tx_prod);
1280} 1280}
@@ -1714,14 +1714,16 @@ error:
1714/* 1714/*
1715 * Check for transmit complete 1715 * Check for transmit complete
1716 */ 1716 */
1717static inline void sky2_tx_check(struct sky2_hw *hw, int port) 1717#define TX_NO_STATUS 0xffff
1718{
1719 struct net_device *dev = hw->dev[port];
1720 1718
1721 if (dev && netif_running(dev)) { 1719static inline void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
1722 sky2_tx_complete(netdev_priv(dev), 1720{
1723 sky2_read16(hw, port == 0 1721 if (last != TX_NO_STATUS) {
1724 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX)); 1722 struct net_device *dev = hw->dev[port];
1723 if (dev && netif_running(dev)) {
1724 struct sky2_port *sky2 = netdev_priv(dev);
1725 sky2_tx_complete(sky2, last);
1726 }
1725 } 1727 }
1726} 1728}
1727 1729
@@ -1735,6 +1737,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1735 unsigned int to_do = min(dev0->quota, *budget); 1737 unsigned int to_do = min(dev0->quota, *budget);
1736 unsigned int work_done = 0; 1738 unsigned int work_done = 0;
1737 u16 hwidx; 1739 u16 hwidx;
1740 u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
1738 1741
1739 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); 1742 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
1740 hwidx = sky2_read16(hw, STAT_PUT_IDX); 1743 hwidx = sky2_read16(hw, STAT_PUT_IDX);
@@ -1806,7 +1809,10 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1806 break; 1809 break;
1807 1810
1808 case OP_TXINDEXLE: 1811 case OP_TXINDEXLE:
1809 /* pick up transmit status later */ 1812 /* TX index reports status for both ports */
1813 tx_done[0] = status & 0xffff;
1814 tx_done[1] = ((status >> 24) & 0xff)
1815 | (u16)(length & 0xf) << 8;
1810 break; 1816 break;
1811 1817
1812 default: 1818 default:
@@ -1818,16 +1824,13 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1818 } 1824 }
1819 1825
1820exit_loop: 1826exit_loop:
1821 sky2_tx_check(hw, 0);
1822 sky2_tx_check(hw, 1);
1823
1824 mmiowb(); 1827 mmiowb();
1825 1828
1829 sky2_tx_check(hw, 0, tx_done[0]);
1830 sky2_tx_check(hw, 1, tx_done[1]);
1831
1826 if (work_done < to_do) { 1832 if (work_done < to_do) {
1827 /* 1833 /* need to restart TX timer */
1828 * Another chip workaround, need to restart TX timer if status
1829 * LE was handled. WA_DEV_43_418
1830 */
1831 if (is_ec_a1(hw)) { 1834 if (is_ec_a1(hw)) {
1832 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); 1835 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
1833 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); 1836 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);