diff options
author | Mohsin Kazmi <sykazmi@cisco.com> | 2020-09-29 10:01:25 +0000 |
---|---|---|
committer | Andrew Yourtchenko <ayourtch@gmail.com> | 2020-09-30 11:31:26 +0000 |
commit | 8eb1e6d1f092609d30496fae28c0e0d3f73bacbc (patch) | |
tree | 82901f2c6656f0a29eca7217457242124c1f4b79 | |
parent | 47e0bd7303b1bcc81c3458ca9e26b43a39fcfe17 (diff) |
virtio: fix modern device queue notify
QUEUE_SELECT and QUEUE_NOTIFY_OFF registers are shared between all
workers operating on the same device and operations are not atomic
Type: fix
Change-Id: Ie017b1bfc7e3b6b4e59029f45db78eeffd9f3aeb
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
(cherry picked from commit 162a296756f3dbead55079e4670973d859df1ef9)
-rw-r--r-- | src/vnet/devices/virtio/pci.c | 26 | ||||
-rw-r--r-- | src/vnet/devices/virtio/pci.h | 5 | ||||
-rw-r--r-- | src/vnet/devices/virtio/virtio.h | 23 | ||||
-rw-r--r-- | src/vnet/devices/virtio/virtio_pci_legacy.c | 10 | ||||
-rw-r--r-- | src/vnet/devices/virtio/virtio_pci_modern.c | 11 |
5 files changed, 53 insertions, 22 deletions
diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c index df8e2bdaf68..7b7a1202833 100644 --- a/src/vnet/devices/virtio/pci.c +++ b/src/vnet/devices/virtio/pci.c @@ -486,7 +486,11 @@ virtio_pci_control_vring_init (vlib_main_t * vm, virtio_if_t * vif, virtio_log_debug (vif, "control-queue: number %u, size %u", queue_num, queue_size); vif->virtio_pci_func->setup_queue (vm, vif, queue_num, ptr); - vring->kick_fd = -1; + vring->queue_notify_offset = + vif->notify_off_multiplier * + vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num); + virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u", + queue_num, vring->queue_notify_offset); return error; } @@ -562,7 +566,11 @@ virtio_pci_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 queue_num) if (vif->virtio_pci_func->setup_queue (vm, vif, queue_num, ptr)) return clib_error_return (0, "error in queue address setup"); - vring->kick_fd = -1; + vring->queue_notify_offset = + vif->notify_off_multiplier * + vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num); + virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u", + queue_num, vring->queue_notify_offset); return error; } @@ -775,6 +783,7 @@ virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif, void **bar) if (common_cfg == 0 || notify == 0 || dev_cfg == 0 || isr == 0) { vif->virtio_pci_func = &virtio_pci_legacy_func; + vif->notify_off_multiplier = 0; virtio_log_debug (vif, "legacy virtio pci device found"); return error; } @@ -783,9 +792,14 @@ virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif, void **bar) vif->virtio_pci_func = &virtio_pci_modern_func; if (!pci_cfg) - virtio_log_debug (vif, "modern virtio pci device found"); + { + virtio_log_debug (vif, "modern virtio pci device found"); + } + else + { + virtio_log_debug (vif, "transitional virtio pci device found"); + } - virtio_log_debug (vif, "transitional virtio pci device found"); return error; } @@ -1231,8 +1245,6 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) vec_foreach_index (i, vif->rxq_vrings) { virtio_vring_t *vring = vec_elt_at_index (vif->rxq_vrings, i); - if (vring->kick_fd != -1) - close (vring->kick_fd); if (vring->used) { virtio_free_rx_buffers (vm, vring); @@ -1244,8 +1256,6 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) vec_foreach_index (i, vif->txq_vrings) { virtio_vring_t *vring = vec_elt_at_index (vif->txq_vrings, i); - if (vring->kick_fd != -1) - close (vring->kick_fd); if (vring->used) { virtio_free_used_desc (vm, vring); diff --git a/src/vnet/devices/virtio/pci.h b/src/vnet/devices/virtio/pci.h index ab5c6f15ec2..eeb0f9454bb 100644 --- a/src/vnet/devices/virtio/pci.h +++ b/src/vnet/devices/virtio/pci.h @@ -195,7 +195,10 @@ typedef struct _virtio_pci_func u8 (*setup_queue) (vlib_main_t * vm, virtio_if_t * vif, u16 queue_id, void *p); void (*del_queue) (vlib_main_t * vm, virtio_if_t * vif, u16 queue_id); - void (*notify_queue) (vlib_main_t * vm, virtio_if_t * vif, u16 queue_id); + u16 (*get_queue_notify_off) (vlib_main_t * vm, virtio_if_t * vif, + u16 queue_id); + void (*notify_queue) (vlib_main_t * vm, virtio_if_t * vif, u16 queue_id, + u16 queue_notify_offset); u16 (*set_config_irq) (vlib_main_t * vm, virtio_if_t * vif, u16 vec); u16 (*set_queue_irq) (vlib_main_t * vm, virtio_if_t * vif, u16 vec, diff --git a/src/vnet/devices/virtio/virtio.h b/src/vnet/devices/virtio/virtio.h index b00e1eceb85..309a2c37664 100644 --- a/src/vnet/devices/virtio/virtio.h +++ b/src/vnet/devices/virtio/virtio.h @@ -65,8 +65,15 @@ typedef struct vring_avail_t *avail; u16 desc_in_use; u16 desc_next; - int kick_fd; - int call_fd; + union + { + struct + { + int kick_fd; + int call_fd; + }; + u16 queue_notify_offset; + }; u8 buffer_pool_index; u16 size; u16 queue_id; @@ -204,9 +211,11 @@ extern void virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr, u32 type); extern void virtio_set_packet_coalesce (virtio_if_t * vif); extern void virtio_pci_legacy_notify_queue (vlib_main_t * vm, - virtio_if_t * vif, u16 queue_id); + virtio_if_t * vif, u16 queue_id, + u16 queue_notify_offset); extern void virtio_pci_modern_notify_queue (vlib_main_t * vm, - virtio_if_t * vif, u16 queue_id); + virtio_if_t * vif, u16 queue_id, + u16 queue_notify_offset); format_function_t format_virtio_device_name; format_function_t format_virtio_log_name; @@ -216,9 +225,11 @@ virtio_kick (vlib_main_t * vm, virtio_vring_t * vring, virtio_if_t * vif) if (vif->type == VIRTIO_IF_TYPE_PCI) { if (vif->is_modern) - virtio_pci_modern_notify_queue (vm, vif, vring->queue_id); + virtio_pci_modern_notify_queue (vm, vif, vring->queue_id, + vring->queue_notify_offset); else - virtio_pci_legacy_notify_queue (vm, vif, vring->queue_id); + virtio_pci_legacy_notify_queue (vm, vif, vring->queue_id, + vring->queue_notify_offset); } else { diff --git a/src/vnet/devices/virtio/virtio_pci_legacy.c b/src/vnet/devices/virtio/virtio_pci_legacy.c index cf1d84135aa..1426a7035a2 100644 --- a/src/vnet/devices/virtio/virtio_pci_legacy.c +++ b/src/vnet/devices/virtio/virtio_pci_legacy.c @@ -203,9 +203,16 @@ virtio_pci_legacy_del_queue (vlib_main_t * vm, virtio_if_t * vif, vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &src); } +static u16 +virtio_pci_legacy_get_queue_notify_off (vlib_main_t * vm, virtio_if_t * vif, + u16 queue_id) +{ + return 0; +} + inline void virtio_pci_legacy_notify_queue (vlib_main_t * vm, virtio_if_t * vif, - u16 queue_id) + u16 queue_id, u16 queue_notify_off) { vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY, &queue_id); @@ -364,6 +371,7 @@ const virtio_pci_func_t virtio_pci_legacy_func = { .set_queue_size = virtio_pci_legacy_set_queue_num, .setup_queue = virtio_pci_legacy_setup_queue, .del_queue = virtio_pci_legacy_del_queue, + .get_queue_notify_off = virtio_pci_legacy_get_queue_notify_off, .notify_queue = virtio_pci_legacy_notify_queue, .set_config_irq = virtio_pci_legacy_set_config_irq, .set_queue_irq = virtio_pci_legacy_set_queue_irq, diff --git a/src/vnet/devices/virtio/virtio_pci_modern.c b/src/vnet/devices/virtio/virtio_pci_modern.c index 4eb0ff102ae..1934f98003d 100644 --- a/src/vnet/devices/virtio/virtio_pci_modern.c +++ b/src/vnet/devices/virtio/virtio_pci_modern.c @@ -208,7 +208,8 @@ virtio_pci_modern_set_queue_enable (virtio_if_t * vif, u16 queue_id, } static u16 -virtio_pci_modern_get_queue_notify_off (virtio_if_t * vif, u16 queue_id) +virtio_pci_modern_get_queue_notify_off (vlib_main_t * vm, virtio_if_t * vif, + u16 queue_id) { u16 queue_notify_off = 0; virtio_pci_modern_set_queue_select (vif, queue_id); @@ -387,14 +388,11 @@ virtio_pci_modern_get_isr (vlib_main_t * vm, virtio_if_t * vif) inline void virtio_pci_modern_notify_queue (vlib_main_t * vm, virtio_if_t * vif, - u16 queue_id) + u16 queue_id, u16 queue_notify_off) { - u16 queue_notify_off = - virtio_pci_modern_get_queue_notify_off (vif, queue_id); virtio_pci_reg_write_u16 (vif, VIRTIO_NOTIFICATION_OFFSET (vif) + - vif->notify_off_multiplier * queue_notify_off, - queue_id); + queue_notify_off, queue_id); } static void @@ -418,6 +416,7 @@ const virtio_pci_func_t virtio_pci_modern_func = { .set_queue_size = virtio_pci_modern_set_queue_size, .setup_queue = virtio_pci_modern_setup_queue, .del_queue = virtio_pci_modern_del_queue, + .get_queue_notify_off = virtio_pci_modern_get_queue_notify_off, .notify_queue = virtio_pci_modern_notify_queue, .set_config_irq = virtio_pci_modern_set_msix_config, .set_queue_irq = virtio_pci_modern_set_queue_msix_vector, |