Message ID | 20180816153959.6489-1-marcelo.cerri@canonical.com |
---|---|
State | New |
Headers | show |
Series | [bionic/linux-azure] hv_netvsc: Fix napi reschedule while receive completion is busy | expand |
On 16/08/18 16:39, Marcelo Henrique Cerri wrote: > From: Haiyang Zhang <haiyangz@microsoft.com> > > BugLink: http://bugs.launchpad.net/bugs/1786313 > > 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: 7426b1a51803 ("netvsc: optimize receive completions") > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > (cherry picked from commit 6b81b193b83e87da1ea13217d684b54fccf8ee8a) > Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com> > --- > drivers/net/hyperv/netvsc.c | 17 ++++++++++------- > 1 file changed, 10 insertions(+), 7 deletions(-) > > diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c > index b500baf99eba..b2c3a28381b9 100644 > --- a/drivers/net/hyperv/netvsc.c > +++ b/drivers/net/hyperv/netvsc.c > @@ -1222,6 +1222,7 @@ int netvsc_poll(struct napi_struct *napi, int budget) > struct hv_device *device = netvsc_channel_to_device(channel); > struct net_device *ndev = hv_get_drvdata(device); > int work_done = 0; > + int ret; > > /* If starting a new interval */ > if (!nvchan->desc) > @@ -1233,16 +1234,18 @@ int netvsc_poll(struct napi_struct *napi, int budget) > nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc); > } > > - /* If send of pending receive completions suceeded > - * and did not exhaust NAPI budget this time > - * and not doing busy poll > + /* Send any pending receive completions */ > + ret = send_recv_completions(ndev, net_device, nvchan); > + > + /* If it did not exhaust NAPI budget this time > + * and not doing busy poll > * 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 && > - work_done < budget && > + if (work_done < budget && > napi_complete_done(napi, work_done) && > - hv_end_read(&channel->inbound) && > + (ret || hv_end_read(&channel->inbound)) && > napi_schedule_prep(napi)) { > hv_begin_read(&channel->inbound); > __napi_schedule(napi); > Looks OK, cherry pick etc. Acked-by: Colin Ian King <colin.king@canonical.com>
Acked-by: Kamal Mostafa <kamal@canonical.com> On Thu, Aug 16, 2018 at 12:39:59PM -0300, Marcelo Henrique Cerri wrote: > From: Haiyang Zhang <haiyangz@microsoft.com> > > BugLink: http://bugs.launchpad.net/bugs/1786313 > > 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: 7426b1a51803 ("netvsc: optimize receive completions") > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > (cherry picked from commit 6b81b193b83e87da1ea13217d684b54fccf8ee8a) > Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com> > --- > drivers/net/hyperv/netvsc.c | 17 ++++++++++------- > 1 file changed, 10 insertions(+), 7 deletions(-) > > diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c > index b500baf99eba..b2c3a28381b9 100644 > --- a/drivers/net/hyperv/netvsc.c > +++ b/drivers/net/hyperv/netvsc.c > @@ -1222,6 +1222,7 @@ int netvsc_poll(struct napi_struct *napi, int budget) > struct hv_device *device = netvsc_channel_to_device(channel); > struct net_device *ndev = hv_get_drvdata(device); > int work_done = 0; > + int ret; > > /* If starting a new interval */ > if (!nvchan->desc) > @@ -1233,16 +1234,18 @@ int netvsc_poll(struct napi_struct *napi, int budget) > nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc); > } > > - /* If send of pending receive completions suceeded > - * and did not exhaust NAPI budget this time > - * and not doing busy poll > + /* Send any pending receive completions */ > + ret = send_recv_completions(ndev, net_device, nvchan); > + > + /* If it did not exhaust NAPI budget this time > + * and not doing busy poll > * 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 && > - work_done < budget && > + if (work_done < budget && > napi_complete_done(napi, work_done) && > - hv_end_read(&channel->inbound) && > + (ret || hv_end_read(&channel->inbound)) && > napi_schedule_prep(napi)) { > hv_begin_read(&channel->inbound); > __napi_schedule(napi); > -- > 2.17.1 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index b500baf99eba..b2c3a28381b9 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -1222,6 +1222,7 @@ int netvsc_poll(struct napi_struct *napi, int budget) struct hv_device *device = netvsc_channel_to_device(channel); struct net_device *ndev = hv_get_drvdata(device); int work_done = 0; + int ret; /* If starting a new interval */ if (!nvchan->desc) @@ -1233,16 +1234,18 @@ int netvsc_poll(struct napi_struct *napi, int budget) nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc); } - /* If send of pending receive completions suceeded - * and did not exhaust NAPI budget this time - * and not doing busy poll + /* Send any pending receive completions */ + ret = send_recv_completions(ndev, net_device, nvchan); + + /* If it did not exhaust NAPI budget this time + * and not doing busy poll * 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 && - work_done < budget && + if (work_done < budget && napi_complete_done(napi, work_done) && - hv_end_read(&channel->inbound) && + (ret || hv_end_read(&channel->inbound)) && napi_schedule_prep(napi)) { hv_begin_read(&channel->inbound); __napi_schedule(napi);