From: Sachin Saxena Date: Fri, 4 Sep 2020 08:39:25 +0000 (+0530) Subject: net/dpaa: support FMCless mode X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=4defbc8cbb6d5b520f13ee7f2396b0a31516d370;p=dpdk.git net/dpaa: support FMCless mode This patch uses fmlib to configure the FMAN HW for flow and distribution configuration, thus avoiding the need for static FMC tool execution optionally. Signed-off-by: Sachin Saxena Signed-off-by: Hemant Agrawal --- diff --git a/drivers/bus/dpaa/include/fsl_qman.h b/drivers/bus/dpaa/include/fsl_qman.h index 8ba37411af..dd7ca783a2 100644 --- a/drivers/bus/dpaa/include/fsl_qman.h +++ b/drivers/bus/dpaa/include/fsl_qman.h @@ -1896,6 +1896,7 @@ int qman_enqueue_orp(struct qman_fq *fq, const struct qm_fd *fd, u32 flags, * FQs than requested (though alignment will be as requested). If @partial is * zero, the return value will either be 'count' or negative. */ +__rte_internal int qman_alloc_fqid_range(u32 *result, u32 count, u32 align, int partial); static inline int qman_alloc_fqid(u32 *result) { diff --git a/drivers/bus/dpaa/rte_bus_dpaa_version.map b/drivers/bus/dpaa/rte_bus_dpaa_version.map index 77840a5645..f47922c6a0 100644 --- a/drivers/bus/dpaa/rte_bus_dpaa_version.map +++ b/drivers/bus/dpaa/rte_bus_dpaa_version.map @@ -49,6 +49,7 @@ INTERNAL { netcfg_release; per_lcore_dpaa_io; qman_alloc_cgrid_range; + qman_alloc_fqid_range; qman_alloc_pool_range; qman_clear_irq; qman_create_cgr; diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c index c15e2b5462..c5b9ac1a5b 100644 --- a/drivers/net/dpaa/dpaa_ethdev.c +++ b/drivers/net/dpaa/dpaa_ethdev.c @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -76,6 +77,7 @@ static uint64_t dev_tx_offloads_nodis = /* Keep track of whether QMAN and BMAN have been globally initialized */ static int is_global_init; +static int fmc_q = 1; /* Indicates the use of static fmc for distribution */ static int default_q; /* use default queue - FMC is not executed*/ /* At present we only allow up to 4 push mode queues as default - as each of * this queue need dedicated portal and we are short of portals. @@ -1418,16 +1420,15 @@ static int dpaa_rx_queue_init(struct qman_fq *fq, struct qman_cgr *cgr_rx, } }; - if (fqid) { + if (fmc_q || default_q) { ret = qman_reserve_fqid(fqid); if (ret) { - DPAA_PMD_ERR("reserve rx fqid 0x%x failed with ret: %d", + DPAA_PMD_ERR("reserve rx fqid 0x%x failed, ret: %d", fqid, ret); return -EINVAL; } - } else { - flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; } + DPAA_PMD_DEBUG("creating rx fq %p, fqid 0x%x", fq, fqid); ret = qman_create_fq(fqid, flags, fq); if (ret) { @@ -1602,7 +1603,7 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev) struct fman_if_bpool *bp, *tmp_bp; uint32_t cgrid[DPAA_MAX_NUM_PCD_QUEUES]; uint32_t cgrid_tx[MAX_DPAA_CORES]; - char eth_buf[RTE_ETHER_ADDR_FMT_SIZE]; + uint32_t dev_rx_fqids[DPAA_MAX_NUM_PCD_QUEUES]; PMD_INIT_FUNC_TRACE(); @@ -1619,30 +1620,36 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev) dpaa_intf->ifid = dev_id; dpaa_intf->cfg = cfg; + memset((char *)dev_rx_fqids, 0, + sizeof(uint32_t) * DPAA_MAX_NUM_PCD_QUEUES); + /* Initialize Rx FQ's */ if (default_q) { num_rx_fqs = DPAA_DEFAULT_NUM_PCD_QUEUES; + } else if (fmc_q) { + num_rx_fqs = 1; } else { - if (getenv("DPAA_NUM_RX_QUEUES")) - num_rx_fqs = atoi(getenv("DPAA_NUM_RX_QUEUES")); - else - num_rx_fqs = DPAA_DEFAULT_NUM_PCD_QUEUES; + /* FMCLESS mode, load balance to multiple cores.*/ + num_rx_fqs = rte_lcore_count(); } - /* Each device can not have more than DPAA_MAX_NUM_PCD_QUEUES RX * queues. */ - if (num_rx_fqs <= 0 || num_rx_fqs > DPAA_MAX_NUM_PCD_QUEUES) { + if (num_rx_fqs < 0 || num_rx_fqs > DPAA_MAX_NUM_PCD_QUEUES) { DPAA_PMD_ERR("Invalid number of RX queues\n"); return -EINVAL; } - dpaa_intf->rx_queues = rte_zmalloc(NULL, - sizeof(struct qman_fq) * num_rx_fqs, MAX_CACHELINE); - if (!dpaa_intf->rx_queues) { - DPAA_PMD_ERR("Failed to alloc mem for RX queues\n"); - return -ENOMEM; + if (num_rx_fqs > 0) { + dpaa_intf->rx_queues = rte_zmalloc(NULL, + sizeof(struct qman_fq) * num_rx_fqs, MAX_CACHELINE); + if (!dpaa_intf->rx_queues) { + DPAA_PMD_ERR("Failed to alloc mem for RX queues\n"); + return -ENOMEM; + } + } else { + dpaa_intf->rx_queues = NULL; } memset(cgrid, 0, sizeof(cgrid)); @@ -1661,7 +1668,7 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev) } /* If congestion control is enabled globally*/ - if (td_threshold) { + if (num_rx_fqs > 0 && td_threshold) { dpaa_intf->cgr_rx = rte_zmalloc(NULL, sizeof(struct qman_cgr) * num_rx_fqs, MAX_CACHELINE); if (!dpaa_intf->cgr_rx) { @@ -1680,12 +1687,20 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev) dpaa_intf->cgr_rx = NULL; } + if (!fmc_q && !default_q) { + ret = qman_alloc_fqid_range(dev_rx_fqids, num_rx_fqs, + num_rx_fqs, 0); + if (ret < 0) { + DPAA_PMD_ERR("Failed to alloc rx fqid's\n"); + goto free_rx; + } + } + for (loop = 0; loop < num_rx_fqs; loop++) { if (default_q) fqid = cfg->rx_def; else - fqid = DPAA_PCD_FQID_START + fman_intf->mac_idx * - DPAA_PCD_FQID_MULTIPLIER + loop; + fqid = dev_rx_fqids[loop]; if (dpaa_intf->cgr_rx) dpaa_intf->cgr_rx[loop].cgrid = cgrid[loop]; @@ -1782,9 +1797,16 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev) /* copy the primary mac address */ rte_ether_addr_copy(&fman_intf->mac_addr, ð_dev->data->mac_addrs[0]); - rte_ether_format_addr(eth_buf, sizeof(eth_buf), &fman_intf->mac_addr); - DPAA_PMD_INFO("net: dpaa: %s: %s", dpaa_device->name, eth_buf); + RTE_LOG(INFO, PMD, "net: dpaa: %s: %02x:%02x:%02x:%02x:%02x:%02x\n", + dpaa_device->name, + fman_intf->mac_addr.addr_bytes[0], + fman_intf->mac_addr.addr_bytes[1], + fman_intf->mac_addr.addr_bytes[2], + fman_intf->mac_addr.addr_bytes[3], + fman_intf->mac_addr.addr_bytes[4], + fman_intf->mac_addr.addr_bytes[5]); + /* Disable RX mode */ fman_if_discard_rx_errors(fman_intf); @@ -1831,6 +1853,12 @@ dpaa_dev_uninit(struct rte_eth_dev *dev) return -1; } + /* DPAA FM deconfig */ + if (!(default_q || fmc_q)) { + if (dpaa_fm_deconfig(dpaa_intf, dev->process_private)) + DPAA_PMD_WARN("DPAA FM deconfig failed\n"); + } + dpaa_eth_dev_close(dev); /* release configuration memory */ @@ -1874,7 +1902,7 @@ dpaa_dev_uninit(struct rte_eth_dev *dev) } static int -rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused, +rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv, struct rte_dpaa_device *dpaa_dev) { int diag; @@ -1920,6 +1948,13 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused, default_q = 1; } + if (!(default_q || fmc_q)) { + if (dpaa_fm_init()) { + DPAA_PMD_ERR("FM init failed\n"); + return -1; + } + } + /* disabling the default push mode for LS1043 */ if (dpaa_svr_family == SVR_LS1043A_FAMILY) dpaa_push_mode_max_queue = 0; @@ -1993,6 +2028,38 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev) return 0; } +static void __attribute__((destructor(102))) dpaa_finish(void) +{ + /* For secondary, primary will do all the cleanup */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + if (!(default_q || fmc_q)) { + unsigned int i; + + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if (rte_eth_devices[i].dev_ops == &dpaa_devops) { + struct rte_eth_dev *dev = &rte_eth_devices[i]; + struct dpaa_if *dpaa_intf = + dev->data->dev_private; + struct fman_if *fif = + dev->process_private; + if (dpaa_intf->port_handle) + if (dpaa_fm_deconfig(dpaa_intf, fif)) + DPAA_PMD_WARN("DPAA FM " + "deconfig failed\n"); + } + } + if (is_global_init) + if (dpaa_fm_term()) + DPAA_PMD_WARN("DPAA FM term failed\n"); + + is_global_init = 0; + + DPAA_PMD_INFO("DPAA fman cleaned up"); + } +} + static struct rte_dpaa_driver rte_dpaa_pmd = { .drv_flags = RTE_DPAA_DRV_INTR_LSC, .drv_type = FSL_DPAA_ETH, diff --git a/drivers/net/dpaa/dpaa_ethdev.h b/drivers/net/dpaa/dpaa_ethdev.h index 4c40ff86a8..b10c4a20ba 100644 --- a/drivers/net/dpaa/dpaa_ethdev.h +++ b/drivers/net/dpaa/dpaa_ethdev.h @@ -118,6 +118,10 @@ struct dpaa_if { uint32_t ifid; struct dpaa_bp_info *bp_info; struct rte_eth_fc_conf *fc_conf; + void *port_handle; + void *netenv_handle; + void *scheme_handle[2]; + uint32_t scheme_count; }; struct dpaa_if_stats { diff --git a/drivers/net/dpaa/dpaa_flow.c b/drivers/net/dpaa/dpaa_flow.c new file mode 100644 index 0000000000..a12141efe4 --- /dev/null +++ b/drivers/net/dpaa/dpaa_flow.c @@ -0,0 +1,901 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2017-2019 NXP + */ + +/* System headers */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DPAA_MAX_NUM_ETH_DEV 8 + +static inline +ioc_fm_pcd_extract_entry_t * +SCH_EXT_ARR(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ +return &scheme_params->param.key_ext_and_hash.extract_array[hdr_idx]; +} + +#define SCH_EXT_HDR(scheme_params, hdr_idx) \ + SCH_EXT_ARR(scheme_params, hdr_idx)->extract_params.extract_by_hdr + +#define SCH_EXT_FULL_FLD(scheme_params, hdr_idx) \ + SCH_EXT_HDR(scheme_params, hdr_idx).extract_by_hdr_type.full_field + +/* FM global info */ +struct dpaa_fm_info { + t_handle fman_handle; + t_handle pcd_handle; +}; + +/*FM model to read and write from file */ +struct dpaa_fm_model { + uint32_t dev_count; + uint8_t device_order[DPAA_MAX_NUM_ETH_DEV]; + t_fm_port_params fm_port_params[DPAA_MAX_NUM_ETH_DEV]; + t_handle netenv_devid[DPAA_MAX_NUM_ETH_DEV]; + t_handle scheme_devid[DPAA_MAX_NUM_ETH_DEV][2]; +}; + +static struct dpaa_fm_info fm_info; +static struct dpaa_fm_model fm_model; +static const char *fm_log = "/tmp/fmdpdk.bin"; + +static void fm_prev_cleanup(void) +{ + uint32_t fman_id = 0, i = 0, devid; + struct dpaa_if dpaa_intf = {0}; + t_fm_pcd_params fm_pcd_params = {0}; + PMD_INIT_FUNC_TRACE(); + + fm_info.fman_handle = fm_open(fman_id); + if (!fm_info.fman_handle) { + printf("\n%s- unable to open FMAN", __func__); + return; + } + + fm_pcd_params.h_fm = fm_info.fman_handle; + fm_pcd_params.prs_support = true; + fm_pcd_params.kg_support = true; + /* FM PCD Open */ + fm_info.pcd_handle = fm_pcd_open(&fm_pcd_params); + if (!fm_info.pcd_handle) { + printf("\n%s- unable to open PCD", __func__); + return; + } + + while (i < fm_model.dev_count) { + devid = fm_model.device_order[i]; + /* FM Port Open */ + fm_model.fm_port_params[devid].h_fm = fm_info.fman_handle; + dpaa_intf.port_handle = + fm_port_open(&fm_model.fm_port_params[devid]); + dpaa_intf.scheme_handle[0] = create_device(fm_info.pcd_handle, + fm_model.scheme_devid[devid][0]); + dpaa_intf.scheme_count = 1; + if (fm_model.scheme_devid[devid][1]) { + dpaa_intf.scheme_handle[1] = + create_device(fm_info.pcd_handle, + fm_model.scheme_devid[devid][1]); + if (dpaa_intf.scheme_handle[1]) + dpaa_intf.scheme_count++; + } + + dpaa_intf.netenv_handle = create_device(fm_info.pcd_handle, + fm_model.netenv_devid[devid]); + i++; + if (!dpaa_intf.netenv_handle || + !dpaa_intf.scheme_handle[0] || + !dpaa_intf.port_handle) + continue; + + if (dpaa_fm_deconfig(&dpaa_intf, NULL)) + printf("\nDPAA FM deconfig failed\n"); + } + + if (dpaa_fm_term()) + printf("\nDPAA FM term failed\n"); + + memset(&fm_model, 0, sizeof(struct dpaa_fm_model)); +} + +void dpaa_write_fm_config_to_file(void) +{ + size_t bytes_write; + FILE *fp = fopen(fm_log, "wb"); + PMD_INIT_FUNC_TRACE(); + + if (!fp) { + DPAA_PMD_ERR("File open failed"); + return; + } + bytes_write = fwrite(&fm_model, sizeof(struct dpaa_fm_model), 1, fp); + if (!bytes_write) { + DPAA_PMD_WARN("No bytes write"); + fclose(fp); + return; + } + fclose(fp); +} + +static void dpaa_read_fm_config_from_file(void) +{ + size_t bytes_read; + FILE *fp = fopen(fm_log, "rb"); + PMD_INIT_FUNC_TRACE(); + + if (!fp) + return; + DPAA_PMD_INFO("Previous DPDK-FM config instance present, cleaning up."); + + bytes_read = fread(&fm_model, sizeof(struct dpaa_fm_model), 1, fp); + if (!bytes_read) { + DPAA_PMD_WARN("No bytes read"); + fclose(fp); + return; + } + fclose(fp); + + /*FM cleanup from previous configured app */ + fm_prev_cleanup(); +} + +static inline int +set_hash_params_eth(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ + int k; + + for (k = 0; k < 2; k++) { + SCH_EXT_ARR(scheme_params, hdr_idx)->type = + e_IOC_FM_PCD_EXTRACT_BY_HDR; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr = + HEADER_TYPE_ETH; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index = + e_IOC_FM_PCD_HDR_INDEX_NONE; + SCH_EXT_HDR(scheme_params, hdr_idx).type = + e_IOC_FM_PCD_EXTRACT_FULL_FIELD; + if (k == 0) + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).eth = + IOC_NET_HF_ETH_SA; + else + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).eth = + IOC_NET_HF_ETH_DA; + hdr_idx++; + } + return hdr_idx; +} + +static inline int +set_hash_params_ipv4(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ + int k; + + for (k = 0; k < 2; k++) { + SCH_EXT_ARR(scheme_params, hdr_idx)->type = + e_IOC_FM_PCD_EXTRACT_BY_HDR; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr = + HEADER_TYPE_IPV4; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index = + e_IOC_FM_PCD_HDR_INDEX_NONE; + SCH_EXT_HDR(scheme_params, hdr_idx).type = + e_IOC_FM_PCD_EXTRACT_FULL_FIELD; + if (k == 0) + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv4 = + ioc_net_hf_ipv_4_src_ip; + else + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv4 = + ioc_net_hf_ipv_4_dst_ip; + hdr_idx++; + } + return hdr_idx; +} + +static inline int +set_hash_params_ipv6(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ + int k; + + for (k = 0; k < 2; k++) { + SCH_EXT_ARR(scheme_params, hdr_idx)->type = + e_IOC_FM_PCD_EXTRACT_BY_HDR; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr = + HEADER_TYPE_IPV6; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index = + e_IOC_FM_PCD_HDR_INDEX_NONE; + SCH_EXT_HDR(scheme_params, hdr_idx).type = + e_IOC_FM_PCD_EXTRACT_FULL_FIELD; + if (k == 0) + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv6 = + ioc_net_hf_ipv_6_src_ip; + else + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv6 = + ioc_net_hf_ipv_6_dst_ip; + hdr_idx++; + } + return hdr_idx; +} + +static inline int +set_hash_params_udp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ + int k; + + for (k = 0; k < 2; k++) { + SCH_EXT_ARR(scheme_params, hdr_idx)->type = + e_IOC_FM_PCD_EXTRACT_BY_HDR; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr = + HEADER_TYPE_UDP; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index = + e_IOC_FM_PCD_HDR_INDEX_NONE; + SCH_EXT_HDR(scheme_params, hdr_idx).type = + e_IOC_FM_PCD_EXTRACT_FULL_FIELD; + if (k == 0) + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).udp = + IOC_NET_HF_UDP_PORT_SRC; + else + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).udp = + IOC_NET_HF_UDP_PORT_DST; + hdr_idx++; + } + return hdr_idx; +} + +static inline int +set_hash_params_tcp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ + int k; + + for (k = 0; k < 2; k++) { + SCH_EXT_ARR(scheme_params, hdr_idx)->type = + e_IOC_FM_PCD_EXTRACT_BY_HDR; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr = + HEADER_TYPE_TCP; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index = + e_IOC_FM_PCD_HDR_INDEX_NONE; + SCH_EXT_HDR(scheme_params, hdr_idx).type = + e_IOC_FM_PCD_EXTRACT_FULL_FIELD; + if (k == 0) + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).tcp = + IOC_NET_HF_TCP_PORT_SRC; + else + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).tcp = + IOC_NET_HF_TCP_PORT_DST; + hdr_idx++; + } + return hdr_idx; +} + +static inline int +set_hash_params_sctp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx) +{ + int k; + + for (k = 0; k < 2; k++) { + SCH_EXT_ARR(scheme_params, hdr_idx)->type = + e_IOC_FM_PCD_EXTRACT_BY_HDR; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr = + HEADER_TYPE_SCTP; + SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index = + e_IOC_FM_PCD_HDR_INDEX_NONE; + SCH_EXT_HDR(scheme_params, hdr_idx).type = + e_IOC_FM_PCD_EXTRACT_FULL_FIELD; + if (k == 0) + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).sctp = + IOC_NET_HF_SCTP_PORT_SRC; + else + SCH_EXT_FULL_FLD(scheme_params, hdr_idx).sctp = + IOC_NET_HF_SCTP_PORT_DST; + hdr_idx++; + } + return hdr_idx; +} + +/* Set scheme params for hash distribution */ +static int set_scheme_params(ioc_fm_pcd_kg_scheme_params_t *scheme_params, + ioc_fm_pcd_net_env_params_t *dist_units, + struct dpaa_if *dpaa_intf, + struct fman_if *fif __rte_unused) +{ + int dist_idx, hdr_idx = 0; + PMD_INIT_FUNC_TRACE(); + + scheme_params->param.use_hash = 1; + scheme_params->param.modify = false; + scheme_params->param.always_direct = false; + scheme_params->param.scheme_counter.update = 1; + scheme_params->param.scheme_counter.value = 0; + scheme_params->param.next_engine = e_IOC_FM_PCD_DONE; + scheme_params->param.base_fqid = dpaa_intf->rx_queues[0].fqid; + scheme_params->param.net_env_params.net_env_id = + dpaa_intf->netenv_handle; + scheme_params->param.net_env_params.num_of_distinction_units = + dist_units->param.num_of_distinction_units; + + scheme_params->param.key_ext_and_hash.hash_dist_num_of_fqids = + dpaa_intf->nb_rx_queues; + scheme_params->param.key_ext_and_hash.num_of_used_extracts = + 2 * dist_units->param.num_of_distinction_units; + + for (dist_idx = 0; dist_idx < + dist_units->param.num_of_distinction_units; + dist_idx++) { + switch (dist_units->param.units[dist_idx].hdrs[0].hdr) { + case HEADER_TYPE_ETH: + hdr_idx = set_hash_params_eth(scheme_params, hdr_idx); + break; + + case HEADER_TYPE_IPV4: + hdr_idx = set_hash_params_ipv4(scheme_params, hdr_idx); + break; + + case HEADER_TYPE_IPV6: + hdr_idx = set_hash_params_ipv6(scheme_params, hdr_idx); + break; + + case HEADER_TYPE_UDP: + hdr_idx = set_hash_params_udp(scheme_params, hdr_idx); + break; + + case HEADER_TYPE_TCP: + hdr_idx = set_hash_params_tcp(scheme_params, hdr_idx); + break; + + case HEADER_TYPE_SCTP: + hdr_idx = set_hash_params_sctp(scheme_params, hdr_idx); + break; + + default: + DPAA_PMD_ERR("Invalid Distinction Unit"); + return -1; + } + } + + return 0; +} + +static void set_dist_units(ioc_fm_pcd_net_env_params_t *dist_units, + uint64_t req_dist_set) +{ + uint32_t loop = 0, dist_idx = 0, dist_field = 0; + int l2_configured = 0, ipv4_configured = 0, ipv6_configured = 0; + int udp_configured = 0, tcp_configured = 0, sctp_configured = 0; + PMD_INIT_FUNC_TRACE(); + + if (!req_dist_set) + dist_units->param.units[dist_idx++].hdrs[0].hdr = + HEADER_TYPE_ETH; + + while (req_dist_set) { + if (req_dist_set % 2 != 0) { + dist_field = 1U << loop; + switch (dist_field) { + case ETH_RSS_L2_PAYLOAD: + + if (l2_configured) + break; + l2_configured = 1; + + dist_units->param.units[dist_idx++].hdrs[0].hdr + = HEADER_TYPE_ETH; + break; + + case ETH_RSS_IPV4: + case ETH_RSS_FRAG_IPV4: + case ETH_RSS_NONFRAG_IPV4_OTHER: + + if (ipv4_configured) + break; + ipv4_configured = 1; + dist_units->param.units[dist_idx++].hdrs[0].hdr + = HEADER_TYPE_IPV4; + break; + + case ETH_RSS_IPV6: + case ETH_RSS_FRAG_IPV6: + case ETH_RSS_NONFRAG_IPV6_OTHER: + case ETH_RSS_IPV6_EX: + + if (ipv6_configured) + break; + ipv6_configured = 1; + dist_units->param.units[dist_idx++].hdrs[0].hdr + = HEADER_TYPE_IPV6; + break; + + case ETH_RSS_NONFRAG_IPV4_TCP: + case ETH_RSS_NONFRAG_IPV6_TCP: + case ETH_RSS_IPV6_TCP_EX: + + if (tcp_configured) + break; + tcp_configured = 1; + dist_units->param.units[dist_idx++].hdrs[0].hdr + = HEADER_TYPE_TCP; + break; + + case ETH_RSS_NONFRAG_IPV4_UDP: + case ETH_RSS_NONFRAG_IPV6_UDP: + case ETH_RSS_IPV6_UDP_EX: + + if (udp_configured) + break; + udp_configured = 1; + dist_units->param.units[dist_idx++].hdrs[0].hdr + = HEADER_TYPE_UDP; + break; + + case ETH_RSS_NONFRAG_IPV4_SCTP: + case ETH_RSS_NONFRAG_IPV6_SCTP: + + if (sctp_configured) + break; + sctp_configured = 1; + + dist_units->param.units[dist_idx++].hdrs[0].hdr + = HEADER_TYPE_SCTP; + break; + + default: + DPAA_PMD_ERR("Bad flow distribution option"); + } + } + req_dist_set = req_dist_set >> 1; + loop++; + } + + /* Dist units is set to dist_idx */ + dist_units->param.num_of_distinction_units = dist_idx; +} + +/* Apply PCD configuration on interface */ +static inline int set_port_pcd(struct dpaa_if *dpaa_intf) +{ + int ret = 0; + unsigned int idx; + ioc_fm_port_pcd_params_t pcd_param; + ioc_fm_port_pcd_prs_params_t prs_param; + ioc_fm_port_pcd_kg_params_t kg_param; + + PMD_INIT_FUNC_TRACE(); + + /* PCD support for hash distribution */ + uint8_t pcd_support = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG; + + memset(&pcd_param, 0, sizeof(pcd_param)); + memset(&prs_param, 0, sizeof(prs_param)); + memset(&kg_param, 0, sizeof(kg_param)); + + /* Set parse params */ + prs_param.first_prs_hdr = HEADER_TYPE_ETH; + + /* Set kg params */ + for (idx = 0; idx < dpaa_intf->scheme_count; idx++) + kg_param.scheme_ids[idx] = dpaa_intf->scheme_handle[idx]; + kg_param.num_schemes = dpaa_intf->scheme_count; + + /* Set pcd params */ + pcd_param.net_env_id = dpaa_intf->netenv_handle; + pcd_param.pcd_support = pcd_support; + pcd_param.p_kg_params = &kg_param; + pcd_param.p_prs_params = &prs_param; + + /* FM PORT Disable */ + ret = fm_port_disable(dpaa_intf->port_handle); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_port_disable: Failed"); + return ret; + } + + /* FM PORT SetPCD */ + ret = fm_port_set_pcd(dpaa_intf->port_handle, &pcd_param); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_port_set_pcd: Failed"); + return ret; + } + + /* FM PORT Enable */ + ret = fm_port_enable(dpaa_intf->port_handle); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_port_enable: Failed"); + goto fm_port_delete_pcd; + } + + return 0; + +fm_port_delete_pcd: + /* FM PORT DeletePCD */ + ret = fm_port_delete_pcd(dpaa_intf->port_handle); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_port_delete_pcd: Failed\n"); + return ret; + } + return -1; +} + +/* Unset PCD NerEnv and scheme */ +static inline void unset_pcd_netenv_scheme(struct dpaa_if *dpaa_intf) +{ + int ret; + PMD_INIT_FUNC_TRACE(); + + /* reduce scheme count */ + if (dpaa_intf->scheme_count) + dpaa_intf->scheme_count--; + + DPAA_PMD_DEBUG("KG SCHEME DEL %d handle =%p", + dpaa_intf->scheme_count, + dpaa_intf->scheme_handle[dpaa_intf->scheme_count]); + + ret = fm_pcd_kg_scheme_delete(dpaa_intf->scheme_handle + [dpaa_intf->scheme_count]); + if (ret != E_OK) + DPAA_PMD_ERR("fm_pcd_kg_scheme_delete: Failed"); + + dpaa_intf->scheme_handle[dpaa_intf->scheme_count] = NULL; +} + +/* Set PCD NetEnv and Scheme and default scheme */ +static inline int set_default_scheme(struct dpaa_if *dpaa_intf) +{ + ioc_fm_pcd_kg_scheme_params_t scheme_params; + int idx = dpaa_intf->scheme_count; + PMD_INIT_FUNC_TRACE(); + + /* Set PCD NetEnvCharacteristics */ + memset(&scheme_params, 0, sizeof(scheme_params)); + + /* Adding 10 to default schemes as the number of interface would be + * lesser than 10 and the relative scheme ids should be unique for + * every scheme. + */ + scheme_params.param.scm_id.relative_scheme_id = + 10 + dpaa_intf->ifid; + scheme_params.param.use_hash = 0; + scheme_params.param.next_engine = e_IOC_FM_PCD_DONE; + scheme_params.param.net_env_params.num_of_distinction_units = 0; + scheme_params.param.net_env_params.net_env_id = + dpaa_intf->netenv_handle; + scheme_params.param.base_fqid = dpaa_intf->rx_queues[0].fqid; + scheme_params.param.key_ext_and_hash.hash_dist_num_of_fqids = 1; + scheme_params.param.key_ext_and_hash.num_of_used_extracts = 0; + scheme_params.param.modify = false; + scheme_params.param.always_direct = false; + scheme_params.param.scheme_counter.update = 1; + scheme_params.param.scheme_counter.value = 0; + + /* FM PCD KgSchemeSet */ + dpaa_intf->scheme_handle[idx] = + fm_pcd_kg_scheme_set(fm_info.pcd_handle, &scheme_params); + DPAA_PMD_DEBUG("KG SCHEME SET %d handle =%p", + idx, dpaa_intf->scheme_handle[idx]); + if (!dpaa_intf->scheme_handle[idx]) { + DPAA_PMD_ERR("fm_pcd_kg_scheme_set: Failed"); + return -1; + } + + fm_model.scheme_devid[dpaa_intf->ifid][idx] = + get_device_id(dpaa_intf->scheme_handle[idx]); + dpaa_intf->scheme_count++; + return 0; +} + + +/* Set PCD NetEnv and Scheme and default scheme */ +static inline int set_pcd_netenv_scheme(struct dpaa_if *dpaa_intf, + uint64_t req_dist_set, + struct fman_if *fif) +{ + int ret = -1; + ioc_fm_pcd_net_env_params_t dist_units; + ioc_fm_pcd_kg_scheme_params_t scheme_params; + int idx = dpaa_intf->scheme_count; + PMD_INIT_FUNC_TRACE(); + + /* Set PCD NetEnvCharacteristics */ + memset(&dist_units, 0, sizeof(dist_units)); + memset(&scheme_params, 0, sizeof(scheme_params)); + + /* Set dist unit header type */ + set_dist_units(&dist_units, req_dist_set); + + scheme_params.param.scm_id.relative_scheme_id = dpaa_intf->ifid; + + /* Set PCD Scheme params */ + ret = set_scheme_params(&scheme_params, &dist_units, dpaa_intf, fif); + if (ret) { + DPAA_PMD_ERR("Set scheme params: Failed"); + return -1; + } + + /* FM PCD KgSchemeSet */ + dpaa_intf->scheme_handle[idx] = + fm_pcd_kg_scheme_set(fm_info.pcd_handle, &scheme_params); + DPAA_PMD_DEBUG("KG SCHEME SET %d handle =%p", + idx, dpaa_intf->scheme_handle[idx]); + if (!dpaa_intf->scheme_handle[idx]) { + DPAA_PMD_ERR("fm_pcd_kg_scheme_set: Failed"); + return -1; + } + + fm_model.scheme_devid[dpaa_intf->ifid][idx] = + get_device_id(dpaa_intf->scheme_handle[idx]); + dpaa_intf->scheme_count++; + return 0; +} + + +static inline int get_port_type(struct fman_if *fif) +{ + if (fif->mac_type == fman_mac_1g) + return e_FM_PORT_TYPE_RX; + else if (fif->mac_type == fman_mac_2_5g) + return e_FM_PORT_TYPE_RX_2_5G; + else if (fif->mac_type == fman_mac_10g) + return e_FM_PORT_TYPE_RX_10G; + + DPAA_PMD_ERR("MAC type unsupported"); + return -1; +} + +static inline int set_fm_port_handle(struct dpaa_if *dpaa_intf, + uint64_t req_dist_set, + struct fman_if *fif) +{ + t_fm_port_params fm_port_params; + ioc_fm_pcd_net_env_params_t dist_units; + PMD_INIT_FUNC_TRACE(); + + /* FMAN mac indexes mappings (0 is unused, + * first 8 are for 1G, next for 10G ports + */ + uint8_t mac_idx[] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1}; + + /* Memset FM port params */ + memset(&fm_port_params, 0, sizeof(fm_port_params)); + + /* Set FM port params */ + fm_port_params.h_fm = fm_info.fman_handle; + fm_port_params.port_type = get_port_type(fif); + fm_port_params.port_id = mac_idx[fif->mac_idx]; + + /* FM PORT Open */ + dpaa_intf->port_handle = fm_port_open(&fm_port_params); + if (!dpaa_intf->port_handle) { + DPAA_PMD_ERR("fm_port_open: Failed\n"); + return -1; + } + + fm_model.fm_port_params[dpaa_intf->ifid] = fm_port_params; + + /* Set PCD NetEnvCharacteristics */ + memset(&dist_units, 0, sizeof(dist_units)); + + /* Set dist unit header type */ + set_dist_units(&dist_units, req_dist_set); + + /* FM PCD NetEnvCharacteristicsSet */ + dpaa_intf->netenv_handle = + fm_pcd_net_env_characteristics_set(fm_info.pcd_handle, + &dist_units); + if (!dpaa_intf->netenv_handle) { + DPAA_PMD_ERR("fm_pcd_net_env_characteristics_set: Failed"); + return -1; + } + + fm_model.netenv_devid[dpaa_intf->ifid] = + get_device_id(dpaa_intf->netenv_handle); + + return 0; +} + +/* De-Configure DPAA FM */ +int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf, + struct fman_if *fif __rte_unused) +{ + int ret; + unsigned int idx; + + PMD_INIT_FUNC_TRACE(); + + /* FM PORT Disable */ + ret = fm_port_disable(dpaa_intf->port_handle); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_port_disable: Failed"); + return ret; + } + + /* FM PORT DeletePCD */ + ret = fm_port_delete_pcd(dpaa_intf->port_handle); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_port_delete_pcd: Failed"); + return ret; + } + + for (idx = 0; idx < dpaa_intf->scheme_count; idx++) { + DPAA_PMD_DEBUG("KG SCHEME DEL %d, handle =%p", + idx, dpaa_intf->scheme_handle[idx]); + /* FM PCD KgSchemeDelete */ + ret = fm_pcd_kg_scheme_delete(dpaa_intf->scheme_handle[idx]); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_pcd_kg_scheme_delete: Failed"); + return ret; + } + dpaa_intf->scheme_handle[idx] = NULL; + } + /* FM PCD NetEnvCharacteristicsDelete */ + ret = fm_pcd_net_env_characteristics_delete(dpaa_intf->netenv_handle); + if (ret != E_OK) { + DPAA_PMD_ERR("fm_pcd_net_env_characteristics_delete: Failed"); + return ret; + } + dpaa_intf->netenv_handle = NULL; + + /* FM PORT Close */ + fm_port_close(dpaa_intf->port_handle); + dpaa_intf->port_handle = NULL; + + /* Set scheme count to 0 */ + dpaa_intf->scheme_count = 0; + + return 0; +} + +int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set) +{ + struct dpaa_if *dpaa_intf = dev->data->dev_private; + struct fman_if *fif = dev->process_private; + int ret; + unsigned int i = 0; + PMD_INIT_FUNC_TRACE(); + + if (dpaa_intf->port_handle) { + if (dpaa_fm_deconfig(dpaa_intf, fif)) + DPAA_PMD_ERR("DPAA FM deconfig failed"); + } + + if (!dev->data->nb_rx_queues) + return 0; + + if (dev->data->nb_rx_queues & (dev->data->nb_rx_queues - 1)) { + DPAA_PMD_ERR("No of queues should be power of 2"); + return -1; + } + + dpaa_intf->nb_rx_queues = dev->data->nb_rx_queues; + + /* Open FM Port and set it in port info */ + ret = set_fm_port_handle(dpaa_intf, req_dist_set, fif); + if (ret) { + DPAA_PMD_ERR("Set FM Port handle: Failed"); + return -1; + } + + /* Set PCD netenv and scheme */ + if (req_dist_set) { + ret = set_pcd_netenv_scheme(dpaa_intf, req_dist_set, fif); + if (ret) { + DPAA_PMD_ERR("Set PCD NetEnv and Scheme dist: Failed"); + goto unset_fm_port_handle; + } + } + /* Set default netenv and scheme */ + ret = set_default_scheme(dpaa_intf); + if (ret) { + DPAA_PMD_ERR("Set PCD NetEnv and Scheme: Failed"); + goto unset_pcd_netenv_scheme1; + } + + /* Set Port PCD */ + ret = set_port_pcd(dpaa_intf); + if (ret) { + DPAA_PMD_ERR("Set Port PCD: Failed"); + goto unset_pcd_netenv_scheme; + } + + for (; i < fm_model.dev_count; i++) + if (fm_model.device_order[i] == dpaa_intf->ifid) + return 0; + + fm_model.device_order[fm_model.dev_count] = dpaa_intf->ifid; + fm_model.dev_count++; + + return 0; + +unset_pcd_netenv_scheme: + unset_pcd_netenv_scheme(dpaa_intf); + +unset_pcd_netenv_scheme1: + unset_pcd_netenv_scheme(dpaa_intf); + +unset_fm_port_handle: + /* FM PORT Close */ + fm_port_close(dpaa_intf->port_handle); + dpaa_intf->port_handle = NULL; + return -1; +} + +int dpaa_fm_init(void) +{ + t_handle fman_handle; + t_handle pcd_handle; + t_fm_pcd_params fm_pcd_params = {0}; + /* Hard-coded : fman id 0 since one fman is present in LS104x */ + int fman_id = 0, ret; + PMD_INIT_FUNC_TRACE(); + + dpaa_read_fm_config_from_file(); + + /* FM Open */ + fman_handle = fm_open(fman_id); + if (!fman_handle) { + DPAA_PMD_ERR("fm_open: Failed"); + return -1; + } + + /* FM PCD Open */ + fm_pcd_params.h_fm = fman_handle; + fm_pcd_params.prs_support = true; + fm_pcd_params.kg_support = true; + pcd_handle = fm_pcd_open(&fm_pcd_params); + if (!pcd_handle) { + fm_close(fman_handle); + DPAA_PMD_ERR("fm_pcd_open: Failed"); + return -1; + } + + /* FM PCD Enable */ + ret = fm_pcd_enable(pcd_handle); + if (ret) { + fm_close(fman_handle); + fm_pcd_close(pcd_handle); + DPAA_PMD_ERR("fm_pcd_enable: Failed"); + return -1; + } + + /* Set fman and pcd handle in fm info */ + fm_info.fman_handle = fman_handle; + fm_info.pcd_handle = pcd_handle; + + return 0; +} + + +/* De-initialization of FM */ +int dpaa_fm_term(void) +{ + int ret; + + PMD_INIT_FUNC_TRACE(); + + if (fm_info.pcd_handle && fm_info.fman_handle) { + /* FM PCD Disable */ + ret = fm_pcd_disable(fm_info.pcd_handle); + if (ret) { + DPAA_PMD_ERR("fm_pcd_disable: Failed"); + return -1; + } + + /* FM PCD Close */ + fm_pcd_close(fm_info.pcd_handle); + fm_info.pcd_handle = NULL; + } + + if (fm_info.fman_handle) { + /* FM Close */ + fm_close(fm_info.fman_handle); + fm_info.fman_handle = NULL; + } + + if (access(fm_log, F_OK) != -1) { + ret = remove(fm_log); + if (ret) + DPAA_PMD_ERR("File remove: Failed"); + } + return 0; +} diff --git a/drivers/net/dpaa/dpaa_flow.h b/drivers/net/dpaa/dpaa_flow.h new file mode 100644 index 0000000000..d16bfec210 --- /dev/null +++ b/drivers/net/dpaa/dpaa_flow.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2017,2019 NXP + */ + +#ifndef __DPAA_FLOW_H__ +#define __DPAA_FLOW_H__ + +int dpaa_fm_init(void); +int dpaa_fm_term(void); +int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set); +int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf, struct fman_if *fif); +void dpaa_write_fm_config_to_file(void); + +#endif diff --git a/drivers/net/dpaa/meson.build b/drivers/net/dpaa/meson.build index aca1dccc3b..51f1f32a13 100644 --- a/drivers/net/dpaa/meson.build +++ b/drivers/net/dpaa/meson.build @@ -10,6 +10,7 @@ deps += ['mempool_dpaa'] sources = files('dpaa_ethdev.c', 'fmlib/fm_lib.c', 'fmlib/fm_vsp.c', + 'dpaa_flow.c', 'dpaa_rxtx.c') if cc.has_argument('-Wno-pointer-arith')