@@ -26,6 +26,7 @@ sources = files(
'nfpcore/nfp_nsp_eth.c',
'nfpcore/nfp_resource.c',
'nfpcore/nfp_rtsym.c',
+ 'nfpcore/nfp_sync.c',
'nfpcore/nfp_target.c',
'nfpcore/nfp6000_pcie.c',
'nfp_cpp_bridge.c',
@@ -19,6 +19,7 @@
#include "nfpcore/nfp_nsp.h"
#include "nfpcore/nfp6000_pcie.h"
#include "nfpcore/nfp_resource.h"
+#include "nfpcore/nfp_sync.h"
#include "nfp_cpp_bridge.h"
#include "nfp_ipsec.h"
@@ -551,6 +552,7 @@ nfp_pf_uninit(struct nfp_pf_dev *pf_dev)
free(pf_dev->nfp_eth_table);
free(pf_dev->hwinfo);
nfp_cpp_free(pf_dev->cpp);
+ nfp_sync_free(pf_dev->sync);
rte_free(pf_dev);
}
@@ -559,6 +561,7 @@ nfp_pf_secondary_uninit(struct nfp_pf_dev *pf_dev)
{
free(pf_dev->sym_tbl);
nfp_cpp_free(pf_dev->cpp);
+ nfp_sync_free(pf_dev->sync);
rte_free(pf_dev);
return 0;
@@ -1612,6 +1615,7 @@ nfp_net_speed_capa_get(struct nfp_pf_dev *pf_dev,
static int
nfp_pf_init(struct rte_pci_device *pci_dev)
{
+ void *sync;
uint32_t i;
uint32_t id;
int ret = 0;
@@ -1652,6 +1656,13 @@ nfp_pf_init(struct rte_pci_device *pci_dev)
return -ENOMEM;
}
+ sync = nfp_sync_alloc();
+ if (sync == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to alloc sync zone.");
+ ret = -ENOMEM;
+ goto pf_cleanup;
+ }
+
/*
* When device bound to UIO, the device could be used, by mistake,
* by two DPDK apps, and the UIO driver does not avoid it. This
@@ -1667,7 +1678,7 @@ nfp_pf_init(struct rte_pci_device *pci_dev)
if (cpp == NULL) {
PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
ret = -EIO;
- goto pf_cleanup;
+ goto sync_free;
}
hwinfo = nfp_hwinfo_read(cpp);
@@ -1734,6 +1745,7 @@ nfp_pf_init(struct rte_pci_device *pci_dev)
pf_dev->sym_tbl = sym_tbl;
pf_dev->pci_dev = pci_dev;
pf_dev->nfp_eth_table = nfp_eth_table;
+ pf_dev->sync = sync;
/* Get the speed capability */
for (i = 0; i < nfp_eth_table->count; i++) {
@@ -1815,6 +1827,8 @@ nfp_pf_init(struct rte_pci_device *pci_dev)
free(hwinfo);
cpp_cleanup:
nfp_cpp_free(cpp);
+sync_free:
+ nfp_sync_free(sync);
pf_cleanup:
rte_free(pf_dev);
@@ -1878,6 +1892,7 @@ nfp_secondary_init_app_fw_nic(struct nfp_pf_dev *pf_dev)
static int
nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
{
+ void *sync;
int ret = 0;
struct nfp_cpp *cpp;
uint8_t function_id;
@@ -1910,6 +1925,13 @@ nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
return -ENOMEM;
}
+ sync = nfp_sync_alloc();
+ if (sync == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to alloc sync zone.");
+ ret = -ENOMEM;
+ goto pf_cleanup;
+ }
+
/*
* When device bound to UIO, the device could be used, by mistake,
* by two DPDK apps, and the UIO driver does not avoid it. This
@@ -1925,7 +1947,7 @@ nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
if (cpp == NULL) {
PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
ret = -EIO;
- goto pf_cleanup;
+ goto sync_free;
}
/*
@@ -1936,7 +1958,7 @@ nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
if (sym_tbl == NULL) {
PMD_INIT_LOG(ERR, "Something is wrong with the firmware symbol table");
ret = -EIO;
- goto pf_cleanup;
+ goto sync_free;
}
/* Read the app ID of the firmware loaded */
@@ -1954,6 +1976,7 @@ nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
pf_dev->cpp = cpp;
pf_dev->sym_tbl = sym_tbl;
pf_dev->pci_dev = pci_dev;
+ pf_dev->sync = sync;
/* Call app specific init code now */
switch (app_fw_id) {
@@ -1983,6 +2006,8 @@ nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
sym_tbl_cleanup:
free(sym_tbl);
+sync_free:
+ nfp_sync_free(sync);
pf_cleanup:
rte_free(pf_dev);
@@ -12,6 +12,7 @@
#include <nfp_dev.h>
#include <rte_spinlock.h>
+#include "nfpcore/nfp_sync.h"
#include "nfp_net_ctrl.h"
/* Interrupt definitions */
@@ -109,6 +110,9 @@ struct nfp_pf_dev {
/** Supported speeds bitmap */
uint32_t speed_capa;
+
+ /** Synchronized info */
+ struct nfp_sync *sync;
};
#define NFP_NET_FLOW_LIMIT 1024
new file mode 100644
@@ -0,0 +1,382 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_sync.h"
+
+#include <rte_dev.h>
+#include <rte_malloc.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#include "nfp_logs.h"
+
+#define NFP_SYNC_ELEMENT_MAX 8
+#define NFP_SYNC_PCI_MAX 32
+
+struct nfp_sync_element {
+ uint16_t count;
+ /** Element ID, use ASCII - SYN<> */
+ uint32_t magic;
+ void *handle;
+};
+
+struct nfp_sync_common {
+ char pci_name[PCI_PRI_STR_SIZE + 1];
+ uint16_t avail;
+ struct nfp_sync_element element[NFP_SYNC_ELEMENT_MAX];
+};
+
+struct nfp_sync {
+ rte_spinlock_t spinlock;
+
+ uint16_t alloc_count;
+
+ struct nfp_sync_common process;
+
+ struct nfp_sync_common pci[NFP_SYNC_PCI_MAX];
+
+ const struct rte_memzone *mz;
+};
+
+struct nfp_sync *
+nfp_sync_alloc(void)
+{
+ uint16_t i;
+ struct nfp_sync *sync;
+ const struct rte_memzone *mz;
+
+ mz = rte_memzone_lookup("nfp_sync");
+ if (mz != NULL) {
+ sync = mz->addr;
+ sync->alloc_count++;
+
+ return sync;
+ }
+
+ mz = rte_memzone_reserve("nfp_sync", sizeof(*sync), SOCKET_ID_ANY,
+ RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL)
+ return NULL;
+
+ sync = mz->addr;
+
+ memset(sync, 0, sizeof(*sync));
+
+ rte_spinlock_init(&sync->spinlock);
+ sync->alloc_count = 1;
+ sync->mz = mz;
+
+ for (i = 0; i < NFP_SYNC_PCI_MAX; i++)
+ sync->pci[i].avail = NFP_SYNC_ELEMENT_MAX;
+
+ sync->process.avail = NFP_SYNC_ELEMENT_MAX;
+
+ return sync;
+}
+
+void
+nfp_sync_free(struct nfp_sync *sync)
+{
+ uint16_t i;
+
+ rte_spinlock_lock(&sync->spinlock);
+
+ sync->alloc_count--;
+ if (sync->alloc_count != 0) {
+ rte_spinlock_unlock(&sync->spinlock);
+ return;
+ }
+
+ if (sync->process.avail != NFP_SYNC_ELEMENT_MAX)
+ PMD_DRV_LOG(ERR, "Sync process handle residue");
+
+ for (i = 0; i < NFP_SYNC_PCI_MAX; i++) {
+ if (sync->pci[i].avail != NFP_SYNC_ELEMENT_MAX)
+ PMD_DRV_LOG(ERR, "Sync %s pci handle residue",
+ sync->pci[i].pci_name);
+ }
+
+ rte_spinlock_unlock(&sync->spinlock);
+
+ rte_memzone_free(sync->mz);
+}
+
+static void *
+nfp_sync_element_alloc(struct nfp_sync_element *element,
+ uint32_t magic,
+ uint32_t size)
+{
+ void *handle;
+
+ handle = rte_zmalloc(NULL, size, 0);
+ if (handle == NULL)
+ return NULL;
+
+ element->handle = handle;
+ element->count = 1;
+ element->magic = magic;
+
+ return handle;
+}
+
+static void
+nfp_sync_element_free(struct nfp_sync_element *element,
+ void *handle)
+{
+ element->count--;
+ if (element->count != 0)
+ return;
+
+ rte_free(handle);
+ element->handle = NULL;
+ element->magic = 0;
+}
+
+static void *
+nfp_sync_common_handle_alloc(struct nfp_sync_common *common,
+ uint32_t magic,
+ uint32_t size)
+{
+ uint16_t i;
+ void *handle = NULL;
+ uint16_t avail_slot = NFP_SYNC_ELEMENT_MAX;
+
+ for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) {
+ if (common->element[i].magic != magic)
+ continue;
+
+ common->element[i].count++;
+
+ return common->element[i].handle;
+ }
+
+ if (common->avail == 0)
+ return NULL;
+
+ for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) {
+ if (common->element[i].magic == 0) {
+ avail_slot = i;
+ break;
+ }
+ }
+
+ handle = nfp_sync_element_alloc(&common->element[avail_slot], magic, size);
+ if (handle == NULL)
+ return NULL;
+
+ common->avail--;
+
+ return handle;
+}
+
+static void
+nfp_sync_common_handle_free(struct nfp_sync_common *common,
+ void *handle)
+{
+ uint16_t i;
+
+ if (common->avail == NFP_SYNC_ELEMENT_MAX)
+ return;
+
+ for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) {
+ if (common->element[i].handle == handle)
+ break;
+ }
+
+ if (i == NFP_SYNC_ELEMENT_MAX)
+ return;
+
+ nfp_sync_element_free(&common->element[i], handle);
+
+ if (common->element[i].count == 0)
+ common->avail++;
+}
+
+static void *
+nfp_sync_process_inner_handle_alloc(struct nfp_sync *sync,
+ uint32_t magic,
+ uint32_t size)
+{
+ void *handle = NULL;
+
+ rte_spinlock_lock(&sync->spinlock);
+
+ handle = nfp_sync_common_handle_alloc(&sync->process, magic, size);
+ if (handle == NULL)
+ PMD_DRV_LOG(ERR, "Process handle alloc failed");
+
+ rte_spinlock_unlock(&sync->spinlock);
+
+ return handle;
+}
+
+static void
+nfp_sync_process_inner_handle_free(struct nfp_sync *sync,
+ void *handle)
+{
+ rte_spinlock_lock(&sync->spinlock);
+
+ nfp_sync_common_handle_free(&sync->process, handle);
+
+ rte_spinlock_unlock(&sync->spinlock);
+}
+
+static uint16_t
+nfp_sync_process_handle_count_get(struct nfp_sync *sync,
+ void *handle)
+{
+ uint16_t i;
+ uint16_t count = 0;
+
+ rte_spinlock_lock(&sync->spinlock);
+
+ for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) {
+ if (sync->process.element[i].handle == handle) {
+ count = sync->process.element[i].count;
+ break;
+ }
+ }
+
+ rte_spinlock_unlock(&sync->spinlock);
+
+ return count;
+}
+
+static void *
+nfp_sync_pci_inner_handle_alloc(struct nfp_sync *sync,
+ const char *pci_name,
+ uint32_t magic,
+ uint32_t size)
+{
+ uint16_t i;
+ void *handle = NULL;
+ uint16_t pci_avail_id = NFP_SYNC_PCI_MAX;
+
+ rte_spinlock_lock(&sync->spinlock);
+
+ for (i = 0; i < NFP_SYNC_PCI_MAX; i++) {
+ if (strcmp(pci_name, sync->pci[i].pci_name) == 0) {
+ pci_avail_id = i;
+ goto common_alloc;
+ }
+ }
+
+ for (i = 0; i < NFP_SYNC_PCI_MAX; i++) {
+ if (strlen(sync->pci[i].pci_name) == 0) {
+ pci_avail_id = i;
+ strcpy(sync->pci[pci_avail_id].pci_name, pci_name);
+ goto common_alloc;
+ }
+ }
+
+ rte_spinlock_unlock(&sync->spinlock);
+
+ return NULL;
+
+common_alloc:
+ handle = nfp_sync_common_handle_alloc(&sync->pci[pci_avail_id],
+ magic, size);
+ if (handle == NULL)
+ PMD_DRV_LOG(ERR, "PCI handle alloc failed");
+
+ rte_spinlock_unlock(&sync->spinlock);
+
+ return handle;
+}
+
+static void
+nfp_sync_pci_inner_handle_free(struct nfp_sync *sync,
+ const char *pci_name,
+ void *handle)
+{
+ uint16_t i;
+ char *name_tmp;
+
+ rte_spinlock_lock(&sync->spinlock);
+
+ for (i = 0; i < NFP_SYNC_PCI_MAX; i++) {
+ name_tmp = sync->pci[i].pci_name;
+ if (strlen(name_tmp) != 0 && strcmp(pci_name, name_tmp) == 0) {
+ nfp_sync_common_handle_free(&sync->pci[i], handle);
+ if (sync->pci[i].avail == NFP_SYNC_ELEMENT_MAX)
+ name_tmp[0] = 0;
+ break;
+ }
+ }
+
+ rte_spinlock_unlock(&sync->spinlock);
+}
+
+static uint16_t
+nfp_sync_pci_handle_count_get(struct nfp_sync *sync,
+ const char *pci_name,
+ void *handle)
+{
+ uint16_t i;
+ uint16_t count = 0;
+ struct nfp_sync_common *pci_common;
+
+ rte_spinlock_lock(&sync->spinlock);
+
+ for (i = 0; i < NFP_SYNC_PCI_MAX; i++) {
+ if (strcmp(sync->pci[i].pci_name, pci_name) == 0)
+ break;
+ }
+
+ if (i == NFP_SYNC_PCI_MAX) {
+ rte_spinlock_unlock(&sync->spinlock);
+ return 0;
+ }
+
+ pci_common = &sync->pci[i];
+
+ for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) {
+ if (pci_common->element[i].handle == handle) {
+ count = pci_common->element[i].count;
+ break;
+ }
+ }
+
+ rte_spinlock_unlock(&sync->spinlock);
+
+ return count;
+}
+
+void *
+nfp_sync_handle_alloc(struct nfp_sync *sync,
+ struct rte_pci_device *pci_dev,
+ uint32_t magic,
+ uint32_t size)
+{
+ if (pci_dev == NULL)
+ return nfp_sync_process_inner_handle_alloc(sync, magic, size);
+
+ return nfp_sync_pci_inner_handle_alloc(sync, pci_dev->device.name,
+ magic, size);
+}
+
+void
+nfp_sync_handle_free(struct nfp_sync *sync,
+ struct rte_pci_device *pci_dev,
+ void *handle)
+{
+ if (pci_dev == NULL) {
+ nfp_sync_process_inner_handle_free(sync, handle);
+ return;
+ }
+
+ nfp_sync_pci_inner_handle_free(sync, pci_dev->device.name, handle);
+}
+
+uint16_t
+nfp_sync_handle_count_get(struct nfp_sync *sync,
+ struct rte_pci_device *pci_dev,
+ void *handle)
+{
+ if (pci_dev == NULL)
+ return nfp_sync_process_handle_count_get(sync, handle);
+
+ return nfp_sync_pci_handle_count_get(sync, pci_dev->device.name, handle);
+}
new file mode 100644
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#ifndef __NFP_SYNC_H__
+#define __NFP_SYNC_H__
+
+#include <stdint.h>
+
+#include <bus_pci_driver.h>
+
+struct nfp_sync;
+
+struct nfp_sync *nfp_sync_alloc(void);
+void nfp_sync_free(struct nfp_sync *sync);
+
+void *nfp_sync_handle_alloc(struct nfp_sync *sync,
+ struct rte_pci_device *pci_dev,
+ uint32_t magic,
+ uint32_t size);
+void nfp_sync_handle_free(struct nfp_sync *sync,
+ struct rte_pci_device *pci_dev,
+ void *handle);
+uint16_t nfp_sync_handle_count_get(struct nfp_sync *sync,
+ struct rte_pci_device *pci_dev,
+ void *handle);
+
+#endif /* __NFP_SYNC_H__ */