diff mbox series

[v2,1/2] virtio_net: virtio_net_tx_complete() stop flush new packets for purge operation

Message ID 20230206032105.35831-2-xuanzhuo@linux.alibaba.com (mailing list archive)
State New, archived
Headers show
Series virtio: fix for assertion failure: virtio_net_get_subqueue(nc)->async_tx.elem failed | expand

Commit Message

Xuan Zhuo Feb. 6, 2023, 3:21 a.m. UTC
For async tx, virtio_net_tx_complete() is called when purge or flush
operation is done. But for purge operation, we should not try to flush
new packet from tx queue. The purge operation means we will stop the
queue soon.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 hw/net/virtio-net.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 3ae909041a..6daa1e5ac1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2601,21 +2601,25 @@  static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
     q->async_tx.elem = NULL;
 
     virtio_queue_set_notification(q->tx_vq, 1);
-    ret = virtio_net_flush_tx(q);
-    if (ret >= n->tx_burst) {
-        /*
-         * the flush has been stopped by tx_burst
-         * we will not receive notification for the
-         * remainining part, so re-schedule
-         */
-        virtio_queue_set_notification(q->tx_vq, 0);
-        if (q->tx_bh) {
-            qemu_bh_schedule(q->tx_bh);
-        } else {
-            timer_mod(q->tx_timer,
-                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
+
+    /* len == 0 means purge, we should not flush new tx packets. */
+    if (len) {
+        ret = virtio_net_flush_tx(q);
+        if (ret >= n->tx_burst) {
+            /*
+             * the flush has been stopped by tx_burst
+             * we will not receive notification for the
+             * remainining part, so re-schedule
+             */
+            virtio_queue_set_notification(q->tx_vq, 0);
+            if (q->tx_bh) {
+                qemu_bh_schedule(q->tx_bh);
+            } else {
+                timer_mod(q->tx_timer,
+                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
+            }
+            q->tx_waiting = 1;
         }
-        q->tx_waiting = 1;
     }
 }