octeon: update roc version 34/42934/2
authorMonendra Singh Kushwaha <[email protected]>
Tue, 6 May 2025 11:58:46 +0000 (17:28 +0530)
committerDamjan Marion <[email protected]>
Fri, 9 May 2025 22:03:07 +0000 (22:03 +0000)
This patch updated roc version and enables the interrupt mechanism to
support VFIO MSI-X by fixing the PCI bus master enable in the OCTEON
plugin. Additionally, it introduces an MSI-X message handler to
support all vectors.

Type: feature

Change-Id: Ic3cea28afffab400923fe5afa729be21dd54cca8
Signed-off-by: Satha Rao <[email protected]>
Signed-off-by: Monendra Singh Kushwaha <[email protected]>
build/external/packages/octeon-roc.mk
src/plugins/dev_octeon/init.c
src/plugins/dev_octeon/octeon.h
src/plugins/dev_octeon/port.c
src/plugins/dev_octeon/roc_helper.c

index 0dade11..9236839 100644 (file)
@@ -2,9 +2,9 @@
 # SPDX-License-Identifier: Apache-2.0
 # https://spdx.org/licenses/Apache-2.0.html
 
-octeon-roc_version             := 0.6
+octeon-roc_version             := 25.05
 octeon-roc_tarball             := v$(octeon-roc_version).tar.gz
-octeon-roc_tarball_sha256sum   := 5018e6da80c80898444b648482b4240cbf62591c64eb463b3f681cf68c07239c
+octeon-roc_tarball_sha256sum   := fc7c8583e49f76b70fb1da242482fe324e6456c04f17d1a0e8726c28266220c6
 
 octeon-roc_tarball_strip_dirs  := 1
 octeon-roc_url                 := https://github.com/MarvellEmbeddedProcessors/marvell-octeon-roc/archive/refs/tags/$(octeon-roc_tarball)
index 69fb097..e1a6f90 100644 (file)
@@ -373,6 +373,7 @@ oct_init (vlib_main_t *vm, vnet_dev_t *dev)
     .id.class_id = pci_hdr.class << 16 | pci_hdr.subclass,
     .pci_handle = vnet_dev_get_pci_handle (dev),
   };
+  cd->msix_handler = NULL;
 
   foreach_int (i, 2, 4)
     {
@@ -383,9 +384,20 @@ oct_init (vlib_main_t *vm, vnet_dev_t *dev)
     }
 
   STATIC_ASSERT (sizeof (cd->plt_pci_dev.name) == sizeof (dev->device_id), "");
+
+  if ((rv = vnet_dev_pci_bus_master_enable (vm, dev)))
+    return rv;
+
   strncpy ((char *) cd->plt_pci_dev.name, dev->device_id,
           sizeof (dev->device_id));
 
+  cd->plt_pci_dev.intr_handle = malloc (sizeof (struct oct_pci_intr_handle));
+  if (!cd->plt_pci_dev.intr_handle)
+    return VNET_DEV_ERR_DMA_MEM_ALLOC_FAIL;
+  memset (cd->plt_pci_dev.intr_handle, 0x0,
+         sizeof (struct oct_pci_intr_handle));
+  cd->plt_pci_dev.intr_handle->pci_handle = cd->plt_pci_dev.pci_handle;
+
   switch (cd->type)
     {
     case OCT_DEVICE_TYPE_RVU_PF:
index 67fe7e6..24d51f9 100644 (file)
@@ -49,6 +49,7 @@ typedef struct
   u32 speed;
   struct plt_pci_device plt_pci_dev;
   struct roc_nix *nix;
+  oct_msix_handler_info_t *msix_handler;
 } oct_device_t;
 
 typedef struct
@@ -66,6 +67,7 @@ typedef struct
   u8 lf_allocated : 1;
   u8 tm_initialized : 1;
   u8 npc_initialized : 1;
+  u8 q_intr_enabled : 1;
   struct roc_npc npc;
   oct_flow_entry_t *flow_entries;
 } oct_port_t;
index 96fc088..0fc3fcb 100644 (file)
@@ -227,6 +227,15 @@ oct_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
       return rv;
     }
 
+  if (roc_nix_register_queue_irqs (nix))
+    {
+      rv = oct_roc_err (dev, rrv, "roc_nix_register_queue_irqs() failed");
+      oct_port_deinit (vm, port);
+      return rv;
+    }
+  cp->q_intr_enabled = 1;
+  oct_port_add_counters (vm, port);
+
   return VNET_DEV_OK;
 }
 
@@ -257,6 +266,13 @@ oct_port_deinit (vlib_main_t *vm, vnet_dev_port_t *port)
       cp->tm_initialized = 0;
     }
 
+  /* Unregister queue irqs */
+  if (cp->q_intr_enabled)
+    {
+      roc_nix_unregister_queue_irqs (nix);
+      cp->q_intr_enabled = 0;
+    }
+
   if (cp->lf_allocated)
     {
       if ((rrv = roc_nix_lf_free (nix)))
index c1166b6..0f87204 100644 (file)
@@ -9,6 +9,7 @@
 #include <vlib/linux/vfio.h>
 #include <base/roc_api.h>
 #include <common.h>
+#include "octeon.h"
 
 static oct_plt_memzone_list_t memzone_list;
 
@@ -76,7 +77,7 @@ oct_drv_physmem_alloc (vlib_main_t *vm, u32 size, u32 align)
   if (align)
     {
       /* Force ROC align alloc in case alignment is less than ROC align */
-      align = align < ROC_ALIGN ? ROC_ALIGN : align;
+      align = ((align + ROC_ALIGN - 1) & ~(ROC_ALIGN - 1));
       mem = vlib_physmem_alloc_aligned_on_numa (vm, size, align, 0);
     }
   else
@@ -114,38 +115,39 @@ oct_plt_zmalloc (u32 size, u32 align)
   return oct_drv_physmem_alloc (vm, size, align);
 }
 
-static oct_plt_memzone_t *
-memzone_get (u32 index)
+static void *
+oct_plt_realloc (void *addr, u32 size, u32 align)
 {
-  if (index == ((u32) ~0))
-    return 0;
+  align = CLIB_CACHE_LINE_ROUND (align);
+  size = CLIB_CACHE_LINE_ROUND (size);
 
-  return pool_elt_at_index (memzone_list.mem_pool, index);
+  if (align)
+    return clib_mem_realloc_aligned (addr, size, align);
+  else
+    return clib_mem_realloc (addr, size);
 }
 
-static int
-oct_plt_memzone_free (const oct_plt_memzone_t *name)
+static oct_plt_memzone_t *
+oct_plt_memzone_lookup (const char *name)
 {
-  uword *p;
-  p = hash_get_mem (memzone_list.memzone_by_name, name);
-
-  if (p[0] == ((u32) ~0))
-    return -EINVAL;
-
-  hash_unset_mem (memzone_list.memzone_by_name, name);
+  oct_plt_memzone_t *mem_pool;
 
-  pool_put_index (memzone_list.mem_pool, p[0]);
+  pool_foreach (mem_pool, memzone_list.mem_pool)
+    {
+      if (!clib_strcmp (mem_pool->name, name))
+       return mem_pool;
+    }
 
   return 0;
 }
 
-static oct_plt_memzone_t *
-oct_plt_memzone_lookup (const char *name)
+static int
+oct_plt_memzone_free (const oct_plt_memzone_t *mz)
 {
-  uword *p;
-  p = hash_get_mem (memzone_list.memzone_by_name, name);
-  if (p)
-    return memzone_get (p[0]);
+  if (!mz || !oct_plt_memzone_lookup (mz->name))
+    return -EINVAL;
+
+  pool_put (memzone_list.mem_pool, mz);
 
   return 0;
 }
@@ -165,16 +167,258 @@ oct_plt_memzone_reserve_aligned (const char *name, u64 len, u8 socket,
 
   mem_pool->addr = p;
   mem_pool->index = mem_pool - memzone_list.mem_pool;
-  hash_set_mem (memzone_list.memzone_by_name, name, mem_pool->index);
+  strcpy (mem_pool->name, name);
 
   return mem_pool;
 }
 
+static void
+plt_msix_handler (vlib_main_t *vm, vlib_pci_dev_handle_t handle, uint16_t line)
+{
+  vnet_dev_t *dev = (vnet_dev_t *) vlib_pci_get_private_data (vm, handle);
+  oct_device_t *cd = vnet_dev_get_data (dev);
+
+  if (cd->msix_handler && cd->msix_handler[line].fn)
+    cd->msix_handler[line].fn (cd->msix_handler[line].data);
+}
+
+static int
+oct_plt_get_num_vectors (oct_pci_dev_handle_t handle)
+{
+  vlib_main_t *vm = vlib_get_main ();
+
+  return vlib_pci_get_num_msix_interrupts (vm, handle);
+}
+
+static int
+oct_plt_intr_enable (oct_pci_dev_handle_t handle, uint16_t start,
+                    uint16_t count, uint8_t enable,
+                    enum oct_msix_rsrc_op_t op)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vnet_dev_t *dev = (vnet_dev_t *) vlib_pci_get_private_data (vm, handle);
+  oct_device_t *cd = vnet_dev_get_data (dev);
+  clib_error_t *error = NULL;
+
+  if (op == OCT_MSIX_RSRC_ALLOC)
+    {
+      if (cd->msix_handler)
+       {
+         clib_warning ("MSIX handlers already allocated\n");
+         return -EINVAL;
+       }
+      cd->msix_handler = malloc (sizeof (*cd->msix_handler) * (start + count));
+      if (!cd->msix_handler)
+       {
+         clib_warning ("MSIX handlers alilocation failed\n");
+         return -ENOMEM;
+       }
+    }
+  if (enable)
+    error = vlib_pci_enable_msix_irq (vm, handle, start, count);
+  else
+    error = vlib_pci_disable_msix_irq (vm, handle, start, count);
+  if (error)
+    {
+      clib_error_report (error);
+      return -EINVAL;
+    }
+  if (op == OCT_MSIX_RSRC_FREE)
+    {
+      if (cd->msix_handler)
+       free (cd->msix_handler);
+    }
+
+  return 0;
+}
+
+static int
+oct_plt_intr_config (oct_pci_dev_handle_t handle, uint32_t vec,
+                    plt_msix_handler_function_t handler, void *data,
+                    int enable)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vnet_dev_t *dev = (vnet_dev_t *) vlib_pci_get_private_data (vm, handle);
+  oct_device_t *cd = vnet_dev_get_data (dev);
+  clib_error_t *error = NULL;
+
+  /* Skip AF_PF_MBOX interrupt FIXME */
+  if (vec == RVU_PF_INT_VEC_AFPF_MBOX)
+    return 0;
+
+  if (enable)
+    {
+      error =
+       vlib_pci_register_msix_handler (vm, handle, vec, 1, plt_msix_handler);
+      if (error)
+       {
+         clib_error_report (error);
+         return -EINVAL;
+       }
+      if (cd->msix_handler)
+       {
+         cd->msix_handler[vec].fn = handler;
+         cd->msix_handler[vec].vec = vec;
+         cd->msix_handler[vec].data = data;
+       }
+      error = vlib_pci_enable_msix_irq (vm, handle, vec, 1);
+      if (error)
+       {
+         clib_error_report (error);
+         return -EINVAL;
+       }
+    }
+  else
+    {
+      error = vlib_pci_disable_msix_irq (vm, handle, vec, 1);
+      if (error)
+       {
+         clib_error_report (error);
+         return -EINVAL;
+       }
+      error = vlib_pci_unregister_msix_handler (vm, handle, vec, 1);
+      if (error)
+       {
+         clib_error_report (error);
+         return -EINVAL;
+       }
+      if (cd->msix_handler)
+       {
+         cd->msix_handler[vec].fn = NULL;
+         cd->msix_handler[vec].data = NULL;
+       }
+    }
+
+  return 0;
+}
+
+static inline __attribute__ ((__always_inline__)) int
+plt_intr_max_intr_get (const struct plt_intr_handle *intr_handle)
+{
+  if (!intr_handle)
+    return -EINVAL;
+
+  return intr_handle->max_intr;
+}
+
+static inline __attribute__ ((__always_inline__)) int
+plt_intr_max_intr_set (struct plt_intr_handle *intr_handle, int max_intr)
+{
+  if (!intr_handle)
+    return -EINVAL;
+
+  intr_handle->max_intr = max_intr;
+
+  return 0;
+}
+
+static int
+irq_get_info (struct plt_intr_handle *intr_handle)
+{
+  int num_vec;
+
+  num_vec = oct_plt_get_num_vectors (intr_handle->pci_handle);
+  if (num_vec == 0)
+    {
+      plt_err ("HW max=%d > PLT_MAX_RXTX_INTR_VEC_ID: %d", num_vec,
+              PLT_MAX_RXTX_INTR_VEC_ID);
+      plt_intr_max_intr_set (intr_handle, PLT_MAX_RXTX_INTR_VEC_ID);
+    }
+  else
+    {
+      if (plt_intr_max_intr_set (intr_handle, num_vec))
+       return -1;
+    }
+
+  return 0;
+}
+
+static int
+irq_init (struct plt_intr_handle *intr_handle)
+{
+  int rc = oct_plt_intr_enable (intr_handle->pci_handle, 0,
+                               plt_intr_max_intr_get (intr_handle), 0,
+                               OCT_MSIX_RSRC_ALLOC);
+
+  if (rc)
+    plt_err ("Failed to set irqs vector rc=%d", rc);
+
+  return rc;
+}
+
+static int
+oct_plt_irq_register (struct oct_pci_intr_handle *intr_handle,
+                     oct_plt_pci_intr_callback_fn cb, void *data,
+                     unsigned int vec)
+{
+  /* If no max_intr read from VFIO */
+  if (plt_intr_max_intr_get (intr_handle) == 0)
+    {
+      irq_get_info (intr_handle);
+      irq_init (intr_handle);
+    }
+
+  if (vec > (uint32_t) plt_intr_max_intr_get (intr_handle))
+    {
+      plt_err ("Error registering MSI-X interrupts vec:%d > %d", vec,
+              plt_intr_max_intr_get (intr_handle));
+      return -EINVAL;
+    }
+
+  oct_plt_intr_config (intr_handle->pci_handle, vec, cb, data, 1);
+
+  return 0;
+}
+
+static void
+oct_plt_irq_unregister (struct oct_pci_intr_handle *intr_handle,
+                       oct_plt_pci_intr_callback_fn cb, void *data,
+                       unsigned int vec)
+{
+  if (vec > (uint32_t) plt_intr_max_intr_get (intr_handle))
+    {
+      plt_err ("Error unregistering MSI-X interrupts vec:%d > %d", vec,
+              plt_intr_max_intr_get (intr_handle));
+      return;
+    }
+
+  oct_plt_intr_config (intr_handle->pci_handle, vec, cb, data, 0);
+}
+
+static int
+oct_plt_irq_disable (struct oct_pci_intr_handle *intr_handle)
+{
+  int rc = -EINVAL;
+
+  if (!intr_handle)
+    return rc;
+
+  /* Clear max_intr to indicate re-init next time */
+  rc = oct_plt_intr_enable (intr_handle->pci_handle, 0,
+                           plt_intr_max_intr_get (intr_handle), 0,
+                           OCT_MSIX_RSRC_FREE);
+  plt_intr_max_intr_set (intr_handle, 0);
+  return rc;
+}
+
+static int
+oct_plt_irq_reconfigure (struct oct_pci_intr_handle *intr_handle,
+                        uint16_t max_intr)
+{
+  /* Disable interrupts if enabled. */
+  if (plt_intr_max_intr_get (intr_handle))
+    oct_plt_irq_disable (intr_handle);
+
+  plt_intr_max_intr_set (intr_handle, max_intr);
+  return irq_init (intr_handle);
+}
+
 oct_plt_init_param_t oct_plt_init_param = {
   .oct_plt_log_reg_class = vlib_log_register_class,
   .oct_plt_log = oct_plt_log,
   .oct_plt_free = oct_plt_free,
   .oct_plt_zmalloc = oct_plt_zmalloc,
+  .oct_plt_realloc = oct_plt_realloc,
   .oct_plt_memzone_free = oct_plt_memzone_free,
   .oct_plt_memzone_lookup = oct_plt_memzone_lookup,
   .oct_plt_memzone_reserve_aligned = oct_plt_memzone_reserve_aligned,
@@ -184,4 +428,8 @@ oct_plt_init_param_t oct_plt_init_param = {
   .oct_plt_spinlock_trylock = oct_plt_spinlock_trylock,
   .oct_plt_get_thread_index = oct_plt_get_thread_index,
   .oct_plt_get_cache_line_size = oct_plt_get_cache_line_size,
+  .oct_plt_irq_reconfigure = oct_plt_irq_reconfigure,
+  .oct_plt_irq_register = oct_plt_irq_register,
+  .oct_plt_irq_unregister = oct_plt_irq_unregister,
+  .oct_plt_irq_disable = oct_plt_irq_disable
 };