From: Gagandeep Singh <[email protected]> Add support for the DPAA Offline/Host-command (O/H) port, allowing a single OL port to be used by a DPDK application. The feature is selected through the 'drv_oldev' bus device argument, and the associated back-half port is named through the 'drv_bh_port' device argument.
Signed-off-by: Gagandeep Singh <[email protected]> Signed-off-by: Hemant Agrawal <[email protected]> --- doc/guides/nics/dpaa.rst | 12 + drivers/bus/dpaa/bus_dpaa_driver.h | 11 +- drivers/bus/dpaa/dpaa_bus.c | 87 +++- drivers/net/dpaa/dpaa_ethdev.h | 3 + drivers/net/dpaa/dpaa_oldev.c | 701 ++++++++++++++++++++++++++ drivers/net/dpaa/meson.build | 11 +- drivers/net/dpaa/rte_pmd_dpaa_oldev.h | 92 ++++ 7 files changed, 905 insertions(+), 12 deletions(-) create mode 100644 drivers/net/dpaa/dpaa_oldev.c create mode 100644 drivers/net/dpaa/rte_pmd_dpaa_oldev.h diff --git a/doc/guides/nics/dpaa.rst b/doc/guides/nics/dpaa.rst index d4b683ba24..d11a30ca2e 100644 --- a/doc/guides/nics/dpaa.rst +++ b/doc/guides/nics/dpaa.rst @@ -296,6 +296,18 @@ the ``-a`` EAL option (e.g. ``-a dpaa_bus:fm1-mac3,drv_rx_taildrop=64``): Provide the kernel Linux interface name for a shared MAC interface when it differs from the ``fmX-macY`` style name used by DPDK. +* ``drv_bh_port`` + + Name of the back-half port associated with an offline (O/H) port device. + +The following bus-level device arguments configure the DPAA bus itself and +are passed through the EAL bus arguments (e.g. ``--vdev`` / ``-a`` bus +options, ``bus=dpaa,drv_oldev=1``): + +* ``drv_oldev`` (default disabled) + + Enable the DPAA offline (O/H) port device. + FMAN Config ----------- diff --git a/drivers/bus/dpaa/bus_dpaa_driver.h b/drivers/bus/dpaa/bus_dpaa_driver.h index 4aed83f84d..f58aa47357 100644 --- a/drivers/bus/dpaa/bus_dpaa_driver.h +++ b/drivers/bus/dpaa/bus_dpaa_driver.h @@ -69,11 +69,13 @@ struct rte_dpaa_driver; enum rte_dpaa_type { FSL_DPAA_ETH = 1, FSL_DPAA_CRYPTO, - FSL_DPAA_QDMA + FSL_DPAA_QDMA, + FSL_DPAA_OL }; struct dpaa_device_id { uint8_t fman_id; /**< Fman interface ID, for ETH type device */ + uint8_t ol_id; /**< OH interface ID, for OH type device */ uint8_t mac_id; /**< Fman MAC interface ID, for ETH type device */ uint16_t dev_id; /**< Device Identifier from DPDK */ }; @@ -216,6 +218,13 @@ int rte_dpaa_portal_fq_init(void *arg, struct qman_fq *fq); __rte_internal int rte_dpaa_portal_fq_close(struct qman_fq *fq); +/** + * Return non-zero if the DPAA offline (O/H) port device is enabled through + * the "drv_oldev" bus device argument. + */ +__rte_internal +int rte_dpaa_bus_oldev_enabled(void); + /** * Cleanup a DPAA Portal */ diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c index fe1003a1d9..16892b5247 100644 --- a/drivers/bus/dpaa/dpaa_bus.c +++ b/drivers/bus/dpaa/dpaa_bus.c @@ -34,6 +34,8 @@ #include <bus_driver.h> #include <rte_mbuf_pool_ops.h> #include <rte_mbuf_dyn.h> +#include <rte_kvargs.h> +#include <rte_devargs.h> #include <dpaa_of.h> #include <bus_dpaa_driver.h> @@ -66,8 +68,12 @@ struct rte_dpaa_bus_private { uint32_t svr_ver; uint16_t max_push_rxq_num; RTE_ATOMIC(uint16_t) push_rxq_num; + int oldev_enabled; /**< "drv_oldev" bus devarg */ }; +/* Bus level device argument keys */ +#define DPAA_BUS_ARG_OLDEV "drv_oldev" + static struct rte_bus rte_dpaa_bus; static struct rte_dpaa_bus_private dpaa_bus; static struct netcfg_info *dpaa_netcfg; @@ -78,6 +84,42 @@ static pthread_key_t dpaa_portal_key; struct dpaa_portal *dpaa_portals[RTE_MAX_LCORE] = {NULL}; static int dpaa_bus_global_init; +/* + * Parse the bus-level device arguments (specified through the EAL bus + * arguments, e.g. "bus=dpaa,drv_oldev=1") and cache the resulting flags + * in the bus private structure. Replaces the previous environment-variable + * based configuration. + */ +static int +dpaa_bus_parse_bus_args(void) +{ + struct rte_devargs *devargs; + struct rte_kvargs *kvlist; + + RTE_EAL_DEVARGS_FOREACH("dpaa", devargs) { + if (devargs->bus_str == NULL) + continue; + + kvlist = rte_kvargs_parse(devargs->bus_str, NULL); + if (kvlist == NULL) + continue; + + if (rte_kvargs_count(kvlist, DPAA_BUS_ARG_OLDEV)) + dpaa_bus.oldev_enabled = 1; + + rte_kvargs_free(kvlist); + } + + return 0; +} + +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa_bus_oldev_enabled) +int +rte_dpaa_bus_oldev_enabled(void) +{ + return dpaa_bus.oldev_enabled; +} + RTE_EXPORT_INTERNAL_SYMBOL(per_lcore_dpaa_io) RTE_DEFINE_PER_LCORE(struct dpaa_portal *, dpaa_io); @@ -209,6 +251,31 @@ dpaa_create_device_list(void) dpaa_bus.device_count = 0; + if (!dpaa_netcfg && dpaa_bus.oldev_enabled) + return 0; + + /* Creating OL Device */ + if (dpaa_bus.oldev_enabled) { + dev = calloc(1, sizeof(struct rte_dpaa_device)); + if (!dev) { + DPAA_BUS_ERR("Failed to allocate OL devices"); + return -ENOMEM; + } + + dev->device_type = FSL_DPAA_OL; + dev->id.ol_id = 0; + dev->id.dev_id = dpaa_bus.device_count; + + /* Create device name */ + memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN); + sprintf(dev->name, "oldev%d", (dev->id.ol_id + 1)); + DPAA_BUS_INFO("%s oldev added", dev->name); + dev->device.name = dev->name; + + dpaa_add_to_device_list(dev); + dpaa_bus.device_count++; + } + /* Creating Ethernet Devices */ for (i = 0; dpaa_netcfg && (i < dpaa_netcfg->num_ethports); i++) { dev = calloc(1, sizeof(struct rte_dpaa_device)); @@ -619,7 +686,7 @@ rte_dpaa_bus_dev_build(void) /* Get the interface configurations from device-tree */ dpaa_netcfg = netcfg_acquire(); - if (!dpaa_netcfg) { + if (!dpaa_netcfg && !dpaa_bus.oldev_enabled) { DPAA_BUS_ERR("netcfg failed: /dev/fsl_usdpaa device not available"); DPAA_BUS_WARN("Check if you are using USDPAA based device tree"); return -EINVAL; @@ -627,17 +694,20 @@ rte_dpaa_bus_dev_build(void) DPAA_BUS_LOG(NOTICE, "DPAA Bus Detected"); - if (!dpaa_netcfg->num_ethports) { - DPAA_BUS_INFO("NO DPDK mapped net interfaces available"); - /* This is not an error */ + if (!dpaa_bus.oldev_enabled) { + if (!dpaa_netcfg->num_ethports) { + DPAA_BUS_INFO("NO DPDK mapped net interfaces available"); + /* This is not an error */ + } } #ifdef RTE_LIBRTE_DPAA_DEBUG_DRIVER dump_netcfg(dpaa_netcfg, stdout); #endif - - DPAA_BUS_DEBUG("Number of ethernet devices = %d", + if (!dpaa_bus.oldev_enabled) { + DPAA_BUS_DEBUG("Number of ethernet devices = %d", dpaa_netcfg->num_ethports); + } ret = dpaa_create_device_list(); if (ret) { DPAA_BUS_ERR("Unable to create device list. (%d)", ret); @@ -690,6 +760,11 @@ rte_dpaa_bus_scan(void) dpaa_bus.detected = 1; + /* Parse bus-level device arguments (drv_oldev) before building the + * device list. + */ + dpaa_bus_parse_bus_args(); + /* create the key, supplying a function that'll be invoked * when a portal affined thread will be deleted. */ diff --git a/drivers/net/dpaa/dpaa_ethdev.h b/drivers/net/dpaa/dpaa_ethdev.h index d3e005b556..8d366830eb 100644 --- a/drivers/net/dpaa/dpaa_ethdev.h +++ b/drivers/net/dpaa/dpaa_ethdev.h @@ -116,6 +116,9 @@ enum { #define DPAA_DEFAULT_RXQ_VSP_ID 1 +/* Device argument to name the offline (O/H) port back-half port */ +#define DRIVER_OL_BH_PORT "drv_bh_port" + #define FMC_FILE "/tmp/fmc.bin" struct dpaa_if_vsp { diff --git a/drivers/net/dpaa/dpaa_oldev.c b/drivers/net/dpaa/dpaa_oldev.c new file mode 100644 index 0000000000..efe8322fd8 --- /dev/null +++ b/drivers/net/dpaa/dpaa_oldev.c @@ -0,0 +1,701 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020-2026 NXP + */ + +#include <stdio.h> +#include <sys/ioctl.h> + +#include <rte_dpaa_logs.h> +#include <rte_kvargs.h> +#include <rte_string_fns.h> +#include <bus_dpaa_driver.h> +#include <dpaa_ethdev.h> +#include <dpaa_rxtx.h> +#include <dpaa_mempool.h> + +#include <eal_export.h> +#include <fsl_fman.h> + +#include "rte_pmd_dpaa_oldev.h" + +/* The ol device is a tx are queue pair, which is provided to the kernel through + * ioctl calls. It is exposed as a virtual port to the application. + * This ASK Device provides IOCTL calls to driver for communicating fqid's, + * buffer pool id's and channel id's with kernel. + */ +#define ASK_PATH "/dev/cdx_ctrl" +#define CDX_IOC_MAGIC 0xbe + +#define MAX_BH_PORT_NAME_LEN 12 + +static int fd = -1; +static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER; + +struct ask_ctrl_offline_channel { + uint32_t channel_id; + uint32_t ctx_a_hi_val; /* Setting required flags(B0,A2) while creating + * frame queue. + */ + uint32_t ctx_a_lo_val; /* EBD and VSP enable bits */ + uint32_t ctx_b_val; /* VSP ID */ +}; + +struct ask_ctrl_dpdk_fq_info_s { + uint32_t tx_fq_id; /* DPDK transmits GTP packets using FQ + * ID + */ + uint32_t rx_fq_id; /* DPDK receives packets from FMAN */ + uint16_t buff_size; /* Size of each buffer in DPDPK buffer + * pool + */ + uint8_t bp_id; /* DPDK buffer pool id */ + /* BH port interface name , for testing purpose */ + uint8_t bh_port_name[MAX_BH_PORT_NAME_LEN]; + /* below fields are taken from structure t_FmBufferPrefixContent, These + * fields are required for VSP creation on DPDK buffer pool ID. These + * fields should be set based on expected parameters from FMAN + */ + uint16_t privDataSize; /* Number of bytes to be left at the + * beginning of the external buffer; + * Note that the private-area will start + * from the base of the buffer address. + */ + bool passPrsResult; /* TRUE to pass the parse result to/from + * the FM; User may use + * FM_PORT_GetBufferPrsResult() in order + * to get the parser-result from a + * buffer. + */ + bool passTimeStamp; /* < TRUE to pass the timeStamp to/from + * the FM User may use + * FM_PORT_GetBufferTimeStamp() in order + * to get the parser-result from a + * buffer. + */ + bool passHashResult; /* TRUE to pass the KG hash result + * to/from the FM User may use + * FM_PORT_GetBufferHashResult() in + * order to get the parser-result from a + * buffer. + */ + bool passAllOtherPCDInfo; /* Add all other Internal-Context + * information: AD, hash-result, key, + * etc. + */ + uint16_t dataAlign; /* 0 to use driver's default alignment + * [DEFAULT_FM_SP_bufferPrefixContent_dataAlign], + * other value for selecting a data + * alignment (must be a power of 2); if + * write optimization is used, must be + * >= 16. + */ + uint8_t manipExtraSpace; /* Maximum extra size needed (insertion- + * size minus removal-size); Note that + * this field impacts the size of the + * buffer-prefix (i.e. it pushes the + * data offset); This field is + * irrelevant if DPAA_VERSION==10 + */ +}; + +#define ASK_CTRL_GET_OFFLINE_CHANNEL_INFO \ + _IOWR(CDX_IOC_MAGIC, 8, struct ask_ctrl_offline_channel) +#define ASK_CTRL_SET_DPDK_INFO \ + _IOWR(CDX_IOC_MAGIC, 9, struct ask_ctrl_dpdk_fq_info_s) +#define ASK_CTRL_SET_CLASSIF_INFO \ + _IOWR(CDX_IOC_MAGIC, 10, struct rte_pmd_dpaa_uplink_cls_info_s) +#define ASK_CTRL_RESET_CLASSIF_INFO \ + _IOWR(CDX_IOC_MAGIC, 11, struct rte_pmd_dpaa_uplink_cls_info_s) +#define ASK_CTRL_SET_LGW_INFO \ + _IOWR(CDX_IOC_MAGIC, 12, struct rte_pmd_dpaa_lgw_info_s) +#define ASK_CTRL_RESET_LGW_INFO \ + _IOWR(CDX_IOC_MAGIC, 13, struct rte_pmd_dpaa_lgw_info_s) + + +static int check_fd(void) +{ + int ret; + + if (fd >= 0) + return 0; + ret = pthread_mutex_lock(&fd_init_lock); + assert(!ret); + /* check again with the lock held */ + if (fd < 0) + fd = open(ASK_PATH, O_RDWR); + ret = pthread_mutex_unlock(&fd_init_lock); + assert(!ret); + return (fd >= 0) ? 0 : -ENODEV; +} + +static uint32_t ask_get_channel_info(struct ask_ctrl_offline_channel *ch_info) +{ + int ret = check_fd(); + if (ret) + return ret; + + ret = ioctl(fd, ASK_CTRL_GET_OFFLINE_CHANNEL_INFO, ch_info); + if (!ret) { + DPAA_PMD_DEBUG("Get channel info successful"); + DPAA_PMD_DEBUG("Channel id: %x", ch_info->channel_id); + DPAA_PMD_DEBUG("ctx_a_hi_val: %x", ch_info->ctx_a_hi_val); + DPAA_PMD_DEBUG("ctx_a_lo_val: %x", ch_info->ctx_a_lo_val); + DPAA_PMD_DEBUG("ctx_b_val: %x", ch_info->ctx_b_val); + } else { + DPAA_PMD_ERR("Get channel info ioctl failed with errno: %s", + strerror(errno)); + } + + return ret; +} + +static int ask_set_fq_info(struct ask_ctrl_dpdk_fq_info_s *fq_info) +{ + int ret = check_fd(); + if (ret) + return ret; + + ret = ioctl(fd, ASK_CTRL_SET_DPDK_INFO, fq_info); + if (!ret) { + DPAA_PMD_DEBUG("Set fq info successful"); + DPAA_PMD_DEBUG("Tx fqid: %x", fq_info->tx_fq_id); + DPAA_PMD_DEBUG("Rx fqid: %x", fq_info->rx_fq_id); + DPAA_PMD_DEBUG("buff_size: %d", fq_info->buff_size); + DPAA_PMD_DEBUG("bp_id: %d", fq_info->bp_id); + DPAA_PMD_DEBUG("Backhaul port name: %s", + fq_info->bh_port_name); + } else { + DPAA_PMD_ERR("Set FQ info ioctl failed with errno: %s", + strerror(errno)); + } + + return ret; +} + +static int +dpaa_ol_dev_configure(__rte_unused struct rte_eth_dev *dev) +{ + PMD_INIT_FUNC_TRACE(); + + return 0; +} + +static int dpaa_ol_dev_info(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info) +{ + struct dpaa_if *dpaa_intf = dev->data->dev_private; + + PMD_INIT_FUNC_TRACE(); + + dev_info->max_rx_queues = dpaa_intf->nb_rx_queues; + dev_info->max_tx_queues = dpaa_intf->nb_tx_queues; + dev_info->max_rx_pktlen = DPAA_MAX_RX_PKT_LEN; + dev_info->max_mac_addrs = DPAA_MAX_MAC_FILTER; + dev_info->max_hash_mac_addrs = 0; + dev_info->max_vfs = 0; + + dev_info->speed_capa = RTE_ETH_LINK_SPEED_10M_HD | + RTE_ETH_LINK_SPEED_10M | + RTE_ETH_LINK_SPEED_100M_HD | + RTE_ETH_LINK_SPEED_100M | + RTE_ETH_LINK_SPEED_1G | + RTE_ETH_LINK_SPEED_2_5G | + RTE_ETH_LINK_SPEED_10G; + + return 0; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa_ol_set_classif_info, 25.11) +int rte_pmd_dpaa_ol_set_classif_info(struct rte_pmd_dpaa_uplink_cls_info_s *classif_info) +{ + int i, ret = check_fd(); + if (ret) + return ret; + + if (classif_info == NULL) { + DPAA_PMD_ERR("No classification data available"); + return -1; + } + + ret = ioctl(fd, ASK_CTRL_SET_CLASSIF_INFO, classif_info); + if (!ret) { + DPAA_PMD_DEBUG("Set classification info successful"); + for (i = 0; i < classif_info->num_ports; i++) { + DPAA_PMD_DEBUG("UDP dest port: %d", + classif_info->gtp_udp_port[i]); + } + DPAA_PMD_DEBUG("Protocol ID: %d", + classif_info->gtp_proto_id); + } else { + DPAA_PMD_ERR("Set classification info ioctl failed with errno: %s", + strerror(errno)); + } + + return ret; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa_ol_reset_classif_info, 25.11) +int rte_pmd_dpaa_ol_reset_classif_info(void) +{ + struct rte_pmd_dpaa_uplink_cls_info_s classif_info; + int ret = 0; + + memset(&classif_info, 0, sizeof(classif_info)); + ret = check_fd(); + if (ret) + return ret; + + ret = ioctl(fd, ASK_CTRL_RESET_CLASSIF_INFO, &classif_info); + if (ret) { + DPAA_PMD_ERR("Reset classification info ioctl failed with errno: %s", + strerror(errno)); + } else { + DPAA_PMD_DEBUG("Reset classification info successful"); + } + + return ret; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa_ol_set_lgw_info, 25.11) +int rte_pmd_dpaa_ol_set_lgw_info(struct rte_pmd_dpaa_lgw_info_s *lgw_info) +{ + int ret = check_fd(); + if (ret) + return ret; + + if (lgw_info == NULL) { + DPAA_PMD_ERR("No LGW data available"); + return -1; + } + ret = ioctl(fd, ASK_CTRL_SET_LGW_INFO, lgw_info); + if (!ret) { + DPAA_PMD_DEBUG("Set LGW info successful"); + } else { + DPAA_PMD_ERR("Set LGW info ioctl failed with errno: %s", + strerror(errno)); + } + + return ret; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa_ol_reset_lgw_info, 25.11) +int rte_pmd_dpaa_ol_reset_lgw_info(void) +{ + struct rte_pmd_dpaa_lgw_info_s lgw_info; + int ret = 0; + + PMD_INIT_FUNC_TRACE(); + + memset(&lgw_info, 0, sizeof(lgw_info)); + ret = check_fd(); + if (ret) + return ret; + + ret = ioctl(fd, ASK_CTRL_RESET_LGW_INFO, &lgw_info); + if (ret) { + DPAA_PMD_ERR("Reset LGW info ioctl failed with errno: %s", + strerror(errno)); + } else { + DPAA_PMD_DEBUG("Reset LGW info successful"); + } + + return ret; +} + +static int dpaa_ol_dev_start(struct rte_eth_dev *dev) +{ + PMD_INIT_FUNC_TRACE(); + + dev->tx_pkt_burst = dpaa_eth_queue_tx; + + return 0; +} + +static int dpaa_ol_dev_stop(struct rte_eth_dev *dev) +{ + PMD_INIT_FUNC_TRACE(); + + dev->tx_pkt_burst = dpaa_eth_tx_drop_all; + + return 0; +} + +static int dpaa_ol_dev_close(__rte_unused struct rte_eth_dev *dev) +{ + PMD_INIT_FUNC_TRACE(); + + return 0; +} + +static inline void +dpaa_poll_queue_default_config(struct qm_mcc_initfq *opts) +{ + memset(opts, 0, sizeof(struct qm_mcc_initfq)); + opts->we_mask = QM_INITFQ_WE_CONTEXTA; + opts->fqd.fq_ctrl = QM_FQCTRL_AVOIDBLOCK | QM_FQCTRL_CTXASTASHING | + QM_FQCTRL_PREFERINCACHE; + opts->fqd.context_a.stashing.exclusive = 0; + if (dpaa_soc_ver() != SVR_LS1046A_FAMILY) + opts->fqd.context_a.stashing.annotation_cl = + DPAA_IF_RX_ANNOTATION_STASH; + opts->fqd.context_a.stashing.data_cl = DPAA_IF_RX_DATA_STASH; + opts->fqd.context_a.stashing.context_cl = DPAA_IF_RX_CONTEXT_STASH; +} + +static +int dpaa_ol_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, + __rte_unused uint16_t nb_desc, + unsigned int socket_id __rte_unused, + __rte_unused const struct rte_eth_rxconf *rx_conf, + struct rte_mempool *mp) +{ + struct dpaa_if *dpaa_intf = dev->data->dev_private; + struct qman_fq *rxq = &dpaa_intf->rx_queues[queue_idx]; + + PMD_INIT_FUNC_TRACE(); + + if (queue_idx >= dev->data->nb_rx_queues) { + rte_errno = EOVERFLOW; + DPAA_PMD_ERR("%p: queue index out of range (%u >= %u)", + (void *)dev, queue_idx, dev->data->nb_rx_queues); + return -rte_errno; + } + + dpaa_intf->bp_info = DPAA_MEMPOOL_TO_POOL_INFO(mp); + dpaa_intf->valid = 1; + + rxq->bp_array = rte_dpaa_bpid_info; + dev->data->rx_queues[queue_idx] = rxq; + + return 0; +} + +/* This API has dependency on RX queue setup */ +static int +dpaa_ol_get_bh_port_name(struct rte_devargs *devargs, char *val, size_t size) +{ + struct rte_kvargs *kvlist; + const char *str; + int ret; + + if (!devargs) + return 0; + + kvlist = rte_kvargs_parse(devargs->args, NULL); + if (!kvlist) + return 0; + + if (!rte_kvargs_count(kvlist, DRIVER_OL_BH_PORT)) { + rte_kvargs_free(kvlist); + return 0; + } + + str = rte_kvargs_get(kvlist, DRIVER_OL_BH_PORT); + if (str == NULL) { + rte_kvargs_free(kvlist); + return 0; + } + + ret = rte_strscpy(val, str, size); + rte_kvargs_free(kvlist); + if (ret < 0) + return ret; + + return 1; +} + +static +int dpaa_ol_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, + uint16_t nb_desc __rte_unused, + unsigned int socket_id __rte_unused, + const struct rte_eth_txconf *tx_conf __rte_unused) +{ + struct dpaa_if *dpaa_intf = dev->data->dev_private; + struct qman_fq *txq = &dpaa_intf->tx_queues[queue_idx]; + struct qman_fq *rxq = &dpaa_intf->rx_queues[queue_idx]; + struct ask_ctrl_dpdk_fq_info_s fq_info; + int ret; + struct rte_pktmbuf_pool_private *mbp_priv; + + PMD_INIT_FUNC_TRACE(); + + dev->data->tx_queues[queue_idx] = txq; + + if (dpaa_intf->bp_info == NULL || rxq == NULL) + return 0; + + mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(dpaa_intf->bp_info->mp); + fq_info.tx_fq_id = txq->fqid; + fq_info.rx_fq_id = rxq->fqid; + fq_info.buff_size = mbp_priv->mbuf_data_room_size; + fq_info.bp_id = dpaa_intf->bp_info->bpid; + +/* Private area reserved by driver. + * Aligned with "struct annotations_t". Parse results will be written from + * the 17th byte by the HW. + */ +#define DPAA_OL_PARSERSLT_START_OFFSET 16 +#define DPAA_OL_DATA_ALIGNMENT 64 +/* Change this value to increase the data offset. + * final value will be aligned by DPAA_OL_DATA_ALIGNMENT + */ +#define DPAA_OL_MAX_EXTRA_SIZE 0 +#define DPAA_OL_PARSE_RESULT_REQUIRED true +#define DPAA_OL_TIME_STAMP_REQUIRED false +#define DPAA_OL_HASH_RESULT_REQUIRED false +#define DPAA_OL_PCD_INFO_REQUIRED false + + fq_info.privDataSize = DPAA_OL_PARSERSLT_START_OFFSET; + fq_info.passPrsResult = DPAA_OL_PARSE_RESULT_REQUIRED; + fq_info.passTimeStamp = DPAA_OL_TIME_STAMP_REQUIRED; + fq_info.passHashResult = DPAA_OL_HASH_RESULT_REQUIRED; + fq_info.passAllOtherPCDInfo = DPAA_OL_PCD_INFO_REQUIRED; + fq_info.dataAlign = DPAA_OL_DATA_ALIGNMENT; + fq_info.manipExtraSpace = DPAA_OL_MAX_EXTRA_SIZE; + + ret = dpaa_ol_get_bh_port_name(dev->device->devargs, + (char *)fq_info.bh_port_name, + MAX_BH_PORT_NAME_LEN); + if (ret <= 0) { + DPAA_PMD_ERR("Offline port \"%s\" devarg not defined or invalid", + DRIVER_OL_BH_PORT); + return -1; + } + + ret = ask_set_fq_info(&fq_info); + if (ret) { + DPAA_PMD_ERR("Set FQ info failed with ret: %d", ret); + return ret; + } + + return 0; +} + +static int dpaa_ol_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete) +{ + struct dpaa_if *dpaa_intf = dev->data->dev_private; + struct rte_eth_link *link = &dev->data->dev_link; + + PMD_INIT_FUNC_TRACE(); + + PMD_INIT_FUNC_TRACE(); + + link->link_status = dpaa_intf->valid; + link->link_speed = RTE_ETH_SPEED_NUM_NONE; + link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX; + link->link_autoneg = RTE_ETH_LINK_AUTONEG; + + return 0; +} + +static int dpaa_ol_promiscuous_enable(__rte_unused struct rte_eth_dev *dev) +{ + PMD_INIT_FUNC_TRACE(); + + return 0; +} + +static int dpaa_ol_rx_queue_init(struct qman_fq *fq, uint32_t fqid) +{ + int ret; + struct qm_mcc_initfq opts = {0}; + u32 flags = QMAN_FQ_FLAG_DYNAMIC_FQID | QMAN_FQ_FLAG_NO_ENQUEUE; + + if (unlikely(!DPAA_PER_LCORE_PORTAL)) { + ret = rte_dpaa_portal_init(NULL); + if (ret < 0) { + DPAA_PMD_ERR("portal initialization failure"); + return ret; + } + } + + ret = qman_create_fq(fqid, flags, fq); + if (ret) { + DPAA_PMD_ERR("create rx fqid 0x%x failed with ret: %d", fqid, + ret); + return ret; + } + fq->is_static = false; + + dpaa_poll_queue_default_config(&opts); + + ret = qman_init_fq(fq, 0, &opts); + if (ret) + DPAA_PMD_ERR("init rx fqid 0x%x failed with ret:%d", fqid, ret); + return ret; +} + +static int dpaa_ol_tx_queue_init(struct qman_fq *fq, uint32_t fqid) +{ + int ret; + struct qm_mcc_initfq opts = {0}; + u32 flags = QMAN_FQ_FLAG_DYNAMIC_FQID | QMAN_FQ_FLAG_TO_DCPORTAL; + struct ask_ctrl_offline_channel ch_info; + + memset(&ch_info, 0, sizeof(ch_info)); + + ret = ask_get_channel_info(&ch_info); + if (ret) { + DPAA_PMD_ERR("Get channel info failed with ret: %d", ret); + return ret; + } + ret = qman_create_fq(fqid, flags, fq); + if (ret) { + DPAA_PMD_ERR("Create tx fq failed with ret: %d", ret); + return ret; + } + + opts.we_mask = QM_INITFQ_WE_DESTWQ | + QM_INITFQ_WE_CONTEXTB | QM_INITFQ_WE_CONTEXTA; + + opts.fqd.dest.channel = ch_info.channel_id; + +#define DPA_ISC_WQ_ID 2 + opts.fqd.dest.wq = DPA_ISC_WQ_ID; + opts.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; + opts.fqd.context_b = ch_info.ctx_b_val; + opts.fqd.context_a.hi = ch_info.ctx_a_hi_val; + opts.fqd.context_a.lo = ch_info.ctx_a_lo_val; + + opts.fqid = fq->fqid; + fq->ch_id = ch_info.channel_id; + opts.count = 1; + + ret = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &opts); + if (ret) + DPAA_PMD_ERR("init tx fqid 0x%x failed %d", fq->fqid, ret); + return ret; +} + +static struct eth_dev_ops dpaa_ol_devops = { + .dev_configure = dpaa_ol_dev_configure, + .dev_start = dpaa_ol_dev_start, + .dev_stop = dpaa_ol_dev_stop, + .dev_close = dpaa_ol_dev_close, + .dev_infos_get = dpaa_ol_dev_info, + + .rx_queue_setup = dpaa_ol_rx_queue_setup, + .tx_queue_setup = dpaa_ol_tx_queue_setup, + + .link_update = dpaa_ol_link_update, + .promiscuous_enable = dpaa_ol_promiscuous_enable, +}; + +static int dpaa_oldev_init(struct rte_eth_dev *eth_dev) +{ + int num_fqs, ret; + struct dpaa_if *dpaa_intf; + + PMD_INIT_FUNC_TRACE(); + + num_fqs = DPAA_DEFAULT_NUM_PCD_QUEUES; + dpaa_intf = eth_dev->data->dev_private; + + dpaa_intf->rx_queues = rte_zmalloc(NULL, + sizeof(struct qman_fq) * num_fqs, + MAX_CACHELINE); + if (!dpaa_intf->rx_queues) { + DPAA_PMD_ERR("Failed to alloc mem for RX queues"); + return -ENOMEM; + } + + ret = dpaa_ol_rx_queue_init(&dpaa_intf->rx_queues[0], 0); + if (ret) + goto free_rx; + dpaa_intf->rx_queues[0].dpaa_intf = dpaa_intf; + + dpaa_intf->nb_rx_queues = num_fqs; + + dpaa_intf->tx_queues = rte_zmalloc(NULL, + sizeof(struct qman_fq) * num_fqs, + MAX_CACHELINE); + if (!dpaa_intf->tx_queues) { + DPAA_PMD_ERR("Failed to alloc mem for TX queues"); + ret = -ENOMEM; + goto free_rx; + } + + ret = dpaa_ol_tx_queue_init(&dpaa_intf->tx_queues[0], 0); + if (ret) + goto free_tx; + + dpaa_intf->nb_tx_queues = num_fqs; + + eth_dev->dev_ops = &dpaa_ol_devops; + eth_dev->rx_pkt_burst = dpaa_eth_queue_rx; + eth_dev->tx_pkt_burst = dpaa_eth_tx_drop_all; + + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("mac_addr", + RTE_ETHER_ADDR_LEN * DPAA_MAX_MAC_FILTER, 0); + if (eth_dev->data->mac_addrs == NULL) { + DPAA_PMD_ERR("Failed to allocate %d bytes needed to " + "store MAC addresses", + RTE_ETHER_ADDR_LEN * DPAA_MAX_MAC_FILTER); + ret = -ENOMEM; + goto free_tx; + } + + return 0; + +free_tx: + rte_free(dpaa_intf->tx_queues); + dpaa_intf->tx_queues = NULL; + dpaa_intf->nb_tx_queues = 0; +free_rx: + rte_free(dpaa_intf->rx_queues); + dpaa_intf->rx_queues = NULL; + dpaa_intf->nb_rx_queues = 0; + return ret; +} + +static int rte_dpaa_probe(__rte_unused struct rte_dpaa_driver *dpaa_drv, + __rte_unused struct rte_dpaa_device *dpaa_dev) +{ + int ret; + struct rte_eth_dev *eth_dev; + + PMD_INIT_FUNC_TRACE(); + + eth_dev = rte_eth_dev_allocate(dpaa_dev->name); + if (!eth_dev) + return -ENOMEM; + eth_dev->data->dev_private = rte_zmalloc("ethdev private structure", + sizeof(struct dpaa_if), + RTE_CACHE_LINE_SIZE); + if (!eth_dev->data->dev_private) { + DPAA_PMD_ERR("Cannot allocate memzone for port data"); + rte_eth_dev_release_port(eth_dev); + return -ENOMEM; + } + + eth_dev->device = &dpaa_dev->device; + + ret = dpaa_oldev_init(eth_dev); + if (ret == 0) { + rte_eth_dev_probing_finish(eth_dev); + return 0; + } + + rte_eth_dev_release_port(eth_dev); + return ret; +} + +static int rte_dpaa_remove(__rte_unused struct rte_dpaa_device *dpaa_dev) +{ + PMD_INIT_FUNC_TRACE(); + + return 0; +} + +static struct rte_dpaa_driver rte_dpaa_ol_pmd = { + .drv_type = FSL_DPAA_OL, + .probe = rte_dpaa_probe, + .remove = rte_dpaa_remove, +}; + +RTE_PMD_REGISTER_DPAA(ol_dpaa, rte_dpaa_ol_pmd); +RTE_PMD_REGISTER_PARAM_STRING(ol_dpaa, + DRIVER_OL_BH_PORT "=<string>"); + diff --git a/drivers/net/dpaa/meson.build b/drivers/net/dpaa/meson.build index 8d4f69c596..d3ae02946b 100644 --- a/drivers/net/dpaa/meson.build +++ b/drivers/net/dpaa/meson.build @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2020 NXP +# Copyright 2018-2021 NXP if not is_linux build = false @@ -9,12 +9,13 @@ deps += ['mempool_dpaa'] sources = files( 'dpaa_ethdev.c', - 'fmlib/fm_lib.c', - 'fmlib/fm_vsp.c', 'dpaa_flow.c', - 'dpaa_rxtx.c', 'dpaa_fmc.c', 'dpaa_ptp.c', + 'dpaa_oldev.c', + 'dpaa_rxtx.c', + 'fmlib/fm_lib.c', + 'fmlib/fm_vsp.c', ) cflags += no_wvla_cflag @@ -24,4 +25,4 @@ if cc.has_argument('-Wno-pointer-arith') cflags += '-Wno-pointer-arith' endif -headers = files('rte_pmd_dpaa.h') +headers = files('rte_pmd_dpaa.h', 'rte_pmd_dpaa_oldev.h') diff --git a/drivers/net/dpaa/rte_pmd_dpaa_oldev.h b/drivers/net/dpaa/rte_pmd_dpaa_oldev.h new file mode 100644 index 0000000000..6ba61b77b9 --- /dev/null +++ b/drivers/net/dpaa/rte_pmd_dpaa_oldev.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020-2026 NXP + */ + +#ifndef _RTE_PMD_DPAA_OLDEV_H +#define _RTE_PMD_DPAA_OLDEV_H + + +#include <stdint.h> +#include <rte_compat.h> + +#define DPA_ISC_IPV4_ADDR_TYPE 0x04 +#define DPA_ISC_IPV6_ADDR_TYPE 0x06 +#define MAX_NUM_PORTS 2 + +#define DPA_ISC_IPV4_SUBNET_TYPE 0x04 +#define DPA_ISC_IPV6_SUBNET_TYPE 0x06 +#define MAX_NUM_SUBNETS 4 + +/* following macros used for flags field */ +/* this macro should be set when addr pair consisting valid + * inner IP address + */ +#define DPDK_CLASSIF_INNER_IP 0x1 + +/* this macro should be set when addr pair consisting static + * IP address + */ +#define DPDK_CLASSIF_STATIC_IP 0x2 + +/* macro to indicate telecom application is listening on only + * static IP address + */ +#define DPDK_TELECOM_LISTEN_ON_ONLY_STATICIP 0x4 + +/* macro to indicate that telecom application is listening on + * both static and inner IP addresses + */ +#define DPDK_TELECOM_LISTEN_ON_BOTH_STATIC_INNER_IP 0x8 + +/* macro to indicate that telecom application is listening on + * only inner IP address + */ +#define DPDK_TELECOM_LISTEN_ON_ONLY_INNERIP 0x10 + + +struct ip_addr_s { + uint32_t ip_addr[4]; +}; + +struct __rte_packed_begin ip_pair_s { + struct ip_addr_s static_ip, inner_ip; + uint8_t flags; + uint8_t addr_type; + uint8_t pad[2]; +} __rte_packed_end; + +struct __rte_packed_begin lgw_subnet_s { + uint32_t subnet[4]; + uint8_t mask; + uint8_t subnet_type; + uint8_t pad[2]; +} __rte_packed_end; + +struct rte_pmd_dpaa_uplink_cls_info_s { + struct ip_pair_s addr_pair; + uint16_t gtp_udp_port[MAX_NUM_PORTS]; /* DPDK app listens on this GTP ports */ + uint8_t gtp_proto_id; /* DPDK app listens on UDP protocol */ + uint8_t num_ports; + uint8_t sec_enabled; + uint8_t pad; +}; + +struct __rte_packed_begin rte_pmd_dpaa_lgw_info_s { + struct lgw_subnet_s subnets[MAX_NUM_SUBNETS]; + uint8_t num_subnets; + uint8_t pad[3]; +} __rte_packed_end; + +__rte_experimental +int rte_pmd_dpaa_ol_set_classif_info(struct rte_pmd_dpaa_uplink_cls_info_s *cls_info); + +__rte_experimental +int rte_pmd_dpaa_ol_reset_classif_info(void); + +__rte_experimental +int rte_pmd_dpaa_ol_set_lgw_info(struct rte_pmd_dpaa_lgw_info_s *lgw_info); + +__rte_experimental +int rte_pmd_dpaa_ol_reset_lgw_info(void); + +#endif -- 2.25.1

