Commit 6b81b193 authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller

hv_netvsc: Fix napi reschedule while receive completion is busy

If out ring is full temporarily and receive completion cannot go out,
we may still need to reschedule napi if certain conditions are met.
Otherwise the napi poll might be stopped forever, and cause network
disconnect.

Fixes: 7426b1a5 ("netvsc: optimize receive completions")
Signed-off-by: default avatarStephen Hemminger <stephen@networkplumber.org>
Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a2ec9d14
...@@ -1274,6 +1274,7 @@ int netvsc_poll(struct napi_struct *napi, int budget) ...@@ -1274,6 +1274,7 @@ int netvsc_poll(struct napi_struct *napi, int budget)
struct hv_device *device = netvsc_channel_to_device(channel); struct hv_device *device = netvsc_channel_to_device(channel);
struct net_device *ndev = hv_get_drvdata(device); struct net_device *ndev = hv_get_drvdata(device);
int work_done = 0; int work_done = 0;
int ret;
/* If starting a new interval */ /* If starting a new interval */
if (!nvchan->desc) if (!nvchan->desc)
...@@ -1285,16 +1286,18 @@ int netvsc_poll(struct napi_struct *napi, int budget) ...@@ -1285,16 +1286,18 @@ int netvsc_poll(struct napi_struct *napi, int budget)
nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc); nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc);
} }
/* If send of pending receive completions suceeded /* Send any pending receive completions */
* and did not exhaust NAPI budget this time ret = send_recv_completions(ndev, net_device, nvchan);
/* If it did not exhaust NAPI budget this time
* and not doing busy poll * and not doing busy poll
* then re-enable host interrupts * then re-enable host interrupts
* and reschedule if ring is not empty. * and reschedule if ring is not empty
* or sending receive completion failed.
*/ */
if (send_recv_completions(ndev, net_device, nvchan) == 0 && if (work_done < budget &&
work_done < budget &&
napi_complete_done(napi, work_done) && napi_complete_done(napi, work_done) &&
hv_end_read(&channel->inbound) && (ret || hv_end_read(&channel->inbound)) &&
napi_schedule_prep(napi)) { napi_schedule_prep(napi)) {
hv_begin_read(&channel->inbound); hv_begin_read(&channel->inbound);
__napi_schedule(napi); __napi_schedule(napi);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment