diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2005-12-09 14:35:04 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-12-12 15:27:21 -0500 |
commit | af2a58acb12f6b19e6f04b730203e199abedc44a (patch) | |
tree | 8fc6c649cff639a3d9af758af90f9b7806bd892b /drivers/net/sky2.c | |
parent | 13b97b74b964f9da9b5dab6c57708bccd3ada542 (diff) |
[PATCH] sky2: transmit complete routine optimization
Hand optimize transmit completion routine.
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, 16 insertions, 19 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ff6557dd079c..21aeb0c91fa6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1227,6 +1227,8 @@ out_unlock: | |||
1227 | static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | 1227 | static void sky2_tx_complete(struct sky2_port *sky2, u16 done) |
1228 | { | 1228 | { |
1229 | struct net_device *dev = sky2->netdev; | 1229 | struct net_device *dev = sky2->netdev; |
1230 | struct pci_dev *pdev = sky2->hw->pdev; | ||
1231 | u16 nxt, put; | ||
1230 | unsigned i; | 1232 | unsigned i; |
1231 | 1233 | ||
1232 | BUG_ON(done >= TX_RING_SIZE); | 1234 | BUG_ON(done >= TX_RING_SIZE); |
@@ -1235,39 +1237,34 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1235 | printk(KERN_DEBUG "%s: tx done, up to %u\n", | 1237 | printk(KERN_DEBUG "%s: tx done, up to %u\n", |
1236 | dev->name, done); | 1238 | dev->name, done); |
1237 | 1239 | ||
1238 | spin_lock(&sky2->tx_lock); | 1240 | for (put = sky2->tx_cons; put != done; put = nxt) { |
1241 | struct tx_ring_info *re = sky2->tx_ring + put; | ||
1242 | struct sk_buff *skb = re->skb; | ||
1239 | 1243 | ||
1240 | while (sky2->tx_cons != done) { | 1244 | nxt = re->idx; |
1241 | struct tx_ring_info *re = sky2->tx_ring + sky2->tx_cons; | 1245 | BUG_ON(nxt >= TX_RING_SIZE); |
1242 | struct sk_buff *skb; | ||
1243 | 1246 | ||
1244 | /* Check for partial status */ | 1247 | /* Check for partial status */ |
1245 | if (tx_dist(sky2->tx_cons, done) | 1248 | if (tx_dist(put, done) < tx_dist(put, nxt)) |
1246 | < tx_dist(sky2->tx_cons, re->idx)) | 1249 | break; |
1247 | goto out; | ||
1248 | 1250 | ||
1249 | skb = re->skb; | 1251 | skb = re->skb; |
1250 | pci_unmap_single(sky2->hw->pdev, | 1252 | pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr), |
1251 | pci_unmap_addr(re, mapaddr), | ||
1252 | skb_headlen(skb), PCI_DMA_TODEVICE); | 1253 | skb_headlen(skb), PCI_DMA_TODEVICE); |
1253 | 1254 | ||
1254 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 1255 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
1255 | struct tx_ring_info *fre; | 1256 | struct tx_ring_info *fre; |
1256 | fre = | 1257 | fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; |
1257 | sky2->tx_ring + (sky2->tx_cons + i + | 1258 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), |
1258 | 1) % TX_RING_SIZE; | 1259 | skb_shinfo(skb)->frags[i].size, |
1259 | pci_unmap_page(sky2->hw->pdev, | ||
1260 | pci_unmap_addr(fre, mapaddr), | ||
1261 | skb_shinfo(skb)->frags[i].size, | ||
1262 | PCI_DMA_TODEVICE); | 1260 | PCI_DMA_TODEVICE); |
1263 | } | 1261 | } |
1264 | 1262 | ||
1265 | dev_kfree_skb_any(skb); | 1263 | dev_kfree_skb_any(skb); |
1266 | |||
1267 | sky2->tx_cons = re->idx; | ||
1268 | } | 1264 | } |
1269 | out: | ||
1270 | 1265 | ||
1266 | spin_lock(&sky2->tx_lock); | ||
1267 | sky2->tx_cons = put; | ||
1271 | if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) | 1268 | if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) |
1272 | netif_wake_queue(dev); | 1269 | netif_wake_queue(dev); |
1273 | spin_unlock(&sky2->tx_lock); | 1270 | spin_unlock(&sky2->tx_lock); |
@@ -1742,7 +1739,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1742 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 1739 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
1743 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | 1740 | hwidx = sky2_read16(hw, STAT_PUT_IDX); |
1744 | BUG_ON(hwidx >= STATUS_RING_SIZE); | 1741 | BUG_ON(hwidx >= STATUS_RING_SIZE); |
1745 | rmb(); | 1742 | rmb(); |
1746 | 1743 | ||
1747 | while (hwidx != hw->st_idx) { | 1744 | while (hwidx != hw->st_idx) { |
1748 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1745 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |