[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>
This commit is contained in:
committed by
Jeff Garzik
parent
13b97b74b9
commit
af2a58acb1
@@ -1227,6 +1227,8 @@ out_unlock:
|
|||||||
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)
|
|||||||
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;
|
skb_shinfo(skb)->frags[i].size,
|
||||||
pci_unmap_page(sky2->hw->pdev,
|
|
||||||
pci_unmap_addr(fre, mapaddr),
|
|
||||||
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);
|
||||||
@@ -1742,7 +1739,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
|
|||||||
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
|
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
|
||||||
hwidx = sky2_read16(hw, STAT_PUT_IDX);
|
hwidx = sky2_read16(hw, STAT_PUT_IDX);
|
||||||
BUG_ON(hwidx >= STATUS_RING_SIZE);
|
BUG_ON(hwidx >= STATUS_RING_SIZE);
|
||||||
rmb();
|
rmb();
|
||||||
|
|
||||||
while (hwidx != hw->st_idx) {
|
while (hwidx != hw->st_idx) {
|
||||||
struct sky2_status_le *le = hw->st_le + hw->st_idx;
|
struct sky2_status_le *le = hw->st_le + hw->st_idx;
|
||||||
|
Reference in New Issue
Block a user