* [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll @ 2026-06-15 9:45 Longjun Tang 2026-06-15 10:01 ` Xuan Zhuo 0 siblings, 1 reply; 10+ messages in thread From: Longjun Tang @ 2026-06-15 9:45 UTC (permalink / raw) To: mst, jasowang Cc: edumazet, kuba, xuanzhuo, virtualization, lange_tang, tanglongjun From: Longjun Tang <tanglongjun@kylinos.cn> When busy-poll is active, napi_schedule_prep() returns false in skb_recv_done(), so virtqueue_disable_cb() is skipped. The device may keep firing irqs until the next poll round reaches virtqueue_napi_complete(). If cb is enabled under busy-poll case, it will lead to a large number of spurious interrupts. Explicitly disable callbacks in this case to prevent spurious interrupts. Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> --- drivers/net/virtio_net.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f4adcfee7a80..6d675fddc59b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, if (napi_schedule_prep(napi)) { virtqueue_disable_cb(vq); __napi_schedule(napi); + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { + virtqueue_disable_cb(vq); } } -- 2.25.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-15 9:45 [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll Longjun Tang @ 2026-06-15 10:01 ` Xuan Zhuo 2026-06-16 3:00 ` Lange Tang 0 siblings, 1 reply; 10+ messages in thread From: Xuan Zhuo @ 2026-06-15 10:01 UTC (permalink / raw) To: Longjun Tang Cc: edumazet, kuba, virtualization, lange_tang, tanglongjun, mst, jasowang On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: > From: Longjun Tang <tanglongjun@kylinos.cn> > > When busy-poll is active, napi_schedule_prep() returns false in > skb_recv_done(), so virtqueue_disable_cb() is skipped. The device > may keep firing irqs until the next poll round reaches > virtqueue_napi_complete(). If cb is enabled under busy-poll case, > it will lead to a large number of spurious interrupts. Explicitly > disable callbacks in this case to prevent spurious interrupts. > > Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> > --- > drivers/net/virtio_net.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > index f4adcfee7a80..6d675fddc59b 100644 > --- a/drivers/net/virtio_net.c > +++ b/drivers/net/virtio_net.c > @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, > if (napi_schedule_prep(napi)) { > virtqueue_disable_cb(vq); > __napi_schedule(napi); > + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { > + virtqueue_disable_cb(vq); I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the drivers. The NIC driver should remain agnostic to busy polling. I think we need a better way, maybe we should rewrite virtqueue_napi_schedule instead. Thanks. > } > } > > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-15 10:01 ` Xuan Zhuo @ 2026-06-16 3:00 ` Lange Tang 2026-06-16 3:27 ` Xuan Zhuo 0 siblings, 1 reply; 10+ messages in thread From: Lange Tang @ 2026-06-16 3:00 UTC (permalink / raw) To: xuanzhuo@linux.alibaba.com, mst@redhat.com Cc: edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: >> From: Longjun Tang <tanglongjun@kylinos.cn> >> >> When busy-poll is active, napi_schedule_prep() returns false in >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device >> may keep firing irqs until the next poll round reaches >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, >> it will lead to a large number of spurious interrupts. Explicitly >> disable callbacks in this case to prevent spurious interrupts. >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> >> --- >> drivers/net/virtio_net.c | 2 ++ >> 1 file changed, 2 insertions(+) >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c >> index f4adcfee7a80..6d675fddc59b 100644 >> --- a/drivers/net/virtio_net.c >> +++ b/drivers/net/virtio_net.c >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, >> if (napi_schedule_prep(napi)) { >> virtqueue_disable_cb(vq); >> __napi_schedule(napi); >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { >> + virtqueue_disable_cb(vq); > >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the >drivers. The NIC driver should remain agnostic to busy polling. I think we need >a better way, maybe we should rewrite virtqueue_napi_schedule instead. How about rewrite it like this? static void virtqueue_napi_schedule(struct napi_struct *napi, struct virtqueue *vq) { virtqueue_disable_cb(vq); if (napi_schedule_prep(napi)) __napi_schedule(napi); } Any comments are welcome. > >Thanks. > >> } >> } >> >> -- >> 2.25.1 >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-16 3:00 ` Lange Tang @ 2026-06-16 3:27 ` Xuan Zhuo 2026-06-16 6:07 ` Lange Tang 0 siblings, 1 reply; 10+ messages in thread From: Xuan Zhuo @ 2026-06-16 3:27 UTC (permalink / raw) To: Lange Tang Cc: edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com, mst@redhat.com On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: > >> From: Longjun Tang <tanglongjun@kylinos.cn> > >> > >> When busy-poll is active, napi_schedule_prep() returns false in > >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device > >> may keep firing irqs until the next poll round reaches > >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, > >> it will lead to a large number of spurious interrupts. Explicitly > >> disable callbacks in this case to prevent spurious interrupts. > >> > >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> > >> --- > >> drivers/net/virtio_net.c | 2 ++ > >> 1 file changed, 2 insertions(+) > >> > >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > >> index f4adcfee7a80..6d675fddc59b 100644 > >> --- a/drivers/net/virtio_net.c > >> +++ b/drivers/net/virtio_net.c > >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, > >> if (napi_schedule_prep(napi)) { > >> virtqueue_disable_cb(vq); > >> __napi_schedule(napi); > >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { > >> + virtqueue_disable_cb(vq); > > > >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the > >drivers. The NIC driver should remain agnostic to busy polling. I think we need > >a better way, maybe we should rewrite virtqueue_napi_schedule instead. > > How about rewrite it like this? > static void virtqueue_napi_schedule(struct napi_struct *napi, > struct virtqueue *vq) > { > virtqueue_disable_cb(vq); > if (napi_schedule_prep(napi)) > __napi_schedule(napi); > } > Any comments are welcome. Another CPU could be running NAPI and has just enabled the callbacks (cb). Meanwhile, this side unconditionally disables the cb. Since NAPI on the other CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to re-enable the cb. Thanks. > > > >Thanks. > > > >> } > >> } > >> > >> -- > >> 2.25.1 > >> > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re:Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-16 3:27 ` Xuan Zhuo @ 2026-06-16 6:07 ` Lange Tang 2026-06-16 6:49 ` Xuan Zhuo 0 siblings, 1 reply; 10+ messages in thread From: Lange Tang @ 2026-06-16 6:07 UTC (permalink / raw) To: xuanzhuo@linux.alibaba.com, mst@redhat.com Cc: edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com At 2026-06-16 11:27:12, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: >> At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >> >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: >> >> From: Longjun Tang <tanglongjun@kylinos.cn> >> >> >> >> When busy-poll is active, napi_schedule_prep() returns false in >> >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device >> >> may keep firing irqs until the next poll round reaches >> >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, >> >> it will lead to a large number of spurious interrupts. Explicitly >> >> disable callbacks in this case to prevent spurious interrupts. >> >> >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> >> >> --- >> >> drivers/net/virtio_net.c | 2 ++ >> >> 1 file changed, 2 insertions(+) >> >> >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c >> >> index f4adcfee7a80..6d675fddc59b 100644 >> >> --- a/drivers/net/virtio_net.c >> >> +++ b/drivers/net/virtio_net.c >> >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, >> >> if (napi_schedule_prep(napi)) { >> >> virtqueue_disable_cb(vq); >> >> __napi_schedule(napi); >> >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { >> >> + virtqueue_disable_cb(vq); >> > >> >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the >> >drivers. The NIC driver should remain agnostic to busy polling. I think we need >> >a better way, maybe we should rewrite virtqueue_napi_schedule instead. >> >> How about rewrite it like this? >> static void virtqueue_napi_schedule(struct napi_struct *napi, >> struct virtqueue *vq) >> { >> virtqueue_disable_cb(vq); >> if (napi_schedule_prep(napi)) >> __napi_schedule(napi); >> } >> Any comments are welcome. > > >Another CPU could be running NAPI and has just enabled the callbacks (cb). >Meanwhile, this side unconditionally disables the cb. Since NAPI on the other >CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to >re-enable the cb. > >Thanks. Regarding the case you described, when NAPI on another CPU exits, the virtqueue_napi_complete func will be executed to re-enable cb. and if there is still unconsumed data in the virtqueue, virtqueue_napi_schedule will be called again to schedule NAPI. In summary, I think that the disable_cb and __napi_schedule within the virtqueue_napi_schedule func do not need to be bound together. Any comments are welcome. Thinks. > > >> > >> > >> >> } >> >> } >> >> >> >> -- >> >> 2.25.1 >> >> >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re:Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-16 6:07 ` Lange Tang @ 2026-06-16 6:49 ` Xuan Zhuo 2026-06-17 2:08 ` Lange Tang 2026-08-10 7:51 ` Michael S. Tsirkin 0 siblings, 2 replies; 10+ messages in thread From: Xuan Zhuo @ 2026-06-16 6:49 UTC (permalink / raw) To: Lange Tang Cc: edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com, mst@redhat.com On Tue, 16 Jun 2026 14:07:34 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > At 2026-06-16 11:27:12, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > >On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > >> At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > >> >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: > >> >> From: Longjun Tang <tanglongjun@kylinos.cn> > >> >> > >> >> When busy-poll is active, napi_schedule_prep() returns false in > >> >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device > >> >> may keep firing irqs until the next poll round reaches > >> >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, > >> >> it will lead to a large number of spurious interrupts. Explicitly > >> >> disable callbacks in this case to prevent spurious interrupts. > >> >> > >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> > >> >> --- > >> >> drivers/net/virtio_net.c | 2 ++ > >> >> 1 file changed, 2 insertions(+) > >> >> > >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > >> >> index f4adcfee7a80..6d675fddc59b 100644 > >> >> --- a/drivers/net/virtio_net.c > >> >> +++ b/drivers/net/virtio_net.c > >> >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, > >> >> if (napi_schedule_prep(napi)) { > >> >> virtqueue_disable_cb(vq); > >> >> __napi_schedule(napi); > >> >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { > >> >> + virtqueue_disable_cb(vq); > >> > > >> >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the > >> >drivers. The NIC driver should remain agnostic to busy polling. I think we need > >> >a better way, maybe we should rewrite virtqueue_napi_schedule instead. > >> > >> How about rewrite it like this? > >> static void virtqueue_napi_schedule(struct napi_struct *napi, > >> struct virtqueue *vq) > >> { > >> virtqueue_disable_cb(vq); > >> if (napi_schedule_prep(napi)) > >> __napi_schedule(napi); > >> } > >> Any comments are welcome. > > > > > >Another CPU could be running NAPI and has just enabled the callbacks (cb). > >Meanwhile, this side unconditionally disables the cb. Since NAPI on the other > >CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to > >re-enable the cb. > > > >Thanks. > > Regarding the case you described, when NAPI on another CPU exits, the virtqueue_napi_complete func > will be executed to re-enable cb. and if there is still unconsumed data in the virtqueue, virtqueue_napi_schedule > will be called again to schedule NAPI. > > In summary, I think that the disable_cb and __napi_schedule within the virtqueue_napi_schedule func do not need to be bound together. > > Any comments are welcome. Thinks. <Your code> static void virtqueue_napi_schedule(struct napi_struct *napi, struct virtqueue *vq) { |static bool virtqueue_napi_complete(struct napi_struct *napi, | struct virtqueue *vq, int processed) |{ | int opaque; | | opaque = virtqueue_enable_cb_prepare(vq); | virtqueue_disable_cb(vq); | if (napi_schedule_prep(napi)) | __napi_schedule(napi); | | if (napi_complete_done(napi, processed)) { | if (unlikely(virtqueue_poll(vq, opaque))) | virtqueue_napi_schedule(napi, vq); | else | return true; // return directly | } else { | virtqueue_disable_cb(vq); | } | | return false; |} } 1. new packets (notified by irq) are consumed by napi before virtqueue_napi_complete 2. poll is not called by irq, maybe xsk wake up. So irq is not disabled. Thanks. > > > > > > >> > > >> > > >> >> } > >> >> } > >> >> > >> >> -- > >> >> 2.25.1 > >> >> > >> > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re:Re:Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-16 6:49 ` Xuan Zhuo @ 2026-06-17 2:08 ` Lange Tang 2026-08-10 7:13 ` Michael S. Tsirkin 2026-08-10 7:51 ` Michael S. Tsirkin 1 sibling, 1 reply; 10+ messages in thread From: Lange Tang @ 2026-06-17 2:08 UTC (permalink / raw) To: xuanzhuo@linux.alibaba.com Cc: edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com, mst@redhat.com At 2026-06-16 14:49:25, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >On Tue, 16 Jun 2026 14:07:34 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: >> At 2026-06-16 11:27:12, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >> >On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: >> >> At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >> >> >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: >> >> >> From: Longjun Tang <tanglongjun@kylinos.cn> >> >> >> >> >> >> When busy-poll is active, napi_schedule_prep() returns false in >> >> >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device >> >> >> may keep firing irqs until the next poll round reaches >> >> >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, >> >> >> it will lead to a large number of spurious interrupts. Explicitly >> >> >> disable callbacks in this case to prevent spurious interrupts. >> >> >> >> >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> >> >> >> --- >> >> >> drivers/net/virtio_net.c | 2 ++ >> >> >> 1 file changed, 2 insertions(+) >> >> >> >> >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c >> >> >> index f4adcfee7a80..6d675fddc59b 100644 >> >> >> --- a/drivers/net/virtio_net.c >> >> >> +++ b/drivers/net/virtio_net.c >> >> >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, >> >> >> if (napi_schedule_prep(napi)) { >> >> >> virtqueue_disable_cb(vq); >> >> >> __napi_schedule(napi); >> >> >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { >> >> >> + virtqueue_disable_cb(vq); >> >> > >> >> >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the >> >> >drivers. The NIC driver should remain agnostic to busy polling. I think we need >> >> >a better way, maybe we should rewrite virtqueue_napi_schedule instead. >> >> >> >> How about rewrite it like this? >> >> static void virtqueue_napi_schedule(struct napi_struct *napi, >> >> struct virtqueue *vq) >> >> { >> >> virtqueue_disable_cb(vq); >> >> if (napi_schedule_prep(napi)) >> >> __napi_schedule(napi); >> >> } >> >> Any comments are welcome. >> > >> > >> >Another CPU could be running NAPI and has just enabled the callbacks (cb). >> >Meanwhile, this side unconditionally disables the cb. Since NAPI on the other >> >CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to >> >re-enable the cb. >> > >> >Thanks. >> >> Regarding the case you described, when NAPI on another CPU exits, the virtqueue_napi_complete func >> will be executed to re-enable cb. and if there is still unconsumed data in the virtqueue, virtqueue_napi_schedule >> will be called again to schedule NAPI. >> >> In summary, I think that the disable_cb and __napi_schedule within the virtqueue_napi_schedule func do not need to be bound together. >> >> Any comments are welcome. Thinks. > > ><Your code> >static void virtqueue_napi_schedule(struct napi_struct *napi, > struct virtqueue *vq) >{ > > |static bool virtqueue_napi_complete(struct napi_struct *napi, > | struct virtqueue *vq, int processed) > |{ > | int opaque; > | > | opaque = virtqueue_enable_cb_prepare(vq); > | > virtqueue_disable_cb(vq); | > if (napi_schedule_prep(napi)) | > __napi_schedule(napi); | > | if (napi_complete_done(napi, processed)) { > | if (unlikely(virtqueue_poll(vq, opaque))) > | virtqueue_napi_schedule(napi, vq); > | else > | return true; // return directly > | } else { > | virtqueue_disable_cb(vq); > | } > | > | return false; > |} >} > >1. new packets (notified by irq) are consumed by napi before virtqueue_napi_complete >2. poll is not called by irq, maybe xsk wake up. So irq is not disabled. > > >Thanks. Based on your code analysis above, I got . thanks. disable_cb and __napi_schedule in the virtqueue_napi_schedule func indeed cannot be separated. Regarding the issue of not being able to disable cb in a busy-poll context, do you have any suggestions? Any comments are welcome. Thanks. > > >> >> > >> > >> >> > >> >> > >> >> >> } >> >> >> } >> >> >> >> >> >> -- >> >> >> 2.25.1 >> >> >> >> >> >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Re:Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-17 2:08 ` Lange Tang @ 2026-08-10 7:13 ` Michael S. Tsirkin 2026-08-10 9:20 ` Lange Tang 0 siblings, 1 reply; 10+ messages in thread From: Michael S. Tsirkin @ 2026-08-10 7:13 UTC (permalink / raw) To: Lange Tang Cc: xuanzhuo@linux.alibaba.com, edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com On Wed, Jun 17, 2026 at 10:08:55AM +0800, Lange Tang wrote: > At 2026-06-16 14:49:25, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > >On Tue, 16 Jun 2026 14:07:34 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > >> At 2026-06-16 11:27:12, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > >> >On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > >> >> At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > >> >> >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: > >> >> >> From: Longjun Tang <tanglongjun@kylinos.cn> > >> >> >> > >> >> >> When busy-poll is active, napi_schedule_prep() returns false in > >> >> >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device > >> >> >> may keep firing irqs until the next poll round reaches > >> >> >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, > >> >> >> it will lead to a large number of spurious interrupts. Explicitly > >> >> >> disable callbacks in this case to prevent spurious interrupts. > >> >> >> > >> >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> > >> >> >> --- > >> >> >> drivers/net/virtio_net.c | 2 ++ > >> >> >> 1 file changed, 2 insertions(+) > >> >> >> > >> >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > >> >> >> index f4adcfee7a80..6d675fddc59b 100644 > >> >> >> --- a/drivers/net/virtio_net.c > >> >> >> +++ b/drivers/net/virtio_net.c > >> >> >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, > >> >> >> if (napi_schedule_prep(napi)) { > >> >> >> virtqueue_disable_cb(vq); > >> >> >> __napi_schedule(napi); > >> >> >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { > >> >> >> + virtqueue_disable_cb(vq); > >> >> > > >> >> >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the > >> >> >drivers. The NIC driver should remain agnostic to busy polling. I think we need > >> >> >a better way, maybe we should rewrite virtqueue_napi_schedule instead. > >> >> > >> >> How about rewrite it like this? > >> >> static void virtqueue_napi_schedule(struct napi_struct *napi, > >> >> struct virtqueue *vq) > >> >> { > >> >> virtqueue_disable_cb(vq); > >> >> if (napi_schedule_prep(napi)) > >> >> __napi_schedule(napi); > >> >> } > >> >> Any comments are welcome. > >> > > >> > > >> >Another CPU could be running NAPI and has just enabled the callbacks (cb). > >> >Meanwhile, this side unconditionally disables the cb. Since NAPI on the other > >> >CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to > >> >re-enable the cb. > >> > > >> >Thanks. > >> > >> Regarding the case you described, when NAPI on another CPU exits, the virtqueue_napi_complete func > >> will be executed to re-enable cb. and if there is still unconsumed data in the virtqueue, virtqueue_napi_schedule > >> will be called again to schedule NAPI. > >> > >> In summary, I think that the disable_cb and __napi_schedule within the virtqueue_napi_schedule func do not need to be bound together. > >> > >> Any comments are welcome. Thinks. > > > > > ><Your code> > >static void virtqueue_napi_schedule(struct napi_struct *napi, > > struct virtqueue *vq) > >{ > > > > |static bool virtqueue_napi_complete(struct napi_struct *napi, > > | struct virtqueue *vq, int processed) > > |{ > > | int opaque; > > | > > | opaque = virtqueue_enable_cb_prepare(vq); > > | > > virtqueue_disable_cb(vq); | > > if (napi_schedule_prep(napi)) | > > __napi_schedule(napi); | > > | if (napi_complete_done(napi, processed)) { > > | if (unlikely(virtqueue_poll(vq, opaque))) > > | virtqueue_napi_schedule(napi, vq); > > | else > > | return true; // return directly > > | } else { > > | virtqueue_disable_cb(vq); > > | } > > | > > | return false; > > |} > >} > > > >1. new packets (notified by irq) are consumed by napi before virtqueue_napi_complete > >2. poll is not called by irq, maybe xsk wake up. So irq is not disabled. > > > > > >Thanks. > > Based on your code analysis above, I got . thanks. > disable_cb and __napi_schedule in the virtqueue_napi_schedule func indeed cannot be separated. > > Regarding the issue of not being able to disable cb in a busy-poll context, do you have any suggestions? > > Any comments are welcome. Thanks. Add a netdev core API that basically does: test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state) add documentation, either netdev maintainers merge it, or alternatively they will tell you what to do) > > > > > >> > >> > > >> > > >> >> > > >> >> > > >> >> >> } > >> >> >> } > >> >> >> > >> >> >> -- > >> >> >> 2.25.1 > >> >> >> > >> >> > >> > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re:Re: Re:Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-08-10 7:13 ` Michael S. Tsirkin @ 2026-08-10 9:20 ` Lange Tang 0 siblings, 0 replies; 10+ messages in thread From: Lange Tang @ 2026-08-10 9:20 UTC (permalink / raw) To: mst@redhat.com Cc: xuanzhuo@linux.alibaba.com, edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com At 2026-08-10 15:13:14, "Michael S. Tsirkin" <mst@redhat.com> wrote: >On Wed, Jun 17, 2026 at 10:08:55AM +0800, Lange Tang wrote: >> At 2026-06-16 14:49:25, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >> >On Tue, 16 Jun 2026 14:07:34 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: >> >> At 2026-06-16 11:27:12, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >> >> >On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: >> >> >> At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: >> >> >> >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: >> >> >> >> From: Longjun Tang <tanglongjun@kylinos.cn> >> >> >> >> >> >> >> >> When busy-poll is active, napi_schedule_prep() returns false in >> >> >> >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device >> >> >> >> may keep firing irqs until the next poll round reaches >> >> >> >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, >> >> >> >> it will lead to a large number of spurious interrupts. Explicitly >> >> >> >> disable callbacks in this case to prevent spurious interrupts. >> >> >> >> >> >> >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> >> >> >> >> --- >> >> >> >> drivers/net/virtio_net.c | 2 ++ >> >> >> >> 1 file changed, 2 insertions(+) >> >> >> >> >> >> >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c >> >> >> >> index f4adcfee7a80..6d675fddc59b 100644 >> >> >> >> --- a/drivers/net/virtio_net.c >> >> >> >> +++ b/drivers/net/virtio_net.c >> >> >> >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, >> >> >> >> if (napi_schedule_prep(napi)) { >> >> >> >> virtqueue_disable_cb(vq); >> >> >> >> __napi_schedule(napi); >> >> >> >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { >> >> >> >> + virtqueue_disable_cb(vq); >> >> >> > >> >> >> >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the >> >> >> >drivers. The NIC driver should remain agnostic to busy polling. I think we need >> >> >> >a better way, maybe we should rewrite virtqueue_napi_schedule instead. >> >> >> >> >> >> How about rewrite it like this? >> >> >> static void virtqueue_napi_schedule(struct napi_struct *napi, >> >> >> struct virtqueue *vq) >> >> >> { >> >> >> virtqueue_disable_cb(vq); >> >> >> if (napi_schedule_prep(napi)) >> >> >> __napi_schedule(napi); >> >> >> } >> >> >> Any comments are welcome. >> >> > >> >> > >> >> >Another CPU could be running NAPI and has just enabled the callbacks (cb). >> >> >Meanwhile, this side unconditionally disables the cb. Since NAPI on the other >> >> >CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to >> >> >re-enable the cb. >> >> > >> >> >Thanks. >> >> >> >> Regarding the case you described, when NAPI on another CPU exits, the virtqueue_napi_complete func >> >> will be executed to re-enable cb. and if there is still unconsumed data in the virtqueue, virtqueue_napi_schedule >> >> will be called again to schedule NAPI. >> >> >> >> In summary, I think that the disable_cb and __napi_schedule within the virtqueue_napi_schedule func do not need to be bound together. >> >> >> >> Any comments are welcome. Thinks. >> > >> > >> ><Your code> >> >static void virtqueue_napi_schedule(struct napi_struct *napi, >> > struct virtqueue *vq) >> >{ >> > >> > |static bool virtqueue_napi_complete(struct napi_struct *napi, >> > | struct virtqueue *vq, int processed) >> > |{ >> > | int opaque; >> > | >> > | opaque = virtqueue_enable_cb_prepare(vq); >> > | >> > virtqueue_disable_cb(vq); | >> > if (napi_schedule_prep(napi)) | >> > __napi_schedule(napi); | >> > | if (napi_complete_done(napi, processed)) { >> > | if (unlikely(virtqueue_poll(vq, opaque))) >> > | virtqueue_napi_schedule(napi, vq); >> > | else >> > | return true; // return directly >> > | } else { >> > | virtqueue_disable_cb(vq); >> > | } >> > | >> > | return false; >> > |} >> >} >> > >> >1. new packets (notified by irq) are consumed by napi before virtqueue_napi_complete >> >2. poll is not called by irq, maybe xsk wake up. So irq is not disabled. >> > >> > >> >Thanks. >> >> Based on your code analysis above, I got . thanks. >> disable_cb and __napi_schedule in the virtqueue_napi_schedule func indeed cannot be separated. >> >> Regarding the issue of not being able to disable cb in a busy-poll context, do you have any suggestions? >> >> Any comments are welcome. Thanks. > > >Add a netdev core API that basically does: > >test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state) > >add documentation, either netdev maintainers merge it, or >alternatively they will tell you what to do) This issue has already been fixed with https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1eb8fc67ca41db71c90866ff76c990d85247daef, and it was merged. so maybe netdev core API no longer needed. thanks. Lange > >> > >> > >> >> >> >> > >> >> > >> >> >> > >> >> >> > >> >> >> >> } >> >> >> >> } >> >> >> >> >> >> >> >> -- >> >> >> >> 2.25.1 >> >> >> >> >> >> >> >> >> >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Re:Re: [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll 2026-06-16 6:49 ` Xuan Zhuo 2026-06-17 2:08 ` Lange Tang @ 2026-08-10 7:51 ` Michael S. Tsirkin 1 sibling, 0 replies; 10+ messages in thread From: Michael S. Tsirkin @ 2026-08-10 7:51 UTC (permalink / raw) To: Xuan Zhuo Cc: Lange Tang, edumazet@google.com, Jakub Kicinski, virtualization@lists.linux.dev, Tang Longjun, jasowang@redhat.com On Tue, Jun 16, 2026 at 02:49:25PM +0800, Xuan Zhuo wrote: > On Tue, 16 Jun 2026 14:07:34 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > > At 2026-06-16 11:27:12, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > > >On Tue, 16 Jun 2026 11:00:29 +0800 (CST), Lange Tang <lange_tang@163.com> wrote: > > >> At 2026-06-15 18:01:40, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com> wrote: > > >> >On Mon, 15 Jun 2026 17:45:50 +0800, Longjun Tang <lange_tang@163.com> wrote: > > >> >> From: Longjun Tang <tanglongjun@kylinos.cn> > > >> >> > > >> >> When busy-poll is active, napi_schedule_prep() returns false in > > >> >> skb_recv_done(), so virtqueue_disable_cb() is skipped. The device > > >> >> may keep firing irqs until the next poll round reaches > > >> >> virtqueue_napi_complete(). If cb is enabled under busy-poll case, > > >> >> it will lead to a large number of spurious interrupts. Explicitly > > >> >> disable callbacks in this case to prevent spurious interrupts. > > >> >> > > >> >> Signed-off-by: Longjun Tang <tanglongjun@kylinos.cn> > > >> >> --- > > >> >> drivers/net/virtio_net.c | 2 ++ > > >> >> 1 file changed, 2 insertions(+) > > >> >> > > >> >> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > > >> >> index f4adcfee7a80..6d675fddc59b 100644 > > >> >> --- a/drivers/net/virtio_net.c > > >> >> +++ b/drivers/net/virtio_net.c > > >> >> @@ -728,6 +728,8 @@ static void virtqueue_napi_schedule(struct napi_struct *napi, > > >> >> if (napi_schedule_prep(napi)) { > > >> >> virtqueue_disable_cb(vq); > > >> >> __napi_schedule(napi); > > >> >> + } else if (test_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state)) { > > >> >> + virtqueue_disable_cb(vq); > > >> > > > >> >I see, but we should avoid checking NAPI_STATE_IN_BUSY_POLL directly in the > > >> >drivers. The NIC driver should remain agnostic to busy polling. I think we need > > >> >a better way, maybe we should rewrite virtqueue_napi_schedule instead. > > >> > > >> How about rewrite it like this? > > >> static void virtqueue_napi_schedule(struct napi_struct *napi, > > >> struct virtqueue *vq) > > >> { > > >> virtqueue_disable_cb(vq); > > >> if (napi_schedule_prep(napi)) > > >> __napi_schedule(napi); > > >> } > > >> Any comments are welcome. > > > > > > > > >Another CPU could be running NAPI and has just enabled the callbacks (cb). > > >Meanwhile, this side unconditionally disables the cb. Since NAPI on the other > > >CPU hasn't exited yet, the subsequent prep on this side fails, leaving no one to > > >re-enable the cb. > > > > > >Thanks. > > > > Regarding the case you described, when NAPI on another CPU exits, the virtqueue_napi_complete func > > will be executed to re-enable cb. and if there is still unconsumed data in the virtqueue, virtqueue_napi_schedule > > will be called again to schedule NAPI. > > > > In summary, I think that the disable_cb and __napi_schedule within the virtqueue_napi_schedule func do not need to be bound together. > > > > Any comments are welcome. Thinks. > > > <Your code> > static void virtqueue_napi_schedule(struct napi_struct *napi, > struct virtqueue *vq) > { > > |static bool virtqueue_napi_complete(struct napi_struct *napi, > | struct virtqueue *vq, int processed) > |{ > | int opaque; > | > | opaque = virtqueue_enable_cb_prepare(vq); > | > virtqueue_disable_cb(vq); | > if (napi_schedule_prep(napi)) | > __napi_schedule(napi); | > | if (napi_complete_done(napi, processed)) { > | if (unlikely(virtqueue_poll(vq, opaque))) > | virtqueue_napi_schedule(napi, vq); > | else > | return true; // return directly > | } else { > | virtqueue_disable_cb(vq); > | } > | > | return false; > |} > } > > 1. new packets (notified by irq) are consumed by napi before virtqueue_napi_complete > 2. poll is not called by irq, maybe xsk wake up. So irq is not disabled. > > > Thanks. I thought more about it and - so what? It's a rare race that might result in more interrupts. Why is that an issue? This would be a problem: callbacks disabled no NAPI and I do not see how this gets there. so maybe virtqueue_disable_cb(vq); napi_schedule(napi); is exactly the right thing? it's certainly simple. > > > > > > > > > > > >> > > > >> > > > >> >> } > > >> >> } > > >> >> > > >> >> -- > > >> >> 2.25.1 > > >> >> > > >> > > ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-08-10 9:21 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-15 9:45 [PATCH] virtio_net: disable cb when napi_schedule_prep fails during busy-poll Longjun Tang 2026-06-15 10:01 ` Xuan Zhuo 2026-06-16 3:00 ` Lange Tang 2026-06-16 3:27 ` Xuan Zhuo 2026-06-16 6:07 ` Lange Tang 2026-06-16 6:49 ` Xuan Zhuo 2026-06-17 2:08 ` Lange Tang 2026-08-10 7:13 ` Michael S. Tsirkin 2026-08-10 9:20 ` Lange Tang 2026-08-10 7:51 ` Michael S. Tsirkin
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.