From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 042E545B68; Fri, 18 Oct 2024 09:27:34 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0245C40666; Fri, 18 Oct 2024 09:26:58 +0200 (CEST) Received: from inva020.nxp.com (inva020.nxp.com [92.121.34.13]) by mails.dpdk.org (Postfix) with ESMTP id 917014025F for ; Fri, 18 Oct 2024 09:26:49 +0200 (CEST) Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 71FE11A2858; Fri, 18 Oct 2024 09:26:49 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 079421A00C3; Fri, 18 Oct 2024 09:26:49 +0200 (CEST) Received: from lsv03379.swis.in-blr01.nxp.com (lsv03379.swis.in-blr01.nxp.com [92.120.147.188]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 7B6F6183AD46; Fri, 18 Oct 2024 15:26:48 +0800 (+08) From: vanshika.shukla@nxp.com To: dev@dpdk.org, Gagandeep Singh , Sachin Saxena , Vanshika Shukla Subject: [v1 07/12] net/enetc: Add support for multiple queues with RSS Date: Fri, 18 Oct 2024 12:56:39 +0530 Message-Id: <20241018072644.2379012-8-vanshika.shukla@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20241018072644.2379012-1-vanshika.shukla@nxp.com> References: <20241018072644.2379012-1-vanshika.shukla@nxp.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Virus-Scanned: ClamAV using ClamSMTP X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Vanshika Shukla Introduces support for multiple transmit and receive queues in ENETC4 PMD, enabling scalable packet processing, improved throughput, and latency. Packet distribution is handled through Receive Side Scaling (RSS). Signed-off-by: Gagandeep Singh --- doc/guides/nics/features/enetc4.ini | 1 + drivers/net/enetc/base/enetc4_hw.h | 11 + drivers/net/enetc/base/enetc_hw.h | 21 +- drivers/net/enetc/enetc.h | 37 +++- drivers/net/enetc/enetc4_ethdev.c | 145 +++++++++++-- drivers/net/enetc/enetc4_vf.c | 10 +- drivers/net/enetc/enetc_cbdr.c | 311 ++++++++++++++++++++++++++++ drivers/net/enetc/meson.build | 5 +- drivers/net/enetc/ntmp.h | 110 ++++++++++ 9 files changed, 617 insertions(+), 34 deletions(-) create mode 100644 drivers/net/enetc/enetc_cbdr.c create mode 100644 drivers/net/enetc/ntmp.h diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini index 3356475317..79430d0018 100644 --- a/doc/guides/nics/features/enetc4.ini +++ b/doc/guides/nics/features/enetc4.ini @@ -4,6 +4,7 @@ ; Refer to default.ini for the full list of available PMD features. ; [Features] +RSS hash = Y Packet type parsing = Y Basic stats = Y L3 checksum offload = Y diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h index 874cdc4775..49446f2cb4 100644 --- a/drivers/net/enetc/base/enetc4_hw.h +++ b/drivers/net/enetc/base/enetc4_hw.h @@ -110,6 +110,17 @@ #define ENETC4_SITFRM0 0x328 #define ENETC4_SITDFCR 0x340 +/* Control BDR regs */ +#define ENETC4_SICBDRMR 0x800 +#define ENETC4_SICBDRSR 0x804 /* RO */ +#define ENETC4_SICBDRBAR0 0x810 +#define ENETC4_SICBDRBAR1 0x814 +#define ENETC4_SICBDRPIR 0x818 +#define ENETC4_SICBDRCIR 0x81c +#define ENETC4_SICBDRLENR 0x820 +#define ENETC4_SICTR0 0x18 +#define ENETC4_SICTR1 0x1c + /* general register accessors */ #define enetc4_rd_reg(reg) rte_read32((void *)(reg)) #define enetc4_wr_reg(reg, val) rte_write32((val), (void *)(reg)) diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h index 10bd3c050c..3cb56cd851 100644 --- a/drivers/net/enetc/base/enetc_hw.h +++ b/drivers/net/enetc/base/enetc_hw.h @@ -22,6 +22,10 @@ /* SI regs, offset: 0h */ #define ENETC_SIMR 0x0 #define ENETC_SIMR_EN BIT(31) +#define ENETC_SIMR_RSSE BIT(0) + +/* BDR grouping*/ +#define ENETC_SIRBGCR 0x38 #define ENETC_SICAR0 0x40 #define ENETC_SICAR0_COHERENT 0x2B2B6727 @@ -29,6 +33,7 @@ #define ENETC_SIPMAR1 0x84 #define ENETC_SICAPR0 0x900 +#define ENETC_SICAPR0_BDR_MASK 0xFF #define ENETC_SICAPR1 0x904 #define ENETC_SIMSITRV(n) (0xB00 + (n) * 0x4) @@ -36,6 +41,11 @@ #define ENETC_SICCAPR 0x1200 +#define ENETC_SIPCAPR0 0x20 +#define ENETC_SIPCAPR0_RSS BIT(8) +#define ENETC_SIRSSCAPR 0x1600 +#define ENETC_SIRSSCAPR_GET_NUM_RSS(val) (BIT((val) & 0xf) * 32) + /* enum for BD type */ enum enetc_bdr_type {TX, RX}; @@ -44,6 +54,7 @@ enum enetc_bdr_type {TX, RX}; /* RX BDR reg offsets */ #define ENETC_RBMR 0x0 /* RX BDR mode register*/ #define ENETC_RBMR_EN BIT(31) +#define ENETC_BMR_RESET 0x0 /* BDR reset*/ #define ENETC_RBSR 0x4 /* Rx BDR status register*/ #define ENETC_RBBSR 0x8 /* Rx BDR buffer size register*/ @@ -231,15 +242,6 @@ struct enetc_eth_mac_info { uint8_t get_link_status; }; -struct enetc_eth_hw { - struct rte_eth_dev *ndev; - struct enetc_hw hw; - uint16_t device_id; - uint16_t vendor_id; - uint8_t revision_id; - struct enetc_eth_mac_info mac; -}; - /* Transmit Descriptor */ struct enetc_tx_desc { uint64_t addr; @@ -292,5 +294,4 @@ union enetc_rx_bd { }; } r; }; - #endif diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h index 8d4e432426..354cd761d7 100644 --- a/drivers/net/enetc/enetc.h +++ b/drivers/net/enetc/enetc.h @@ -10,7 +10,9 @@ #include "compat.h" #include "base/enetc_hw.h" +#include "base/enetc4_hw.h" #include "enetc_logs.h" +#include "ntmp.h" #define PCI_VENDOR_ID_FREESCALE 0x1957 @@ -50,6 +52,18 @@ RTE_MBUF_F_TX_TCP_CKSUM | \ RTE_MBUF_F_TX_UDP_CKSUM) +#define ENETC_CBD(R, i) (&(((struct enetc_cbd *)((R).bd_base))[i])) +#define ENETC_CBDR_TIMEOUT 1000 /* In multiple of ENETC_CBDR_DELAY */ +#define ENETC_CBDR_DELAY 100 /* usecs */ +#define ENETC_CBDR_SIZE 64 +#define ENETC_CBDR_ALIGN 128 + +/* supported RSS */ +#define ENETC_RSS_OFFLOAD_ALL ( \ + RTE_ETH_RSS_IP | \ + RTE_ETH_RSS_UDP | \ + RTE_ETH_RSS_TCP) + struct enetc_swbd { struct rte_mbuf *buffer_addr; }; @@ -76,6 +90,19 @@ struct enetc_bdr { uint64_t ierrors; }; +struct enetc_eth_hw { + struct rte_eth_dev *ndev; + struct enetc_hw hw; + uint16_t device_id; + uint16_t vendor_id; + uint8_t revision_id; + struct enetc_eth_mac_info mac; + struct netc_cbdr cbdr; + uint32_t num_rss; + uint32_t max_rx_queues; + uint32_t max_tx_queues; +}; + /* * Structure to store private data for each driver instance (for each port). */ @@ -102,7 +129,7 @@ struct enetc_eth_adapter { int enetc4_pci_remove(struct rte_pci_device *pci_dev); int enetc4_dev_configure(struct rte_eth_dev *dev); int enetc4_dev_close(struct rte_eth_dev *dev); -int enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused, +int enetc4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); int enetc4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id __rte_unused, @@ -149,4 +176,12 @@ enetc_bd_unused(struct enetc_bdr *bdr) return bdr->bd_count + bdr->next_to_clean - bdr->next_to_use - 1; } + +/* CBDR prototypes */ +int enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw, + int bd_count, struct netc_cbdr *cbdr); +void netc_free_cbdr(struct netc_cbdr *cbdr); +int ntmp_rsst_query_or_update_entry(struct netc_cbdr *cbdr, uint32_t *table, + int count, bool query); + #endif /* _ENETC_H_ */ diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c index a57408fbe9..075205a0e5 100644 --- a/drivers/net/enetc/enetc4_ethdev.c +++ b/drivers/net/enetc/enetc4_ethdev.c @@ -7,7 +7,6 @@ #include #include "kpage_ncache_api.h" -#include "base/enetc4_hw.h" #include "enetc_logs.h" #include "enetc.h" @@ -134,10 +133,14 @@ enetc4_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev) } int -enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused, +enetc4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { + struct enetc_eth_hw *hw = + ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); + PMD_INIT_FUNC_TRACE(); + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { .nb_max = MAX_BD_COUNT, .nb_min = MIN_BD_COUNT, @@ -148,11 +151,12 @@ enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused, .nb_min = MIN_BD_COUNT, .nb_align = BD_ALIGN, }; - dev_info->max_rx_queues = MAX_RX_RINGS; - dev_info->max_tx_queues = MAX_TX_RINGS; + dev_info->max_rx_queues = hw->max_rx_queues; + dev_info->max_tx_queues = hw->max_tx_queues; dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE; dev_info->rx_offload_capa = dev_rx_offloads_sup; dev_info->tx_offload_capa = dev_tx_offloads_sup; + dev_info->flow_type_rss_offloads = ENETC_RSS_OFFLOAD_ALL; return 0; } @@ -178,6 +182,11 @@ mark_memory_ncache(struct enetc_bdr *bdr, const char *mz_name, unsigned int size mz->hugepage_sz); bdr->mz = mz; + /* Double check memzone alignment and hugepage size */ + if (!rte_is_aligned(bdr->bd_base, size)) + ENETC_PMD_WARN("Memzone is not aligned to %x", size); + + ENETC_PMD_DEBUG("Ring Hugepage start address = %p", bdr->bd_base); /* Mark memory NON-CACHEABLE */ huge_page = (uint64_t)RTE_PTR_ALIGN_FLOOR(bdr->bd_base, size); @@ -197,7 +206,7 @@ enetc4_alloc_txbdr(uint16_t port_id, struct enetc_bdr *txr, uint16_t nb_desc) if (txr->q_swbd == NULL) return -ENOMEM; - snprintf(mz_name, sizeof(mz_name), "bdt_addr_%d", port_id); + snprintf(mz_name, sizeof(mz_name), "bdt_addr_%d_%d", port_id, txr->index); if (mark_memory_ncache(txr, mz_name, SIZE_2MB)) { ENETC_PMD_ERR("Failed to mark BD memory non-cacheable!"); rte_free(txr->q_swbd); @@ -298,17 +307,20 @@ void enetc4_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) { void *txq = dev->data->tx_queues[qid]; + struct enetc_hw *hw; + struct enetc_swbd *tx_swbd; + int i; + uint32_t val; + struct enetc_bdr *tx_ring; + struct enetc_eth_hw *eth_hw; + PMD_INIT_FUNC_TRACE(); if (txq == NULL) return; - struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq; - struct enetc_eth_hw *eth_hw = + tx_ring = (struct enetc_bdr *)txq; + eth_hw = ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private); - struct enetc_hw *hw; - struct enetc_swbd *tx_swbd; - int i; - uint32_t val; /* Disable the ring */ hw = ð_hw->hw; @@ -346,7 +358,7 @@ enetc4_alloc_rxbdr(uint16_t port_id, struct enetc_bdr *rxr, if (rxr->q_swbd == NULL) return -ENOMEM; - snprintf(mz_name, sizeof(mz_name), "bdr_addr_%d", port_id); + snprintf(mz_name, sizeof(mz_name), "bdr_addr_%d_%d", port_id, rxr->index); if (mark_memory_ncache(rxr, mz_name, SIZE_2MB)) { ENETC_PMD_ERR("Failed to mark BD memory non-cacheable!"); rte_free(rxr->q_swbd); @@ -448,17 +460,20 @@ void enetc4_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) { void *rxq = dev->data->rx_queues[qid]; + struct enetc_swbd *q_swbd; + struct enetc_hw *hw; + uint32_t val; + int i; + struct enetc_bdr *rx_ring; + struct enetc_eth_hw *eth_hw; + PMD_INIT_FUNC_TRACE(); if (rxq == NULL) return; - struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq; - struct enetc_eth_hw *eth_hw = + rx_ring = (struct enetc_bdr *)rxq; + eth_hw = ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private); - struct enetc_swbd *q_swbd; - struct enetc_hw *hw; - uint32_t val; - int i; /* Disable the ring */ hw = ð_hw->hw; @@ -524,10 +539,22 @@ enetc4_stats_reset(struct rte_eth_dev *dev) return 0; } +static void +enetc4_rss_configure(struct enetc_hw *hw, int enable) +{ + uint32_t reg; + + reg = enetc4_rd(hw, ENETC_SIMR); + reg &= ~ENETC_SIMR_RSSE; + reg |= (enable) ? ENETC_SIMR_RSSE : 0; + enetc4_wr(hw, ENETC_SIMR, reg); +} + int enetc4_dev_close(struct rte_eth_dev *dev) { struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct enetc_hw *enetc_hw = &hw->hw; uint16_t i; int ret; @@ -540,6 +567,13 @@ enetc4_dev_close(struct rte_eth_dev *dev) else ret = enetc4_dev_stop(dev); + if (dev->data->nb_rx_queues > 1) { + /* Disable RSS */ + enetc4_rss_configure(enetc_hw, false); + /* Free CBDR */ + netc_free_cbdr(&hw->cbdr); + } + for (i = 0; i < dev->data->nb_rx_queues; i++) { enetc4_rx_queue_release(dev, i); dev->data->rx_queues[i] = NULL; @@ -569,7 +603,9 @@ enetc4_dev_configure(struct rte_eth_dev *dev) uint32_t checksum = L3_CKSUM | L4_CKSUM; struct enetc_hw *enetc_hw = &hw->hw; uint32_t max_len; - uint32_t val; + uint32_t val, num_rss; + uint32_t ret = 0, i; + uint32_t *rss_table; PMD_INIT_FUNC_TRACE(); @@ -602,6 +638,69 @@ enetc4_dev_configure(struct rte_eth_dev *dev) enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum); + /* Disable and reset RX and TX rings */ + for (i = 0; i < dev->data->nb_rx_queues; i++) + enetc4_rxbdr_wr(enetc_hw, i, ENETC_RBMR, ENETC_BMR_RESET); + + for (i = 0; i < dev->data->nb_tx_queues; i++) + enetc4_rxbdr_wr(enetc_hw, i, ENETC_TBMR, ENETC_BMR_RESET); + + if (dev->data->nb_rx_queues <= 1) + return 0; + + /* Setup RSS */ + /* Setup control BDR */ + ret = enetc4_setup_cbdr(dev, enetc_hw, ENETC_CBDR_SIZE, &hw->cbdr); + if (ret) { + /* Disable RSS */ + enetc4_rss_configure(enetc_hw, false); + return ret; + } + + /* Reset CIR again after enable CBDR*/ + rte_delay_us(ENETC_CBDR_DELAY); + ENETC_PMD_DEBUG("CIR %x after CBDR enable", rte_read32(hw->cbdr.regs.cir)); + rte_write32(0, hw->cbdr.regs.cir); + ENETC_PMD_DEBUG("CIR %x after reset", rte_read32(hw->cbdr.regs.cir)); + + val = enetc_rd(enetc_hw, ENETC_SIPCAPR0); + if (val & ENETC_SIPCAPR0_RSS) { + num_rss = enetc_rd(enetc_hw, ENETC_SIRSSCAPR); + hw->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(num_rss); + ENETC_PMD_DEBUG("num_rss = %d", hw->num_rss); + + /* Add number of BDR groups */ + enetc4_wr(enetc_hw, ENETC_SIRBGCR, dev->data->nb_rx_queues); + + + /* Configuring indirecton table with default values + * Hash algorithm and RSS secret key to be filled by PF + */ + rss_table = rte_malloc(NULL, hw->num_rss * sizeof(*rss_table), ENETC_CBDR_ALIGN); + if (!rss_table) { + enetc4_rss_configure(enetc_hw, false); + netc_free_cbdr(&hw->cbdr); + return -ENOMEM; + } + + ENETC_PMD_DEBUG("Enabling RSS for port %s with queues = %d", dev->device->name, + dev->data->nb_rx_queues); + for (i = 0; i < hw->num_rss; i++) + rss_table[i] = i % dev->data->nb_rx_queues; + + ret = ntmp_rsst_query_or_update_entry(&hw->cbdr, rss_table, hw->num_rss, false); + if (ret) { + ENETC_PMD_WARN("RSS indirection table update fails," + "Scaling behaviour is undefined"); + enetc4_rss_configure(enetc_hw, false); + netc_free_cbdr(&hw->cbdr); + } + rte_free(rss_table); + + /* Enable RSS */ + enetc4_rss_configure(enetc_hw, true); + } + return 0; } @@ -786,11 +885,19 @@ enetc4_dev_init(struct rte_eth_dev *eth_dev) ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); int error = 0; + uint32_t si_cap; + struct enetc_hw *enetc_hw = &hw->hw; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &enetc4_ops; enetc4_dev_hw_init(eth_dev); + si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0); + hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK; + hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK; + + ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d", + hw->max_rx_queues, hw->max_tx_queues); error = enetc4_mac_init(hw, eth_dev); if (error != 0) { ENETC_PMD_ERR("MAC initialization failed"); diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c index 360bb0c710..a9fb33c432 100644 --- a/drivers/net/enetc/enetc4_vf.c +++ b/drivers/net/enetc/enetc4_vf.c @@ -5,8 +5,6 @@ #include #include #include -#include "base/enetc4_hw.h" -#include "base/enetc_hw.h" #include "enetc_logs.h" #include "enetc.h" @@ -137,11 +135,19 @@ enetc4_vf_dev_init(struct rte_eth_dev *eth_dev) ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); int error = 0; + uint32_t si_cap; + struct enetc_hw *enetc_hw = &hw->hw; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &enetc4_vf_ops; enetc4_dev_hw_init(eth_dev); + si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0); + hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK; + hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK; + + ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d", + hw->max_rx_queues, hw->max_tx_queues); error = enetc4_vf_mac_init(hw, eth_dev); if (error != 0) { ENETC_PMD_ERR("MAC initialization failed!!"); diff --git a/drivers/net/enetc/enetc_cbdr.c b/drivers/net/enetc/enetc_cbdr.c new file mode 100644 index 0000000000..021090775f --- /dev/null +++ b/drivers/net/enetc/enetc_cbdr.c @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2024 NXP + */ + +#include + +#include "enetc_logs.h" +#include "enetc.h" + +#define NTMP_RSST_ID 3 + +/* Define NTMP Access Method */ +#define NTMP_AM_ENTRY_ID 0 +#define NTMP_AM_EXACT_KEY 1 +#define NTMP_AM_SEARCH 2 +#define NTMP_AM_TERNARY_KEY 3 + +/* Define NTMP Header Version */ +#define NTMP_HEADER_VERSION2 2 + +#define NTMP_REQ_HDR_NPF BIT(15) + +#define NTMP_RESP_LEN_MASK GENMASK(19, 0) +#define NTMP_REQ_LEN_MASK GENMASK(31, 20) + +#define ENETC_NTMP_ENTRY_ID_SIZE 4 + +#define ENETC_RSS_TABLE_ENTRY_NUM 64 +#define ENETC_RSS_CFGEU BIT(0) +#define ENETC_RSS_STSEU BIT(1) +#define ENETC_RSS_STSE_DATA_SIZE(n) ((n) * 8) +#define ENETC_RSS_CFGE_DATA_SIZE(n) (n) + +#define NTMP_REQ_RESP_LEN(req, resp) (((req) << 20 & NTMP_REQ_LEN_MASK) | \ + ((resp) & NTMP_RESP_LEN_MASK)) + +static inline uint32_t +netc_cbdr_read(void *reg) +{ + return rte_read32(reg); +} + +static inline void +netc_cbdr_write(void *reg, uint32_t val) +{ + rte_write32(val, reg); +} + +static inline void +ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma, + int len, int table_id, int cmd, + int access_method) +{ + dma_addr_t dma_align; + + memset(cbd, 0, sizeof(*cbd)); + dma_align = dma; + cbd->ntmp_req_hdr.addr = dma_align; + cbd->ntmp_req_hdr.len = len; + cbd->ntmp_req_hdr.cmd = cmd; + cbd->ntmp_req_hdr.access_method = access_method; + cbd->ntmp_req_hdr.table_id = table_id; + cbd->ntmp_req_hdr.hdr_ver = NTMP_HEADER_VERSION2; + cbd->ntmp_req_hdr.cci = 0; + cbd->ntmp_req_hdr.rr = 0; /* Must be set to 0 by SW. */ + /* For NTMP version 2.0 or later version */ + cbd->ntmp_req_hdr.npf = NTMP_REQ_HDR_NPF; +} + +static inline int +netc_get_free_cbd_num(struct netc_cbdr *cbdr) +{ + return (cbdr->next_to_clean - cbdr->next_to_use - 1 + cbdr->bd_num) % + cbdr->bd_num; +} + +static inline union +netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index) +{ + return &((union netc_cbd *)(cbdr->addr_base_align))[index]; +} + +static void +netc_clean_cbdr(struct netc_cbdr *cbdr) +{ + union netc_cbd *cbd; + uint32_t i; + + i = cbdr->next_to_clean; + while (netc_cbdr_read(cbdr->regs.cir) != i) { + cbd = netc_get_cbd(cbdr, i); + memset(cbd, 0, sizeof(*cbd)); + dcbf(cbd); + i = (i + 1) % cbdr->bd_num; + } + + cbdr->next_to_clean = i; +} + +static int +netc_xmit_ntmp_cmd(struct netc_cbdr *cbdr, union netc_cbd *cbd) +{ + union netc_cbd *ring_cbd; + uint32_t i, err = 0; + uint16_t status; + uint32_t timeout = cbdr->timeout; + uint32_t delay = cbdr->delay; + + if (unlikely(!cbdr->addr_base)) + return -EFAULT; + + rte_spinlock_lock(&cbdr->ring_lock); + + if (unlikely(!netc_get_free_cbd_num(cbdr))) + netc_clean_cbdr(cbdr); + + i = cbdr->next_to_use; + ring_cbd = netc_get_cbd(cbdr, i); + + /* Copy command BD to the ring */ + *ring_cbd = *cbd; + /* Update producer index of both software and hardware */ + i = (i + 1) % cbdr->bd_num; + dcbf(ring_cbd); + cbdr->next_to_use = i; + netc_cbdr_write(cbdr->regs.pir, i); + ENETC_PMD_DEBUG("Control msg sent PIR = %d, CIR = %d", netc_cbdr_read(cbdr->regs.pir), + netc_cbdr_read(cbdr->regs.cir)); + do { + if (netc_cbdr_read(cbdr->regs.cir) == i) { + dccivac(ring_cbd); + ENETC_PMD_DEBUG("got response"); + ENETC_PMD_DEBUG("Matched = %d, status = 0x%x", + ring_cbd->ntmp_resp_hdr.num_matched, + ring_cbd->ntmp_resp_hdr.error_rr); + break; + } + rte_delay_us(delay); + } while (timeout--); + + if (timeout <= 0) + ENETC_PMD_ERR("no response of RSS configuration"); + + ENETC_PMD_DEBUG("CIR after receive = %d, SICBDRSR = 0x%x", + netc_cbdr_read(cbdr->regs.cir), + netc_cbdr_read(cbdr->regs.st)); + /* Check the writeback error status */ + status = ring_cbd->ntmp_resp_hdr.error_rr & NTMP_RESP_HDR_ERR; + if (unlikely(status)) { + ENETC_PMD_ERR("Command BD error: 0x%04x", status); + err = -EIO; + } + + netc_clean_cbdr(cbdr); + rte_spinlock_unlock(&cbdr->ring_lock); + + return err; +} + +int +ntmp_rsst_query_or_update_entry(struct netc_cbdr *cbdr, uint32_t *table, + int count, bool query) +{ + struct rsst_req_update *requ; + struct rsst_req_query *req; + union netc_cbd cbd; + uint32_t len, data_size; + dma_addr_t dma; + int err, i; + void *tmp; + + if (count != ENETC_RSS_TABLE_ENTRY_NUM) + /* HW only takes in a full 64 entry table */ + return -EINVAL; + + if (query) + data_size = ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count) + + ENETC_RSS_CFGE_DATA_SIZE(count); + else + data_size = sizeof(*requ) + count * sizeof(uint8_t); + + tmp = rte_malloc(NULL, data_size, ENETC_CBDR_ALIGN); + if (!tmp) + return -ENOMEM; + + dma = rte_mem_virt2iova(tmp); + req = tmp; + /* Set the request data buffer */ + if (query) { + len = NTMP_REQ_RESP_LEN(sizeof(*req), data_size); + ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID, + NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID); + } else { + requ = (struct rsst_req_update *)req; + requ->crd.update_act = (ENETC_RSS_CFGEU | ENETC_RSS_STSEU); + for (i = 0; i < count; i++) + requ->groups[i] = (uint8_t)(table[i]); + + len = NTMP_REQ_RESP_LEN(data_size, 0); + ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID, + NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID); + dcbf(requ); + } + + err = netc_xmit_ntmp_cmd(cbdr, &cbd); + if (err) { + ENETC_PMD_ERR("%s RSS table entry failed (%d)!", + query ? "Query" : "Update", err); + goto end; + } + + if (query) { + uint8_t *group = (uint8_t *)req; + + group += ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count); + for (i = 0; i < count; i++) + table[i] = group[i]; + } +end: + rte_free(tmp); + + return err; +} + +static int +netc_setup_cbdr(struct rte_eth_dev *dev, int cbd_num, + struct netc_cbdr_regs *regs, + struct netc_cbdr *cbdr) +{ + int size; + + size = cbd_num * sizeof(union netc_cbd) + + NETC_CBDR_BASE_ADDR_ALIGN; + + cbdr->addr_base = rte_malloc(NULL, size, ENETC_CBDR_ALIGN); + if (!cbdr->addr_base) + return -ENOMEM; + + cbdr->dma_base = rte_mem_virt2iova(cbdr->addr_base); + cbdr->dma_size = size; + cbdr->bd_num = cbd_num; + cbdr->regs = *regs; + cbdr->dma_dev = dev; + cbdr->timeout = ENETC_CBDR_TIMEOUT; + cbdr->delay = ENETC_CBDR_DELAY; + + if (getenv("ENETC4_CBDR_TIMEOUT")) + cbdr->timeout = atoi(getenv("ENETC4_CBDR_TIMEOUT")); + + if (getenv("ENETC4_CBDR_DELAY")) + cbdr->delay = atoi(getenv("ENETC4_CBDR_DELAY")); + + + ENETC_PMD_DEBUG("CBDR timeout = %u and delay = %u", cbdr->timeout, + cbdr->delay); + /* The base address of the Control BD Ring must be 128 bytes aligned */ + cbdr->dma_base_align = cbdr->dma_base; + cbdr->addr_base_align = cbdr->addr_base; + + cbdr->next_to_clean = 0; + cbdr->next_to_use = 0; + rte_spinlock_init(&cbdr->ring_lock); + + netc_cbdr_write(cbdr->regs.mr, ~((uint32_t)NETC_CBDRMR_EN)); + /* Step 1: Configure the base address of the Control BD Ring */ + netc_cbdr_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align)); + netc_cbdr_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align)); + + /* Step 2: Configure the producer index register */ + netc_cbdr_write(cbdr->regs.pir, cbdr->next_to_clean); + + /* Step 3: Configure the consumer index register */ + netc_cbdr_write(cbdr->regs.cir, cbdr->next_to_use); + /* Step4: Configure the number of BDs of the Control BD Ring */ + netc_cbdr_write(cbdr->regs.lenr, cbdr->bd_num); + + /* Step 5: Enable the Control BD Ring */ + netc_cbdr_write(cbdr->regs.mr, NETC_CBDRMR_EN); + + return 0; +} + +void +netc_free_cbdr(struct netc_cbdr *cbdr) +{ + /* Disable the Control BD Ring */ + if (cbdr->regs.mr != NULL) { + netc_cbdr_write(cbdr->regs.mr, 0); + rte_free(cbdr->addr_base); + memset(cbdr, 0, sizeof(*cbdr)); + } +} + +int +enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw, + int bd_count, struct netc_cbdr *cbdr) +{ + struct netc_cbdr_regs regs; + + regs.pir = (void *)((size_t)hw->reg + ENETC4_SICBDRPIR); + regs.cir = (void *)((size_t)hw->reg + ENETC4_SICBDRCIR); + regs.mr = (void *)((size_t)hw->reg + ENETC4_SICBDRMR); + regs.st = (void *)((size_t)hw->reg + ENETC4_SICBDRSR); + regs.bar0 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR0); + regs.bar1 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR1); + regs.lenr = (void *)((size_t)hw->reg + ENETC4_SICBDRLENR); + regs.sictr0 = (void *)((size_t)hw->reg + ENETC4_SICTR0); + regs.sictr1 = (void *)((size_t)hw->reg + ENETC4_SICTR1); + + return netc_setup_cbdr(dev, bd_count, ®s, cbdr); +} diff --git a/drivers/net/enetc/meson.build b/drivers/net/enetc/meson.build index 6e00758a36..fe8fdc07f3 100644 --- a/drivers/net/enetc/meson.build +++ b/drivers/net/enetc/meson.build @@ -8,10 +8,11 @@ endif deps += ['common_dpaax'] sources = files( - 'enetc4_ethdev.c', - 'enetc4_vf.c', + 'enetc4_ethdev.c', + 'enetc4_vf.c', 'enetc_ethdev.c', 'enetc_rxtx.c', + 'enetc_cbdr.c', ) includes += include_directories('base') diff --git a/drivers/net/enetc/ntmp.h b/drivers/net/enetc/ntmp.h new file mode 100644 index 0000000000..0dbc006f26 --- /dev/null +++ b/drivers/net/enetc/ntmp.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2024 NXP + */ + +#ifndef ENETC_NTMP_H +#define ENETC_NTMP_H + +#include "compat.h" +#include + +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) +#define BITS_PER_LONG_LONG (__SIZEOF_LONG_LONG__ * 8) +#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +/* define NTMP Operation Commands */ +#define NTMP_CMD_DELETE BIT(0) +#define NTMP_CMD_UPDATE BIT(1) +#define NTMP_CMD_QUERY BIT(2) + +#define NETC_CBDR_TIMEOUT 1000 /* us */ +#define NETC_CBDR_BD_NUM 256 +#define NETC_CBDR_BASE_ADDR_ALIGN 128 +#define NETC_CBD_DATA_ADDR_ALIGN 16 +#define NETC_CBDRMR_EN BIT(31) + +#define NTMP_RESP_HDR_ERR GENMASK(11, 0) + +struct common_req_data { + uint16_t update_act; + uint8_t dbg_opt; + uint8_t query_act:4; + uint8_t tbl_ver:4; +}; + +/* RSS Table Request and Response Data Buffer Format */ +struct rsst_req_query { + struct common_req_data crd; + uint32_t entry_id; +}; + +/* struct for update operation */ +struct rsst_req_update { + struct common_req_data crd; + uint32_t entry_id; + uint8_t groups[]; +}; + +/* The format of conctrol buffer descriptor */ +union netc_cbd { + struct { + uint64_t addr; + uint32_t len; + uint8_t cmd; + uint8_t resv1:4; + uint8_t access_method:4; + uint8_t table_id; + uint8_t hdr_ver:6; + uint8_t cci:1; + uint8_t rr:1; + uint32_t resv2[3]; + uint32_t npf; + } ntmp_req_hdr; /* NTMP Request Message Header Format */ + + struct { + uint32_t resv1[3]; + uint16_t num_matched; + uint16_t error_rr; /* bit0~11: error, bit12~14: reserved, bit15: rr */ + uint32_t resv3[4]; + } ntmp_resp_hdr; /* NTMP Response Message Header Format */ +}; + +struct netc_cbdr_regs { + void *pir; + void *cir; + void *mr; + void *st; + + void *bar0; + void *bar1; + void *lenr; + + /* station interface current time register */ + void *sictr0; + void *sictr1; +}; + +struct netc_cbdr { + struct netc_cbdr_regs regs; + + int bd_num; + int next_to_use; + int next_to_clean; + + int dma_size; + void *addr_base; + void *addr_base_align; + dma_addr_t dma_base; + dma_addr_t dma_base_align; + struct rte_eth_dev *dma_dev; + + rte_spinlock_t ring_lock; /* Avoid race condition */ + + /* bitmap of used words of SGCL table */ + unsigned long *sgclt_used_words; + uint32_t sgclt_words_num; + uint32_t timeout; + uint32_t delay; +}; + +#endif /* ENETC_NTMP_H */ -- 2.25.1