new file mode 100644
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#include <rte_common.h>
+#include <ethdev_driver.h>
+#include <rte_service_component.h>
+#include <rte_malloc.h>
+#include <ethdev_pci.h>
+#include <ethdev_driver.h>
+
+#include "../nfp_common.h"
+#include "../nfp_logs.h"
+#include "../nfp_ctrl.h"
+#include "../nfp_cpp_bridge.h"
+#include "nfp_flower.h"
+
+static struct rte_service_spec flower_services[NFP_FLOWER_SERVICE_MAX] = {
+};
+
+static int
+nfp_flower_enable_services(struct nfp_app_flower *app_flower)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < NFP_FLOWER_SERVICE_MAX; i++) {
+ /* Pass a pointer to the flower app to the service */
+ flower_services[i].callback_userdata = (void *)app_flower;
+
+ /* Register the flower services */
+ ret = rte_service_component_register(&flower_services[i],
+ &app_flower->flower_services_ids[i]);
+ if (ret != 0) {
+ PMD_INIT_LOG(WARNING,
+ "Could not register Flower PF vNIC service");
+ break;
+ }
+
+ PMD_INIT_LOG(INFO, "Flower PF vNIC service registered");
+
+ /* Map them to available service cores*/
+ ret = nfp_map_service(app_flower->flower_services_ids[i]);
+ if (ret != 0)
+ break;
+ }
+
+ return ret;
+}
+
+int
+nfp_init_app_flower(struct nfp_pf_dev *pf_dev)
+{
+ int ret;
+ unsigned int numa_node;
+ struct nfp_net_hw *pf_hw;
+ struct nfp_app_flower *app_flower;
+
+ numa_node = rte_socket_id();
+
+ /* Allocate memory for the Flower app */
+ app_flower = rte_zmalloc_socket("nfp_app_flower", sizeof(*app_flower),
+ RTE_CACHE_LINE_SIZE, numa_node);
+ if (app_flower == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ pf_dev->app_priv = app_flower;
+
+ /* Allocate memory for the PF AND ctrl vNIC here (hence the * 2) */
+ pf_hw = rte_zmalloc_socket("nfp_pf_vnic", 2 * sizeof(struct nfp_net_adapter),
+ RTE_CACHE_LINE_SIZE, numa_node);
+ if (pf_hw == NULL) {
+ ret = -ENOMEM;
+ goto app_cleanup;
+ }
+
+ /* Start up flower services */
+ ret = nfp_flower_enable_services(app_flower);
+ if (ret != 0) {
+ ret = -ESRCH;
+ goto vnic_cleanup;
+ }
+
+ return 0;
+
+vnic_cleanup:
+ rte_free(pf_hw);
+app_cleanup:
+ rte_free(app_flower);
+done:
+ return ret;
+}
+
+int
+nfp_secondary_init_app_flower(__rte_unused struct nfp_cpp *cpp)
+{
+ PMD_INIT_LOG(ERR, "Flower firmware not supported");
+ return -ENOTSUP;
+}
new file mode 100644
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _NFP_FLOWER_H_
+#define _NFP_FLOWER_H_
+
+enum nfp_flower_service {
+ NFP_FLOWER_SERVICE_MAX
+};
+
+/* The flower application's private structure */
+struct nfp_app_flower {
+ /* List of rte_service ID's for the flower app */
+ uint32_t flower_services_ids[NFP_FLOWER_SERVICE_MAX];
+};
+
+int nfp_init_app_flower(struct nfp_pf_dev *pf_dev);
+int nfp_secondary_init_app_flower(struct nfp_cpp *cpp);
+
+#endif /* _NFP_FLOWER_H_ */
@@ -6,6 +6,7 @@ if not is_linux or not dpdk_conf.get('RTE_ARCH_64')
reason = 'only supported on 64-bit Linux'
endif
sources = files(
+ 'flower/nfp_flower.c',
'nfpcore/nfp_cpp_pcie_ops.c',
'nfpcore/nfp_nsp.c',
'nfpcore/nfp_cppcore.c',
@@ -114,6 +114,7 @@
/* Firmware application ID's */
enum nfp_app_id {
NFP_APP_CORE_NIC = 0x1,
+ NFP_APP_FLOWER_NIC = 0x3,
};
/* nfp_qcp_ptr - Read or Write Pointer of a queue */
@@ -28,22 +28,86 @@
static int nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp);
static int nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp);
static int nfp_cpp_bridge_serve_ioctl(int sockfd, struct nfp_cpp *cpp);
+static int nfp_cpp_bridge_service_func(void *args);
-void nfp_register_cpp_service(struct nfp_cpp *cpp)
+static struct rte_service_spec cpp_service = {
+ .name = "nfp_cpp_service",
+ .callback = nfp_cpp_bridge_service_func,
+};
+
+int
+nfp_map_service(uint32_t service_id)
{
- uint32_t *cpp_service_id = NULL;
- struct rte_service_spec service;
+ int32_t ret;
+ uint32_t slcore = 0;
+ int32_t slcore_count;
+ uint8_t service_count;
+ const char *service_name;
+ uint32_t slcore_array[RTE_MAX_LCORE];
+ uint8_t min_service_count = UINT8_MAX;
+
+ slcore_count = rte_service_lcore_list(slcore_array, RTE_MAX_LCORE);
+ if (slcore_count <= 0) {
+ PMD_INIT_LOG(DEBUG, "No service cores found");
+ return -ENOENT;
+ }
+
+ /*
+ * Find a service core with the least number of services already
+ * registered to it
+ */
+ while (slcore_count--) {
+ service_count = rte_service_lcore_count_services(slcore_array[slcore_count]);
+ if (service_count < min_service_count) {
+ slcore = slcore_array[slcore_count];
+ min_service_count = service_count;
+ }
+ }
- memset(&service, 0, sizeof(struct rte_service_spec));
- snprintf(service.name, sizeof(service.name), "nfp_cpp_service");
- service.callback = nfp_cpp_bridge_service_func;
- service.callback_userdata = (void *)cpp;
+ service_name = rte_service_get_name(service_id);
+ PMD_INIT_LOG(INFO, "Mapping service %s to core %u", service_name, slcore);
+ ret = rte_service_map_lcore_set(service_id, slcore, 1);
+ if (ret != 0) {
+ PMD_INIT_LOG(DEBUG, "Could not map flower service");
+ return -ENOENT;
+ }
- if (rte_service_component_register(&service,
- cpp_service_id))
- RTE_LOG(WARNING, PMD, "NFP CPP bridge service register() failed");
+ rte_service_runstate_set(service_id, 1);
+ rte_service_component_runstate_set(service_id, 1);
+ rte_service_lcore_start(slcore);
+ if (rte_service_may_be_active(slcore))
+ RTE_LOG(INFO, PMD, "The service %s is running", service_name);
else
- RTE_LOG(DEBUG, PMD, "NFP CPP bridge service registered");
+ RTE_LOG(INFO, PMD, "The service %s is not running", service_name);
+
+ return 0;
+}
+
+int nfp_enable_cpp_service(struct nfp_cpp *cpp, enum nfp_app_id app_id)
+{
+ int ret = 0;
+ uint32_t id = 0;
+
+ cpp_service.callback_userdata = (void *)cpp;
+
+ /* Register the cpp service */
+ ret = rte_service_component_register(&cpp_service, &id);
+ if (ret != 0) {
+ PMD_INIT_LOG(WARNING, "Could not register nfp cpp service");
+ return -EINVAL;
+ }
+
+ PMD_INIT_LOG(INFO, "NFP cpp service registered");
+
+ /* Map it to available service core*/
+ ret = nfp_map_service(id);
+ if (ret != 0) {
+ PMD_INIT_LOG(DEBUG, "Could not map nfp cpp service");
+ if (app_id == NFP_APP_FLOWER_NIC)
+ return -EINVAL;
+ }
+
+ return 0;
}
/*
@@ -307,7 +371,7 @@ void nfp_register_cpp_service(struct nfp_cpp *cpp)
* unaware of the CPP bridge performing the NFP kernel char driver for CPP
* accesses.
*/
-int32_t
+static int
nfp_cpp_bridge_service_func(void *args)
{
struct sockaddr address;
@@ -16,6 +16,8 @@
#ifndef _NFP_CPP_BRIDGE_H_
#define _NFP_CPP_BRIDGE_H_
+#include "nfp_common.h"
+
#define NFP_CPP_MEMIO_BOUNDARY (1 << 20)
#define NFP_BRIDGE_OP_READ 20
#define NFP_BRIDGE_OP_WRITE 30
@@ -24,8 +26,8 @@
#define NFP_IOCTL 'n'
#define NFP_IOCTL_CPP_IDENTIFICATION _IOW(NFP_IOCTL, 0x8f, uint32_t)
-void nfp_register_cpp_service(struct nfp_cpp *cpp);
-int32_t nfp_cpp_bridge_service_func(void *args);
+int nfp_map_service(uint32_t service_id);
+int nfp_enable_cpp_service(struct nfp_cpp *cpp, enum nfp_app_id app_id);
#endif /* _NFP_CPP_BRIDGE_H_ */
/*
@@ -38,6 +38,8 @@
#include "nfp_ctrl.h"
#include "nfp_cpp_bridge.h"
+#include "flower/nfp_flower.h"
+
static int
nfp_net_pf_read_mac(struct nfp_app_nic *app_nic, int port)
{
@@ -837,7 +839,8 @@
}
static int
-nfp_pf_init(struct rte_pci_device *pci_dev)
+nfp_pf_init(struct rte_pci_device *pci_dev,
+ struct rte_pci_driver *pci_drv)
{
int ret;
int err = 0;
@@ -964,6 +967,16 @@
goto hwqueues_cleanup;
}
break;
+ case NFP_APP_FLOWER_NIC:
+ PMD_INIT_LOG(INFO, "Initializing Flower");
+ pci_dev->device.driver = &pci_drv->driver;
+ ret = nfp_init_app_flower(pf_dev);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Could not initialize Flower!");
+ pci_dev->device.driver = NULL;
+ goto hwqueues_cleanup;
+ }
+ break;
default:
PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
ret = -EINVAL;
@@ -971,7 +984,12 @@
}
/* register the CPP bridge service here for primary use */
- nfp_register_cpp_service(pf_dev->cpp);
+ ret = nfp_enable_cpp_service(pf_dev->cpp, pf_dev->app_id);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Enable cpp service failed.");
+ ret = -EINVAL;
+ goto hwqueues_cleanup;
+ }
return 0;
@@ -1095,6 +1113,14 @@
goto sym_tbl_cleanup;
}
break;
+ case NFP_APP_FLOWER_NIC:
+ PMD_INIT_LOG(INFO, "Initializing Flower");
+ ret = nfp_secondary_init_app_flower(cpp);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Could not initialize Flower!");
+ goto sym_tbl_cleanup;
+ }
+ break;
default:
PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
ret = -EINVAL;
@@ -1105,7 +1131,11 @@
goto sym_tbl_cleanup;
/* Register the CPP bridge service for the secondary too */
- nfp_register_cpp_service(cpp);
+ ret = nfp_enable_cpp_service(cpp, app_id);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Enable cpp service failed.");
+ ret = -EINVAL;
+ }
sym_tbl_cleanup:
free(sym_tbl);
@@ -1114,11 +1144,11 @@
}
static int
-nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+nfp_pf_pci_probe(struct rte_pci_driver *pci_drv,
struct rte_pci_device *dev)
{
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
- return nfp_pf_init(dev);
+ return nfp_pf_init(dev, pci_drv);
else
return nfp_pf_secondary_init(dev);
}