The patch titled netpoll: use skb_buff_head for skb cache has been added to the -mm tree. Its filename is netpoll-use-skb_buff_head-for-skb-cache.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: netpoll: use skb_buff_head for skb cache From: Stephen Hemminger <shemminger@xxxxxxxx> The private skb cache should be managed with normal skb_buff_head rather than a DIY queue. If pool is exhausted, don't print anything that just makes the problem worse. After a number of attempts, punt and drop the message (callers handle it already). Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxx> Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- net/core/netpoll.c | 55 +++++++++++++++++-------------------------- 1 files changed, 22 insertions(+), 33 deletions(-) diff -puN net/core/netpoll.c~netpoll-use-skb_buff_head-for-skb-cache net/core/netpoll.c --- a/net/core/netpoll.c~netpoll-use-skb_buff_head-for-skb-cache +++ a/net/core/netpoll.c @@ -36,9 +36,7 @@ #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) #define MAX_RETRIES 20000 -static DEFINE_SPINLOCK(skb_list_lock); -static int nr_skbs; -static struct sk_buff *skbs; +static struct sk_buff_head skb_list; static atomic_t trapped; @@ -51,6 +49,7 @@ static atomic_t trapped; static void zap_completion_queue(void); static void arp_reply(struct sk_buff *skb); +static void refill_skbs(void); static void queue_process(void *p) { @@ -71,6 +70,7 @@ static void queue_process(void *p) dev_queue_xmit(skb); } + refill_skbs(); } static DECLARE_WORK(send_queue, queue_process, NULL); @@ -184,19 +184,14 @@ void netpoll_poll(struct netpoll *np) static void refill_skbs(void) { struct sk_buff *skb; - unsigned long flags; - spin_lock_irqsave(&skb_list_lock, flags); - while (nr_skbs < MAX_SKBS) { + while (skb_queue_len(&skb_list) < MAX_SKBS) { skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC); if (!skb) break; - skb->next = skbs; - skbs = skb; - nr_skbs++; + skb_queue_tail(&skb_list, skb); } - spin_unlock_irqrestore(&skb_list_lock, flags); } static void zap_completion_queue(void) @@ -226,37 +221,24 @@ static void zap_completion_queue(void) put_cpu_var(softnet_data); } -static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve) +static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve) { - int once = 1, count = 0; - unsigned long flags; - struct sk_buff *skb = NULL; + struct sk_buff *skb; + int tries = 0; zap_completion_queue(); -repeat: - if (nr_skbs < MAX_SKBS) - refill_skbs(); +repeat: skb = alloc_skb(len, GFP_ATOMIC); - - if (!skb) { - spin_lock_irqsave(&skb_list_lock, flags); - skb = skbs; - if (skb) { - skbs = skb->next; - skb->next = NULL; - nr_skbs--; - } - spin_unlock_irqrestore(&skb_list_lock, flags); - } + if (!skb) + skb = skb_dequeue(&skb_list); if(!skb) { - count++; - if (once && (count == 1000000)) { - printk("out of netpoll skbs!\n"); - once = 0; - } + if (++tries > MAX_RETRIES) + return NULL; + netpoll_poll(np); + tasklet_schedule(&np->dev->npinfo->tx_task); goto repeat; } @@ -638,6 +620,13 @@ int netpoll_parse_options(struct netpoll return -1; } +static __init int netpoll_init(void) +{ + skb_queue_head_init(&skb_list); + return 0; +} +core_initcall(netpoll_init); + int netpoll_setup(struct netpoll *np) { struct net_device *ndev = NULL; _ Patches currently in -mm which might be from shemminger@xxxxxxxx are origin.patch git-netdev-all.patch bonding-lockdep-annotation.patch netpoll-retry-memory-leak.patch netpoll-initialize-skb-for-udp.patch netpoll-rework-skb-transmit-queue.patch netpoll-use-skb_buff_head-for-skb-cache.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html