aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sky2.c35
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:
1227static void sky2_tx_complete(struct sky2_port *sky2, u16 done) 1227static 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 }
1269out:
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;