diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 20 | 
1 files changed, 15 insertions, 5 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 683d493aa1bf..171420e75b03 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7072,10 +7072,20 @@ static int dev_cpu_callback(struct notifier_block *nfb,  		oldsd->output_queue = NULL;  		oldsd->output_queue_tailp = &oldsd->output_queue;  	} -	/* Append NAPI poll list from offline CPU. */ -	if (!list_empty(&oldsd->poll_list)) { -		list_splice_init(&oldsd->poll_list, &sd->poll_list); -		raise_softirq_irqoff(NET_RX_SOFTIRQ); +	/* Append NAPI poll list from offline CPU, with one exception : +	 * process_backlog() must be called by cpu owning percpu backlog. +	 * We properly handle process_queue & input_pkt_queue later. +	 */ +	while (!list_empty(&oldsd->poll_list)) { +		struct napi_struct *napi = list_first_entry(&oldsd->poll_list, +							    struct napi_struct, +							    poll_list); + +		list_del_init(&napi->poll_list); +		if (napi->poll == process_backlog) +			napi->state = 0; +		else +			____napi_schedule(sd, napi);  	}  	raise_softirq_irqoff(NET_TX_SOFTIRQ); @@ -7086,7 +7096,7 @@ static int dev_cpu_callback(struct notifier_block *nfb,  		netif_rx_internal(skb);  		input_queue_head_incr(oldsd);  	} -	while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { +	while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) {  		netif_rx_internal(skb);  		input_queue_head_incr(oldsd);  	}  | 
