Change netpoll transmit logic so: * retries are per attempt not global. don't want to start drop packets just because of temporary blockage. * acquire xmit_lock correctly * if device is not available just drop * always queue if send fails, don't drop
Signed-off-by: Stephen Hemminger <[EMAIL PROTECTED]> --- netpoll.orig/include/linux/netpoll.h +++ netpoll/include/linux/netpoll.h @@ -27,7 +27,6 @@ struct netpoll { struct netpoll_info { spinlock_t poll_lock; int poll_owner; - int tries; int rx_flags; spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ --- netpoll.orig/net/core/netpoll.c +++ netpoll/net/core/netpoll.c @@ -250,50 +250,42 @@ static struct sk_buff * find_skb(struct static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { - int status; - struct netpoll_info *npinfo; - - if (!np || !np->dev || !netif_running(np->dev)) - goto free_skb; + struct net_device *dev = np->dev; + int tries = MAX_RETRIES; - npinfo = np->dev->npinfo; + do { + int status; - /* avoid recursion */ - if (npinfo->poll_owner == smp_processor_id() || - np->dev->xmit_lock_owner == smp_processor_id()) { - if (np->drop) - np->drop(skb); - else + /* if device is offline, give up */ + if (!netif_running(dev) || !netif_device_present(dev)) { __kfree_skb(skb); - return; - } + return; + } - do { - npinfo->tries--; - netif_tx_lock(np->dev); + /* grap tx lock, but avoid recursion problems */ + if (!netif_tx_trylock(dev)) + break; + + /* drivers do not expect to be called if queue is stopped. */ + if (netif_queue_stopped(dev)) + status = NETDEV_TX_BUSY; + else + status = dev->hard_start_xmit(skb, dev); + netif_tx_unlock(dev); - /* - * network drivers do not expect to be called if the queue is - * stopped. - */ - status = NETDEV_TX_BUSY; - if (!netif_queue_stopped(np->dev)) - status = np->dev->hard_start_xmit(skb, np->dev); - - netif_tx_unlock(np->dev); - - /* success */ - if(!status) { - npinfo->tries = MAX_RETRIES; /* reset */ + /* succesfull send */ + if (status == NETDEV_TX_OK) return; - } - /* transmit busy */ + /* transmit busy, maybe cleaning up will help */ netpoll_poll(np); udelay(50); - } while (npinfo->tries > 0); -free_skb: - __kfree_skb(skb); + } while (--tries > 0); + + if (np->drop) + np->drop(skb); + else + __kfree_skb(skb); } void netpoll_send_udp(struct netpoll *np, const char *msg, int len) @@ -646,7 +638,7 @@ int netpoll_setup(struct netpoll *np) npinfo->rx_np = NULL; spin_lock_init(&npinfo->poll_lock); npinfo->poll_owner = -1; - npinfo->tries = MAX_RETRIES; + spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); } else - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html