LCOV - code coverage report
Current view: top level - drivers/net/enetc - enetc_cbdr.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 108 0.0 %
Date: 2025-11-01 17:50:34 Functions: 0 6 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2024 NXP
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <ethdev_pci.h>
       6                 :            : 
       7                 :            : #include "enetc_logs.h"
       8                 :            : #include "enetc.h"
       9                 :            : 
      10                 :            : #define NTMP_RSST_ID                    3
      11                 :            : 
      12                 :            : /* Define NTMP Access Method */
      13                 :            : #define NTMP_AM_ENTRY_ID                0
      14                 :            : #define NTMP_AM_EXACT_KEY               1
      15                 :            : #define NTMP_AM_SEARCH                  2
      16                 :            : #define NTMP_AM_TERNARY_KEY             3
      17                 :            : 
      18                 :            : /* Define NTMP Header Version */
      19                 :            : #define NTMP_HEADER_VERSION2            2
      20                 :            : 
      21                 :            : #define NTMP_REQ_HDR_NPF                BIT(15)
      22                 :            : 
      23                 :            : #define NTMP_RESP_LEN_MASK              GENMASK(19, 0)
      24                 :            : #define NTMP_REQ_LEN_MASK               GENMASK(31, 20)
      25                 :            : 
      26                 :            : #define ENETC_NTMP_ENTRY_ID_SIZE        4
      27                 :            : 
      28                 :            : #define ENETC_RSS_TABLE_ENTRY_NUM       64
      29                 :            : #define ENETC_RSS_CFGEU                 BIT(0)
      30                 :            : #define ENETC_RSS_STSEU                 BIT(1)
      31                 :            : #define ENETC_RSS_STSE_DATA_SIZE(n)     ((n) * 8)
      32                 :            : #define ENETC_RSS_CFGE_DATA_SIZE(n)     (n)
      33                 :            : 
      34                 :            : #define NTMP_REQ_RESP_LEN(req, resp)    (((req) << 20 & NTMP_REQ_LEN_MASK) | \
      35                 :            :                                         ((resp) & NTMP_RESP_LEN_MASK))
      36                 :            : 
      37                 :            : static inline uint32_t
      38                 :            : netc_cbdr_read(void *reg)
      39                 :            : {
      40                 :            :         return rte_read32(reg);
      41                 :            : }
      42                 :            : 
      43                 :            : static inline void
      44                 :            : netc_cbdr_write(void *reg, uint32_t val)
      45                 :            : {
      46                 :            :         rte_write32(val, reg);
      47                 :            : }
      48                 :            : 
      49                 :            : static inline void
      50                 :            : ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma,
      51                 :            :                         int len, int table_id, int cmd,
      52                 :            :                         int access_method)
      53                 :            : {
      54                 :            :         dma_addr_t dma_align;
      55                 :            : 
      56                 :            :         memset(cbd, 0, sizeof(*cbd));
      57                 :            :         dma_align = dma;
      58                 :          0 :         cbd->ntmp_req_hdr.addr = dma_align;
      59                 :          0 :         cbd->ntmp_req_hdr.len = len;
      60                 :          0 :         cbd->ntmp_req_hdr.cmd = cmd;
      61                 :            :         cbd->ntmp_req_hdr.access_method = access_method;
      62                 :          0 :         cbd->ntmp_req_hdr.table_id = table_id;
      63                 :          0 :         cbd->ntmp_req_hdr.hdr_ver = NTMP_HEADER_VERSION2;
      64                 :            :         cbd->ntmp_req_hdr.cci = 0;
      65                 :            :         cbd->ntmp_req_hdr.rr = 0;       /* Must be set to 0 by SW. */
      66                 :            :         /* For NTMP version 2.0 or later version */
      67                 :          0 :         cbd->ntmp_req_hdr.npf = NTMP_REQ_HDR_NPF;
      68                 :          0 : }
      69                 :            : 
      70                 :            : static inline int
      71                 :            : netc_get_free_cbd_num(struct netc_cbdr *cbdr)
      72                 :            : {
      73                 :          0 :         return (cbdr->next_to_clean - cbdr->next_to_use - 1 + cbdr->bd_num) %
      74                 :            :                 cbdr->bd_num;
      75                 :            : }
      76                 :            : 
      77                 :            : static inline union
      78                 :            : netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index)
      79                 :            : {
      80                 :          0 :         return &((union netc_cbd *)(cbdr->addr_base_align))[index];
      81                 :            : }
      82                 :            : 
      83                 :            : static void
      84                 :          0 : netc_clean_cbdr(struct netc_cbdr *cbdr)
      85                 :            : {
      86                 :            :         union netc_cbd *cbd;
      87                 :            :         uint32_t i;
      88                 :            : 
      89                 :          0 :         i = cbdr->next_to_clean;
      90         [ #  # ]:          0 :         while (netc_cbdr_read(cbdr->regs.cir) != i) {
      91                 :          0 :                 cbd = netc_get_cbd(cbdr, i);
      92                 :            :                 memset(cbd, 0, sizeof(*cbd));
      93                 :            :                 dcbf(cbd);
      94                 :          0 :                 i = (i + 1) % cbdr->bd_num;
      95                 :            :         }
      96                 :            : 
      97                 :          0 :         cbdr->next_to_clean = i;
      98                 :          0 : }
      99                 :            : 
     100                 :            : static int
     101                 :          0 : netc_xmit_ntmp_cmd(struct netc_cbdr *cbdr, union netc_cbd *cbd)
     102                 :            : {
     103                 :            :         union netc_cbd *ring_cbd;
     104                 :            :         uint32_t i, err = 0;
     105                 :            :         uint16_t status;
     106                 :          0 :         uint32_t timeout = cbdr->timeout;
     107                 :          0 :         uint32_t delay = cbdr->delay;
     108                 :            : 
     109         [ #  # ]:          0 :         if (unlikely(!cbdr->addr_base))
     110                 :            :                 return -EFAULT;
     111                 :            : 
     112                 :          0 :         rte_spinlock_lock(&cbdr->ring_lock);
     113                 :            : 
     114         [ #  # ]:          0 :         if (unlikely(!netc_get_free_cbd_num(cbdr)))
     115                 :          0 :                 netc_clean_cbdr(cbdr);
     116                 :            : 
     117                 :          0 :         i = cbdr->next_to_use;
     118                 :            :         ring_cbd = netc_get_cbd(cbdr, i);
     119                 :            : 
     120                 :            :         /* Copy command BD to the ring */
     121                 :          0 :         *ring_cbd = *cbd;
     122                 :            :         /* Update producer index of both software and hardware */
     123                 :          0 :         i = (i + 1) % cbdr->bd_num;
     124                 :            :         dcbf(ring_cbd);
     125                 :          0 :         cbdr->next_to_use = i;
     126                 :          0 :         netc_cbdr_write(cbdr->regs.pir, i);
     127                 :          0 :         ENETC_PMD_DEBUG("Control msg sent PIR = %d, CIR = %d", netc_cbdr_read(cbdr->regs.pir),
     128                 :            :                                         netc_cbdr_read(cbdr->regs.cir));
     129                 :            :         do {
     130         [ #  # ]:          0 :                 if (netc_cbdr_read(cbdr->regs.cir) == i) {
     131                 :            :                         dccivac(ring_cbd);
     132                 :          0 :                         ENETC_PMD_DEBUG("got response");
     133                 :          0 :                         ENETC_PMD_DEBUG("Matched = %d, status = 0x%x",
     134                 :            :                                         ring_cbd->ntmp_resp_hdr.num_matched,
     135                 :            :                                         ring_cbd->ntmp_resp_hdr.error_rr);
     136                 :          0 :                         break;
     137                 :            :                 }
     138                 :          0 :                 rte_delay_us(delay);
     139         [ #  # ]:          0 :         } while (timeout--);
     140                 :            : 
     141         [ #  # ]:          0 :         if (timeout <= 0)
     142                 :          0 :                 ENETC_PMD_ERR("no response of RSS configuration");
     143                 :            : 
     144                 :          0 :         ENETC_PMD_DEBUG("CIR after receive = %d, SICBDRSR = 0x%x",
     145                 :            :                                         netc_cbdr_read(cbdr->regs.cir),
     146                 :            :                                         netc_cbdr_read(cbdr->regs.st));
     147                 :            :         /* Check the writeback error status */
     148                 :          0 :         status = ring_cbd->ntmp_resp_hdr.error_rr & NTMP_RESP_HDR_ERR;
     149         [ #  # ]:          0 :         if (unlikely(status)) {
     150                 :          0 :                 ENETC_PMD_ERR("Command BD error: 0x%04x", status);
     151                 :            :                 err = -EIO;
     152                 :            :         }
     153                 :            : 
     154                 :          0 :         netc_clean_cbdr(cbdr);
     155                 :            :         rte_spinlock_unlock(&cbdr->ring_lock);
     156                 :            : 
     157                 :          0 :         return err;
     158                 :            : }
     159                 :            : 
     160                 :            : int
     161                 :          0 : enetc_ntmp_rsst_query_or_update_entry(struct netc_cbdr *cbdr, uint32_t *table,
     162                 :            :                                 int count, bool query)
     163                 :            : {
     164                 :            :         struct rsst_req_update *requ;
     165                 :            :         struct rsst_req_query *req;
     166                 :            :         union netc_cbd cbd;
     167                 :            :         uint32_t len, data_size;
     168                 :            :         dma_addr_t dma;
     169                 :            :         int err, i;
     170                 :            :         void *tmp;
     171                 :            : 
     172         [ #  # ]:          0 :         if (count != ENETC_RSS_TABLE_ENTRY_NUM)
     173                 :            :                 /* HW only takes in a full 64 entry table */
     174                 :            :                 return -EINVAL;
     175                 :            : 
     176         [ #  # ]:          0 :         if (query)
     177                 :            :                 data_size = ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count) +
     178                 :            :                         ENETC_RSS_CFGE_DATA_SIZE(count);
     179                 :            :         else
     180                 :            :                 data_size = sizeof(*requ) + count * sizeof(uint8_t);
     181                 :            : 
     182                 :          0 :         tmp = rte_malloc(NULL, data_size, ENETC_CBDR_ALIGN);
     183         [ #  # ]:          0 :         if (!tmp)
     184                 :            :                 return -ENOMEM;
     185                 :            : 
     186                 :          0 :         dma = rte_mem_virt2iova(tmp);
     187                 :            :         req = tmp;
     188                 :            :         /* Set the request data buffer */
     189         [ #  # ]:          0 :         if (query) {
     190                 :          0 :                 len = NTMP_REQ_RESP_LEN(sizeof(*req), data_size);
     191                 :            :                 ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID,
     192                 :            :                                         NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
     193                 :            :         } else {
     194                 :            :                 requ = (struct rsst_req_update *)req;
     195                 :          0 :                 requ->crd.update_act = (ENETC_RSS_CFGEU | ENETC_RSS_STSEU);
     196         [ #  # ]:          0 :                 for (i = 0; i < count; i++)
     197                 :          0 :                         requ->groups[i] = (uint8_t)(table[i]);
     198                 :            : 
     199                 :          0 :                 len = NTMP_REQ_RESP_LEN(data_size, 0);
     200                 :            :                 ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID,
     201                 :            :                                 NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
     202                 :            :                 dcbf(requ);
     203                 :            :         }
     204                 :            : 
     205                 :          0 :         err = netc_xmit_ntmp_cmd(cbdr, &cbd);
     206         [ #  # ]:          0 :         if (err) {
     207         [ #  # ]:          0 :                 ENETC_PMD_ERR("%s RSS table entry failed (%d)!",
     208                 :            :                                 query ? "Query" : "Update", err);
     209                 :          0 :                 goto end;
     210                 :            :         }
     211                 :            : 
     212         [ #  # ]:          0 :         if (query) {
     213                 :            :                 uint8_t *group = (uint8_t *)req;
     214                 :            : 
     215                 :            :                 group += ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count);
     216         [ #  # ]:          0 :                 for (i = 0; i < count; i++)
     217                 :          0 :                         table[i] = group[i];
     218                 :            :         }
     219                 :          0 : end:
     220                 :          0 :         rte_free(tmp);
     221                 :            : 
     222                 :          0 :         return err;
     223                 :            : }
     224                 :            : 
     225                 :            : static int
     226                 :          0 : netc_setup_cbdr(struct rte_eth_dev *dev, int cbd_num,
     227                 :            :                 struct netc_cbdr_regs *regs,
     228                 :            :                 struct netc_cbdr *cbdr)
     229                 :            : {
     230                 :            :         int size;
     231                 :            : 
     232                 :          0 :         size = cbd_num * sizeof(union netc_cbd) +
     233                 :            :                 NETC_CBDR_BASE_ADDR_ALIGN;
     234                 :            : 
     235                 :          0 :         cbdr->addr_base = rte_malloc(NULL, size, ENETC_CBDR_ALIGN);
     236         [ #  # ]:          0 :         if (!cbdr->addr_base)
     237                 :            :                 return -ENOMEM;
     238                 :            : 
     239                 :          0 :         cbdr->dma_base = rte_mem_virt2iova(cbdr->addr_base);
     240                 :          0 :         cbdr->dma_size = size;
     241                 :          0 :         cbdr->bd_num = cbd_num;
     242                 :          0 :         cbdr->regs = *regs;
     243                 :          0 :         cbdr->dma_dev = dev;
     244                 :          0 :         cbdr->timeout = ENETC_CBDR_TIMEOUT;
     245                 :          0 :         cbdr->delay = ENETC_CBDR_DELAY;
     246                 :            : 
     247         [ #  # ]:          0 :         if (getenv("ENETC4_CBDR_TIMEOUT"))
     248                 :          0 :                 cbdr->timeout = atoi(getenv("ENETC4_CBDR_TIMEOUT"));
     249                 :            : 
     250         [ #  # ]:          0 :         if (getenv("ENETC4_CBDR_DELAY"))
     251                 :          0 :                 cbdr->delay = atoi(getenv("ENETC4_CBDR_DELAY"));
     252                 :            : 
     253                 :            : 
     254                 :          0 :         ENETC_PMD_DEBUG("CBDR timeout = %u and delay = %u", cbdr->timeout,
     255                 :            :                                                 cbdr->delay);
     256                 :            :         /* The base address of the Control BD Ring must be 128 bytes aligned */
     257                 :          0 :         cbdr->dma_base_align =  cbdr->dma_base;
     258                 :          0 :         cbdr->addr_base_align = cbdr->addr_base;
     259                 :            : 
     260                 :          0 :         cbdr->next_to_clean = 0;
     261                 :          0 :         cbdr->next_to_use = 0;
     262                 :            :         rte_spinlock_init(&cbdr->ring_lock);
     263                 :            : 
     264                 :          0 :         netc_cbdr_write(cbdr->regs.mr, ~((uint32_t)NETC_CBDRMR_EN));
     265                 :            :         /* Step 1: Configure the base address of the Control BD Ring */
     266                 :          0 :         netc_cbdr_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
     267                 :          0 :         netc_cbdr_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
     268                 :            : 
     269                 :            :         /* Step 2: Configure the producer index register */
     270                 :          0 :         netc_cbdr_write(cbdr->regs.pir, cbdr->next_to_clean);
     271                 :            : 
     272                 :            :         /* Step 3: Configure the consumer index register */
     273                 :          0 :         netc_cbdr_write(cbdr->regs.cir, cbdr->next_to_use);
     274                 :            :         /* Step4: Configure the number of BDs of the Control BD Ring */
     275                 :          0 :         netc_cbdr_write(cbdr->regs.lenr, cbdr->bd_num);
     276                 :            : 
     277                 :            :         /* Step 5: Enable the Control BD Ring */
     278                 :          0 :         netc_cbdr_write(cbdr->regs.mr, NETC_CBDRMR_EN);
     279                 :            : 
     280                 :          0 :         return 0;
     281                 :            : }
     282                 :            : 
     283                 :            : void
     284                 :          0 : enetc_free_cbdr(struct netc_cbdr *cbdr)
     285                 :            : {
     286                 :            :         /* Disable the Control BD Ring */
     287         [ #  # ]:          0 :         if (cbdr->regs.mr != NULL) {
     288                 :            :                 netc_cbdr_write(cbdr->regs.mr, 0);
     289                 :          0 :                 rte_free(cbdr->addr_base);
     290                 :            :                 memset(cbdr, 0, sizeof(*cbdr));
     291                 :            :         }
     292                 :          0 : }
     293                 :            : 
     294                 :            : int
     295                 :          0 : enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw,
     296                 :            :                   int bd_count, struct netc_cbdr *cbdr)
     297                 :            : {
     298                 :            :         struct netc_cbdr_regs regs;
     299                 :            : 
     300                 :          0 :         regs.pir = (void *)((size_t)hw->reg + ENETC4_SICBDRPIR);
     301                 :          0 :         regs.cir = (void *)((size_t)hw->reg + ENETC4_SICBDRCIR);
     302                 :          0 :         regs.mr = (void *)((size_t)hw->reg + ENETC4_SICBDRMR);
     303                 :          0 :         regs.st = (void *)((size_t)hw->reg + ENETC4_SICBDRSR);
     304                 :          0 :         regs.bar0 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR0);
     305                 :          0 :         regs.bar1 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR1);
     306                 :          0 :         regs.lenr = (void *)((size_t)hw->reg + ENETC4_SICBDRLENR);
     307                 :          0 :         regs.sictr0 = (void *)((size_t)hw->reg + ENETC4_SICTR0);
     308                 :          0 :         regs.sictr1 = (void *)((size_t)hw->reg + ENETC4_SICTR1);
     309                 :            : 
     310                 :          0 :         return netc_setup_cbdr(dev, bd_count, &regs, cbdr);
     311                 :            : }

Generated by: LCOV version 1.14