aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netfront.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2014-12-16 13:59:46 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-16 15:21:54 -0500
commit6a6dc08ff6395f58be3ee568cb970ea956f16819 (patch)
tree6f43b7a7aec9429a7fb71af7d1d2f1d0bf68a566 /drivers/net/xen-netfront.c
parentf1fb521f7d94c35e278d76a9198f078223f26799 (diff)
xen-netfront: use napi_complete() correctly to prevent Rx stalling
After d75b1ade567ffab085e8adbbdacf0092d10cd09c (net: less interrupt masking in NAPI) the napi instance is removed from the per-cpu list prior to calling the n->poll(), and is only requeued if all of the budget was used. This inadvertently broke netfront because netfront does not use NAPI correctly. If netfront had not used all of its budget it would do a final check for any Rx responses and avoid calling napi_complete() if there were more responses. It would still return under budget so it would never be rescheduled. The final check would also not re-enable the Rx interrupt. Additionally, xenvif_poll() would also call napi_complete() /after/ enabling the interrupt. This resulted in a race between the napi_complete() and the napi_schedule() in the interrupt handler. The use of local_irq_save/restore() avoided by race iff the handler is running on the same CPU but not if it was running on a different CPU. Fix both of these by always calling napi_compete() if the budget was not all used, and then calling napi_schedule() if the final checks says there's more work. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netfront.c')
-rw-r--r--drivers/net/xen-netfront.c11
1 files changed, 3 insertions, 8 deletions
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 2f0a9ce9ff73..22bcb4e12e2a 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -977,7 +977,6 @@ static int xennet_poll(struct napi_struct *napi, int budget)
977 struct sk_buff_head rxq; 977 struct sk_buff_head rxq;
978 struct sk_buff_head errq; 978 struct sk_buff_head errq;
979 struct sk_buff_head tmpq; 979 struct sk_buff_head tmpq;
980 unsigned long flags;
981 int err; 980 int err;
982 981
983 spin_lock(&queue->rx_lock); 982 spin_lock(&queue->rx_lock);
@@ -1050,15 +1049,11 @@ err:
1050 if (work_done < budget) { 1049 if (work_done < budget) {
1051 int more_to_do = 0; 1050 int more_to_do = 0;
1052 1051
1053 napi_gro_flush(napi, false); 1052 napi_complete(napi);
1054
1055 local_irq_save(flags);
1056 1053
1057 RING_FINAL_CHECK_FOR_RESPONSES(&queue->rx, more_to_do); 1054 RING_FINAL_CHECK_FOR_RESPONSES(&queue->rx, more_to_do);
1058 if (!more_to_do) 1055 if (more_to_do)
1059 __napi_complete(napi); 1056 napi_schedule(napi);
1060
1061 local_irq_restore(flags);
1062 } 1057 }
1063 1058
1064 spin_unlock(&queue->rx_lock); 1059 spin_unlock(&queue->rx_lock);