From: Monendra Singh Kushwaha Date: Tue, 6 May 2025 11:58:46 +0000 (+0530) Subject: octeon: update roc version X-Git-Tag: v25.10-rc0~23 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=2eb3240d1a6534be30fa3bfedb45dbb359a9a350;p=vpp.git octeon: update roc version 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 Signed-off-by: Monendra Singh Kushwaha --- diff --git a/build/external/packages/octeon-roc.mk b/build/external/packages/octeon-roc.mk index 0dade11ccc8..92368390ebd 100644 --- a/build/external/packages/octeon-roc.mk +++ b/build/external/packages/octeon-roc.mk @@ -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) diff --git a/src/plugins/dev_octeon/init.c b/src/plugins/dev_octeon/init.c index 69fb097e91f..e1a6f9064ba 100644 --- a/src/plugins/dev_octeon/init.c +++ b/src/plugins/dev_octeon/init.c @@ -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: diff --git a/src/plugins/dev_octeon/octeon.h b/src/plugins/dev_octeon/octeon.h index 67fe7e66896..24d51f9091e 100644 --- a/src/plugins/dev_octeon/octeon.h +++ b/src/plugins/dev_octeon/octeon.h @@ -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; diff --git a/src/plugins/dev_octeon/port.c b/src/plugins/dev_octeon/port.c index 96fc088ae21..0fc3fcb7871 100644 --- a/src/plugins/dev_octeon/port.c +++ b/src/plugins/dev_octeon/port.c @@ -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))) diff --git a/src/plugins/dev_octeon/roc_helper.c b/src/plugins/dev_octeon/roc_helper.c index c1166b654cf..0f872047fb4 100644 --- a/src/plugins/dev_octeon/roc_helper.c +++ b/src/plugins/dev_octeon/roc_helper.c @@ -9,6 +9,7 @@ #include #include #include +#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 };