netpoll deferred transmit path
When the netpoll beast got busy, he tended to babble. Instead of talking out of his large mouth as normal, he tended to try to snort out other orifices. This lead to words (skbs) ending up in odd places (like NIT) that he did not intend. The normal way of talking wouldn't work, but he could at least change to using the same tone all the time. Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
This commit is contained in:
parent
b41848b61b
commit
6c43ff18f9
1 changed files with 19 additions and 2 deletions
|
@ -55,9 +55,25 @@ static void queue_process(void *p)
|
|||
struct netpoll_info *npinfo = p;
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&npinfo->txq)))
|
||||
dev_queue_xmit(skb);
|
||||
while ((skb = skb_dequeue(&npinfo->txq))) {
|
||||
struct net_device *dev = skb->dev;
|
||||
|
||||
if (!netif_device_present(dev) || !netif_running(dev)) {
|
||||
__kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
netif_tx_lock_bh(dev);
|
||||
if (netif_queue_stopped(dev) ||
|
||||
dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
|
||||
skb_queue_head(&npinfo->txq, skb);
|
||||
netif_tx_unlock_bh(dev);
|
||||
|
||||
schedule_delayed_work(&npinfo->tx_work, HZ/10);
|
||||
return;
|
||||
}
|
||||
netif_tx_unlock_bh(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void netpoll_queue(struct sk_buff *skb)
|
||||
|
@ -765,6 +781,7 @@ void netpoll_cleanup(struct netpoll *np)
|
|||
if (atomic_dec_and_test(&npinfo->refcnt)) {
|
||||
skb_queue_purge(&npinfo->arp_tx);
|
||||
skb_queue_purge(&npinfo->txq);
|
||||
cancel_rearming_delayed_work(&npinfo->tx_work);
|
||||
flush_scheduled_work();
|
||||
|
||||
kfree(npinfo);
|
||||
|
|
Loading…
Reference in a new issue