Commit af2a58ac authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Jeff Garzik

[PATCH] sky2: transmit complete routine optimization

Hand optimize transmit completion routine.
Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 13b97b74
...@@ -1227,6 +1227,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -1227,6 +1227,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
static void sky2_tx_complete(struct sky2_port *sky2, u16 done) static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
{ {
struct net_device *dev = sky2->netdev; struct net_device *dev = sky2->netdev;
struct pci_dev *pdev = sky2->hw->pdev;
u16 nxt, put;
unsigned i; unsigned i;
BUG_ON(done >= TX_RING_SIZE); BUG_ON(done >= TX_RING_SIZE);
...@@ -1235,39 +1237,34 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) ...@@ -1235,39 +1237,34 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
printk(KERN_DEBUG "%s: tx done, up to %u\n", printk(KERN_DEBUG "%s: tx done, up to %u\n",
dev->name, done); dev->name, done);
spin_lock(&sky2->tx_lock); for (put = sky2->tx_cons; put != done; put = nxt) {
struct tx_ring_info *re = sky2->tx_ring + put;
struct sk_buff *skb = re->skb;
while (sky2->tx_cons != done) { nxt = re->idx;
struct tx_ring_info *re = sky2->tx_ring + sky2->tx_cons; BUG_ON(nxt >= TX_RING_SIZE);
struct sk_buff *skb;
/* Check for partial status */ /* Check for partial status */
if (tx_dist(sky2->tx_cons, done) if (tx_dist(put, done) < tx_dist(put, nxt))
< tx_dist(sky2->tx_cons, re->idx)) break;
goto out;
skb = re->skb; skb = re->skb;
pci_unmap_single(sky2->hw->pdev, pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr),
pci_unmap_addr(re, mapaddr),
skb_headlen(skb), PCI_DMA_TODEVICE); skb_headlen(skb), PCI_DMA_TODEVICE);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
struct tx_ring_info *fre; struct tx_ring_info *fre;
fre = fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE;
sky2->tx_ring + (sky2->tx_cons + i + pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
1) % TX_RING_SIZE;
pci_unmap_page(sky2->hw->pdev,
pci_unmap_addr(fre, mapaddr),
skb_shinfo(skb)->frags[i].size, skb_shinfo(skb)->frags[i].size,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
} }
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
sky2->tx_cons = re->idx;
} }
out:
spin_lock(&sky2->tx_lock);
sky2->tx_cons = put;
if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE)
netif_wake_queue(dev); netif_wake_queue(dev);
spin_unlock(&sky2->tx_lock); spin_unlock(&sky2->tx_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment