The virtio_net.napi_weight module parameter is signed and is copied directly into the RX NAPI weight after netif_napi_add_config().
A value of -1 lets virtnet_poll() run with a negative budget. The RX loop processes no packets, the unsigned received-vs-budget comparison completes NAPI, and the NAPI core reports: NAPI poll function virtnet_poll returned 0, exceeding its budget of -1 The device then repeatedly drops receive progress under stock QEMU virtio-net traffic. Normalize non-positive values to the default NAPI weight before assigning the RX and TX NAPI weights. TX NAPI can still be disabled through the separate napi_tx parameter, which intentionally sets the TX weight to zero. Assisted-by: Codex:gpt-5.5-cyber-preview Signed-off-by: Samuel Moelius <[email protected]> --- drivers/net/virtio_net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f4adcfee7a80..667026607cfa 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -6481,6 +6481,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) static int virtnet_alloc_queues(struct virtnet_info *vi) { int i; + int weight = napi_weight > 0 ? napi_weight : NAPI_POLL_WEIGHT; if (vi->has_cvq) { vi->ctrl = kzalloc_obj(*vi->ctrl); @@ -6500,10 +6501,10 @@ static int virtnet_alloc_queues(struct virtnet_info *vi) vi->rq[i].pages = NULL; netif_napi_add_config(vi->dev, &vi->rq[i].napi, virtnet_poll, i); - vi->rq[i].napi.weight = napi_weight; + vi->rq[i].napi.weight = weight; netif_napi_add_tx_weight(vi->dev, &vi->sq[i].napi, virtnet_poll_tx, - napi_tx ? napi_weight : 0); + napi_tx ? weight : 0); sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg)); ewma_pkt_len_init(&vi->rq[i].mrg_avg_pkt_len); -- 2.43.0

