virtio: fix modern device queue notify 41/28841/4
authorMohsin Kazmi <sykazmi@cisco.com>
Tue, 29 Sep 2020 10:01:25 +0000 (10:01 +0000)
committerBeno�t Ganne <bganne@cisco.com>
Tue, 29 Sep 2020 13:34:13 +0000 (13:34 +0000)
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>
src/vnet/devices/virtio/pci.c
src/vnet/devices/virtio/pci.h
src/vnet/devices/virtio/virtio.h
src/vnet/devices/virtio/virtio_pci_legacy.c
src/vnet/devices/virtio/virtio_pci_modern.c

index 71d813a..9b68b1c 100644 (file)
@@ -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;
 }
 
@@ -1244,8 +1258,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);
@@ -1257,8 +1269,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);
index 10df49c..70aa983 100644 (file)
@@ -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,
index acefc38..1cca9f3 100644 (file)
@@ -66,8 +66,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;
@@ -208,9 +215,11 @@ extern void virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr,
 extern void virtio_set_packet_coalesce (virtio_if_t * vif);
 clib_error_t *virtio_set_packet_buffering (virtio_if_t * vif, u16 size);
 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;
 
@@ -220,9 +229,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
     {
index cf1d841..1426a70 100644 (file)
@@ -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,
index 4eb0ff1..1934f98 100644 (file)
@@ -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,