Previously, the tx=timer selected between two completely separate code paths at queue creation time. This refactoring introduces a runtime dispatch mechanism while maintaining identical behavior.
This is a preparatory patch with no functional changes, making it easier to add dynamic TX notification coalescing in a subsequent patch. Signed-off-by: Koushik Dutta <[email protected]> --- hw/net/virtio-net.c | 44 ++++++++++++++++++++++------------ include/hw/virtio/virtio-net.h | 1 + 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 2a5d642a64..319842cf28 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1002,6 +1002,8 @@ static void virtio_net_set_features(VirtIODevice *vdev, } } +static void virtio_net_tx_timer(void *opaque); + static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, struct iovec *iov, unsigned int iov_cnt) { @@ -2817,7 +2819,6 @@ detach: return -EINVAL; } -static void virtio_net_tx_timer(void *opaque); static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq) { @@ -2973,6 +2974,22 @@ static void virtio_net_tx_bh(void *opaque) } } +static void virtio_net_handle_tx_dispatch(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIONet *n = VIRTIO_NET(vdev); + VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))]; + + if (n->tx_timer_activate) { + if (q->tx_timer == NULL) { + q->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + virtio_net_tx_timer, q); + } + virtio_net_handle_tx_timer(vdev, vq); + } else { + virtio_net_handle_tx_bh(vdev, vq); + } +} + static void virtio_net_add_queue(VirtIONet *n, int index) { VirtIODevice *vdev = VIRTIO_DEVICE(n); @@ -2980,20 +2997,13 @@ static void virtio_net_add_queue(VirtIONet *n, int index) n->vqs[index].rx_vq = virtio_add_queue(vdev, n->net_conf.rx_queue_size, virtio_net_handle_rx); - if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) { - n->vqs[index].tx_vq = - virtio_add_queue(vdev, n->net_conf.tx_queue_size, - virtio_net_handle_tx_timer); - n->vqs[index].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, - virtio_net_tx_timer, - &n->vqs[index]); - } else { - n->vqs[index].tx_vq = - virtio_add_queue(vdev, n->net_conf.tx_queue_size, - virtio_net_handle_tx_bh); - n->vqs[index].tx_bh = qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index], - &DEVICE(vdev)->mem_reentrancy_guard); - } + n->vqs[index].tx_vq = + virtio_add_queue(vdev, n->net_conf.tx_queue_size, + virtio_net_handle_tx_dispatch); + + n->vqs[index].tx_bh = + qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index], + &DEVICE(vdev)->mem_reentrancy_guard); n->vqs[index].tx_waiting = 0; n->vqs[index].n = n; @@ -3970,6 +3980,10 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) error_printf("Defaulting to \"bh\""); } + if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer") == 0) { + n->tx_timer_activate = true; + } + n->net_conf.tx_queue_size = MIN(virtio_net_max_tx_queue_size(n), n->net_conf.tx_queue_size); diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 371e376428..a4eb3f407e 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -230,6 +230,7 @@ struct VirtIONet { struct EBPFRSSContext ebpf_rss; uint32_t nr_ebpf_rss_fds; char **ebpf_rss_fds; + bool tx_timer_activate; }; size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, -- 2.53.0
