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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2025 Huawei Technologies Co., Ltd
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "base/hinic3_compat.h"
       6                 :            : #include "base/hinic3_hwif.h"
       7                 :            : #include "base/hinic3_hwdev.h"
       8                 :            : #include "base/hinic3_wq.h"
       9                 :            : #include "base/hinic3_nic_cfg.h"
      10                 :            : #include "hinic3_nic_io.h"
      11                 :            : #include "hinic3_ethdev.h"
      12                 :            : #include "hinic3_rx.h"
      13                 :            : 
      14                 :            : /**
      15                 :            :  * Get wqe from receive queue.
      16                 :            :  *
      17                 :            :  * @param[in] rxq
      18                 :            :  * Receive queue.
      19                 :            :  * @param[out] rq_wqe
      20                 :            :  * Receive queue wqe.
      21                 :            :  * @param[out] pi
      22                 :            :  * Current pi.
      23                 :            :  */
      24                 :            : static inline void
      25                 :            : hinic3_get_rq_wqe(struct hinic3_rxq *rxq, struct hinic3_rq_wqe **rq_wqe,
      26                 :            :                   uint16_t *pi)
      27                 :            : {
      28                 :          0 :         *pi = MASKED_QUEUE_IDX(rxq, rxq->prod_idx);
      29                 :            : 
      30                 :            :         /* Get only one rxq wqe. */
      31                 :          0 :         rxq->prod_idx++;
      32                 :          0 :         rxq->delta--;
      33                 :            : 
      34                 :          0 :         *rq_wqe = NIC_WQE_ADDR(rxq, *pi);
      35                 :            : }
      36                 :            : 
      37                 :            : /**
      38                 :            :  * Put wqe into receive queue.
      39                 :            :  *
      40                 :            :  * @param[in] rxq
      41                 :            :  * Receive queue.
      42                 :            :  * @param[in] wqe_cnt
      43                 :            :  * Wqebb counters.
      44                 :            :  */
      45                 :            : static inline void
      46                 :            : hinic3_put_rq_wqe(struct hinic3_rxq *rxq, uint16_t wqe_cnt)
      47                 :            : {
      48                 :          0 :         rxq->delta += wqe_cnt;
      49                 :          0 :         rxq->prod_idx -= wqe_cnt;
      50                 :            : }
      51                 :            : 
      52                 :            : /**
      53                 :            :  * Get receive queue local pi.
      54                 :            :  *
      55                 :            :  * @param[in] rxq
      56                 :            :  * Receive queue.
      57                 :            :  * @return
      58                 :            :  * Receive queue local pi.
      59                 :            :  */
      60                 :            : static inline uint16_t
      61                 :            : hinic3_get_rq_local_pi(struct hinic3_rxq *rxq)
      62                 :            : {
      63                 :          0 :         return MASKED_QUEUE_IDX(rxq, rxq->prod_idx);
      64                 :            : }
      65                 :            : 
      66                 :            : uint16_t
      67                 :          0 : hinic3_rx_fill_wqe(struct hinic3_rxq *rxq)
      68                 :            : {
      69                 :            :         struct hinic3_rq_wqe *rq_wqe = NULL;
      70                 :          0 :         struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
      71                 :            :         rte_iova_t cqe_dma;
      72                 :            :         uint16_t pi = 0;
      73                 :            :         uint16_t i;
      74                 :            : 
      75                 :          0 :         cqe_dma = rxq->cqe_start_paddr;
      76         [ #  # ]:          0 :         for (i = 0; i < rxq->q_depth; i++) {
      77                 :            :                 hinic3_get_rq_wqe(rxq, &rq_wqe, &pi);
      78         [ #  # ]:          0 :                 if (!rq_wqe) {
      79                 :          0 :                         PMD_DRV_LOG(ERR,
      80                 :            :                                     "Get rq wqe failed, rxq id: %d, wqe id: %d",
      81                 :            :                                     rxq->q_id, i);
      82                 :          0 :                         break;
      83                 :            :                 }
      84                 :            : 
      85         [ #  # ]:          0 :                 if (rxq->wqe_type == HINIC3_EXTEND_RQ_WQE) {
      86                 :            :                         /* Unit of cqe length is 16B. */
      87                 :          0 :                         hinic3_set_sge(&rq_wqe->extend_wqe.cqe_sect.sge,
      88                 :            :                                        cqe_dma,
      89                 :            :                                        HINIC3_CQE_LEN >> HINIC3_CQE_SIZE_SHIFT);
      90                 :            :                         /* Use fixed len. */
      91                 :          0 :                         rq_wqe->extend_wqe.buf_desc.sge.len = nic_dev->rx_buff_len;
      92                 :            :                 } else {
      93                 :          0 :                         rq_wqe->normal_wqe.cqe_hi_addr = upper_32_bits(cqe_dma);
      94                 :          0 :                         rq_wqe->normal_wqe.cqe_lo_addr = lower_32_bits(cqe_dma);
      95                 :            :                 }
      96                 :            : 
      97                 :          0 :                 cqe_dma += sizeof(struct hinic3_rq_cqe);
      98                 :            : 
      99                 :            :                 hinic3_cpu_to_hw(rq_wqe, rxq->wqebb_size);
     100                 :            :         }
     101                 :            : 
     102                 :            :         hinic3_put_rq_wqe(rxq, i);
     103                 :            : 
     104                 :          0 :         return i;
     105                 :            : }
     106                 :            : 
     107                 :            : static struct rte_mbuf *
     108                 :          0 : hinic3_rx_alloc_mbuf(struct hinic3_rxq *rxq, rte_iova_t *dma_addr)
     109                 :            : {
     110                 :          0 :         struct rte_mbuf *mbuf = NULL;
     111                 :            : 
     112         [ #  # ]:          0 :         if (unlikely(rte_pktmbuf_alloc_bulk(rxq->mb_pool, &mbuf, 1) != 0))
     113                 :            :                 return NULL;
     114                 :            : 
     115                 :          0 :         *dma_addr = rte_mbuf_data_iova_default(mbuf);
     116                 :            : #ifdef HINIC3_XSTAT_MBUF_USE
     117                 :            :         rxq->rxq_stats.rx_alloc_mbuf_bytes++;
     118                 :            : #endif
     119                 :          0 :         return mbuf;
     120                 :            : }
     121                 :            : 
     122                 :            : #ifdef HINIC3_XSTAT_RXBUF_INFO
     123                 :            : static void
     124                 :            : hinic3_rxq_buffer_done_count(struct hinic3_rxq *rxq)
     125                 :            : {
     126                 :            :         uint16_t sw_ci, avail_pkts = 0, hit_done = 0, cqe_hole = 0;
     127                 :            :         RTE_ATOMIC(uint32_t)status;
     128                 :            :         volatile struct hinic3_rq_cqe *rx_cqe;
     129                 :            : 
     130                 :            :         for (sw_ci = 0; sw_ci < rxq->q_depth; sw_ci++) {
     131                 :            :                 rx_cqe = &rxq->rx_cqe[sw_ci];
     132                 :            : 
     133                 :            :                 /* Check current ci is done. */
     134                 :            :                 status = rx_cqe->status;
     135                 :            :                 if (!HINIC3_GET_RX_DONE(status)) {
     136                 :            :                         if (hit_done) {
     137                 :            :                                 cqe_hole++;
     138                 :            :                                 hit_done = 0;
     139                 :            :                         }
     140                 :            :                         continue;
     141                 :            :                 }
     142                 :            : 
     143                 :            :                 avail_pkts++;
     144                 :            :                 hit_done = 1;
     145                 :            :         }
     146                 :            : 
     147                 :            :         rxq->rxq_stats.rx_avail = avail_pkts;
     148                 :            :         rxq->rxq_stats.rx_hole = cqe_hole;
     149                 :            : }
     150                 :            : 
     151                 :            : void
     152                 :            : hinic3_get_stats(struct hinic3_rxq *rxq)
     153                 :            : {
     154                 :            :         rxq->rxq_stats.rx_mbuf = rxq->q_depth - hinic3_get_rq_free_wqebb(rxq);
     155                 :            : 
     156                 :            :         hinic3_rxq_buffer_done_count(rxq);
     157                 :            : }
     158                 :            : #endif
     159                 :            : 
     160                 :            : uint16_t
     161                 :          0 : hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
     162                 :            : {
     163                 :            :         struct hinic3_rq_wqe *rq_wqe = NULL;
     164                 :            :         struct hinic3_rx_info *rx_info = NULL;
     165                 :            :         struct rte_mbuf *mb = NULL;
     166                 :            :         rte_iova_t dma_addr;
     167                 :            :         uint16_t i, free_wqebbs;
     168                 :            : 
     169                 :          0 :         free_wqebbs = rxq->delta - 1;
     170         [ #  # ]:          0 :         for (i = 0; i < free_wqebbs; i++) {
     171                 :          0 :                 rx_info = &rxq->rx_info[rxq->next_to_update];
     172                 :            : 
     173                 :          0 :                 mb = hinic3_rx_alloc_mbuf(rxq, &dma_addr);
     174         [ #  # ]:          0 :                 if (!mb) {
     175                 :          0 :                         PMD_DRV_LOG(ERR, "Alloc mbuf failed");
     176                 :          0 :                         break;
     177                 :            :                 }
     178                 :            : 
     179                 :          0 :                 rx_info->mbuf = mb;
     180                 :            : 
     181                 :          0 :                 rq_wqe = NIC_WQE_ADDR(rxq, rxq->next_to_update);
     182                 :            : 
     183                 :            :                 /* Fill buffer address only. */
     184         [ #  # ]:          0 :                 if (rxq->wqe_type == HINIC3_EXTEND_RQ_WQE) {
     185                 :          0 :                         rq_wqe->extend_wqe.buf_desc.sge.hi_addr =
     186                 :          0 :                                 hinic3_hw_be32(upper_32_bits(dma_addr));
     187                 :          0 :                         rq_wqe->extend_wqe.buf_desc.sge.lo_addr =
     188                 :          0 :                                 hinic3_hw_be32(lower_32_bits(dma_addr));
     189                 :            :                 } else {
     190                 :          0 :                         rq_wqe->normal_wqe.buf_hi_addr =
     191                 :          0 :                                 hinic3_hw_be32(upper_32_bits(dma_addr));
     192                 :          0 :                         rq_wqe->normal_wqe.buf_lo_addr =
     193                 :          0 :                                 hinic3_hw_be32(lower_32_bits(dma_addr));
     194                 :            :                 }
     195                 :            : 
     196                 :          0 :                 rxq->next_to_update = (rxq->next_to_update + 1) & rxq->q_mask;
     197                 :            :         }
     198                 :            : 
     199         [ #  # ]:          0 :         if (likely(i > 0)) {
     200                 :          0 :                 hinic3_write_db(rxq->db_addr, rxq->q_id, 0, RQ_CFLAG_DP,
     201                 :          0 :                                 (rxq->next_to_update << rxq->wqe_type));
     202                 :            :                 /* Init rxq contxet used, need to optimization. */
     203                 :          0 :                 rxq->prod_idx = rxq->next_to_update;
     204                 :          0 :                 rxq->delta -= i;
     205                 :            :         } else {
     206                 :          0 :                 PMD_DRV_LOG(ERR, "Alloc rx buffers failed, rxq_id: %d", rxq->q_id);
     207                 :            :         }
     208                 :            : 
     209                 :          0 :         return i;
     210                 :            : }
     211                 :            : 
     212                 :            : void
     213                 :          0 : hinic3_free_rxq_mbufs(struct hinic3_rxq *rxq)
     214                 :            : {
     215                 :            :         struct hinic3_rx_info *rx_info = NULL;
     216                 :          0 :         int free_wqebbs = hinic3_get_rq_free_wqebb(rxq) + 1;
     217                 :            :         volatile struct hinic3_rq_cqe *rx_cqe = NULL;
     218                 :            :         uint16_t ci;
     219                 :            : 
     220         [ #  # ]:          0 :         while (free_wqebbs++ < rxq->q_depth) {
     221                 :            :                 ci = hinic3_get_rq_local_ci(rxq);
     222                 :            : 
     223                 :          0 :                 rx_cqe = &rxq->rx_cqe[ci];
     224                 :            : 
     225                 :            :                 /* Clear done bit. */
     226                 :          0 :                 rx_cqe->status = 0;
     227                 :            : 
     228                 :          0 :                 rx_info = &rxq->rx_info[ci];
     229                 :          0 :                 rte_pktmbuf_free(rx_info->mbuf);
     230                 :          0 :                 rx_info->mbuf = NULL;
     231                 :            : 
     232                 :            :                 hinic3_update_rq_local_ci(rxq, 1);
     233                 :            : #ifdef HINIC3_XSTAT_MBUF_USE
     234                 :            :                 rxq->rxq_stats.rx_free_mbuf_bytes++;
     235                 :            : #endif
     236                 :            :         }
     237                 :          0 : }
     238                 :            : 
     239                 :            : void
     240                 :          0 : hinic3_free_all_rxq_mbufs(struct hinic3_nic_dev *nic_dev)
     241                 :            : {
     242                 :            :         uint16_t qid;
     243                 :            : 
     244         [ #  # ]:          0 :         for (qid = 0; qid < nic_dev->num_rqs; qid++)
     245                 :          0 :                 hinic3_free_rxq_mbufs(nic_dev->rxqs[qid]);
     246                 :          0 : }
     247                 :            : 
     248                 :            : static uint32_t
     249                 :            : hinic3_rx_alloc_mbuf_bulk(struct hinic3_rxq *rxq, struct rte_mbuf **mbufs,
     250                 :            :                           uint32_t exp_mbuf_cnt)
     251                 :            : {
     252                 :            :         uint32_t avail_cnt;
     253                 :            :         int err;
     254                 :            : 
     255                 :          0 :         err = rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, exp_mbuf_cnt);
     256         [ #  # ]:          0 :         if (likely(err == 0)) {
     257                 :            :                 avail_cnt = exp_mbuf_cnt;
     258                 :            :         } else {
     259                 :            :                 avail_cnt = 0;
     260                 :          0 :                 rxq->rxq_stats.rx_nombuf += exp_mbuf_cnt;
     261                 :            :         }
     262                 :            : #ifdef HINIC3_XSTAT_MBUF_USE
     263                 :            :         rxq->rxq_stats.rx_alloc_mbuf_bytes += avail_cnt;
     264                 :            : #endif
     265                 :            :         return avail_cnt;
     266                 :            : }
     267                 :            : 
     268                 :            : static int
     269                 :          0 : hinic3_rearm_rxq_mbuf(struct hinic3_rxq *rxq)
     270                 :            : {
     271                 :            :         struct hinic3_rq_wqe *rq_wqe = NULL;
     272                 :            :         struct rte_mbuf **rearm_mbufs;
     273                 :            :         uint32_t i, free_wqebbs, rearm_wqebbs, exp_wqebbs;
     274                 :            :         rte_iova_t dma_addr;
     275                 :            :         uint16_t pi;
     276         [ #  # ]:          0 :         struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
     277                 :            : 
     278                 :            :         /* Check free wqebb cnt fo rearm. */
     279                 :          0 :         free_wqebbs = hinic3_get_rq_free_wqebb(rxq);
     280         [ #  # ]:          0 :         if (unlikely(free_wqebbs < rxq->rx_free_thresh))
     281                 :            :                 return -ENOMEM;
     282                 :            : 
     283                 :            :         /* Get rearm mbuf array. */
     284                 :            :         pi = hinic3_get_rq_local_pi(rxq);
     285                 :          0 :         rearm_mbufs = (struct rte_mbuf **)(&rxq->rx_info[pi]);
     286                 :            : 
     287                 :            :         /* Check rxq free wqebbs turn around. */
     288                 :          0 :         exp_wqebbs = rxq->q_depth - pi;
     289                 :            :         if (free_wqebbs < exp_wqebbs)
     290                 :            :                 exp_wqebbs = free_wqebbs;
     291                 :            : 
     292                 :            :         /* Alloc mbuf in bulk. */
     293                 :            :         rearm_wqebbs = hinic3_rx_alloc_mbuf_bulk(rxq, rearm_mbufs, exp_wqebbs);
     294         [ #  # ]:          0 :         if (unlikely(rearm_wqebbs == 0))
     295                 :            :                 return -ENOMEM;
     296                 :            : 
     297                 :            :         /* Rearm rxq mbuf. */
     298                 :          0 :         rq_wqe = NIC_WQE_ADDR(rxq, pi);
     299         [ #  # ]:          0 :         for (i = 0; i < rearm_wqebbs; i++) {
     300         [ #  # ]:          0 :                 dma_addr = rte_mbuf_data_iova_default(rearm_mbufs[i]);
     301                 :            : 
     302                 :            :                 /* Fill buffer address only. */
     303         [ #  # ]:          0 :                 if (rxq->wqe_type == HINIC3_EXTEND_RQ_WQE) {
     304                 :          0 :                         rq_wqe->extend_wqe.buf_desc.sge.hi_addr =
     305                 :          0 :                                 hinic3_hw_be32(upper_32_bits(dma_addr));
     306                 :          0 :                         rq_wqe->extend_wqe.buf_desc.sge.lo_addr =
     307                 :          0 :                                 hinic3_hw_be32(lower_32_bits(dma_addr));
     308                 :          0 :                         rq_wqe->extend_wqe.buf_desc.sge.len =
     309                 :          0 :                                 nic_dev->rx_buff_len;
     310                 :            :                 } else {
     311                 :          0 :                         rq_wqe->normal_wqe.buf_hi_addr =
     312                 :          0 :                                 hinic3_hw_be32(upper_32_bits(dma_addr));
     313                 :          0 :                         rq_wqe->normal_wqe.buf_lo_addr =
     314                 :          0 :                                 hinic3_hw_be32(lower_32_bits(dma_addr));
     315                 :            :                 }
     316                 :            : 
     317                 :          0 :                 rq_wqe =
     318                 :          0 :                         (struct hinic3_rq_wqe *)((uint64_t)rq_wqe + rxq->wqebb_size);
     319                 :            :         }
     320                 :          0 :         rxq->prod_idx += rearm_wqebbs;
     321                 :          0 :         rxq->delta -= rearm_wqebbs;
     322                 :            : 
     323                 :          0 :         hinic3_write_db(rxq->db_addr, rxq->q_id, 0, RQ_CFLAG_DP,
     324                 :          0 :                         ((pi + rearm_wqebbs) & rxq->q_mask) << rxq->wqe_type);
     325                 :          0 :         return 0;
     326                 :            : }
     327                 :            : 
     328                 :            : static int
     329                 :          0 : hinic3_init_rss_key(struct hinic3_nic_dev *nic_dev,
     330                 :            :                     struct rte_eth_rss_conf *rss_conf)
     331                 :            : {
     332                 :          0 :         uint8_t default_rss_key[HINIC3_RSS_KEY_SIZE] = {
     333                 :            :                          0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
     334                 :            :                          0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
     335                 :            :                          0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
     336                 :            :                          0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
     337                 :            :                          0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa};
     338                 :          0 :         uint8_t hashkey[HINIC3_RSS_KEY_SIZE] = {0};
     339                 :            :         int err;
     340                 :            : 
     341         [ #  # ]:          0 :         if (rss_conf->rss_key == NULL ||
     342         [ #  # ]:          0 :             rss_conf->rss_key_len > HINIC3_RSS_KEY_SIZE)
     343                 :            :                 memcpy(hashkey, default_rss_key, HINIC3_RSS_KEY_SIZE);
     344                 :            :         else
     345                 :          0 :                 memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len);
     346                 :            : 
     347                 :          0 :         err = hinic3_rss_set_hash_key(nic_dev->hwdev, hashkey, HINIC3_RSS_KEY_SIZE);
     348         [ #  # ]:          0 :         if (err)
     349                 :            :                 return err;
     350                 :            : 
     351                 :          0 :         memcpy(nic_dev->rss_key, hashkey, HINIC3_RSS_KEY_SIZE);
     352                 :          0 :         return 0;
     353                 :            : }
     354                 :            : 
     355                 :            : void
     356                 :          0 : hinic3_add_rq_to_rx_queue_list(struct hinic3_nic_dev *nic_dev, uint16_t queue_id)
     357                 :            : {
     358                 :          0 :         uint8_t rss_queue_count = nic_dev->num_rss;
     359                 :            : 
     360                 :            :         RTE_ASSERT(rss_queue_count <= (RTE_DIM(nic_dev->rx_queue_list) - 1));
     361                 :            : 
     362                 :          0 :         nic_dev->rx_queue_list[rss_queue_count] = (uint8_t)queue_id;
     363                 :          0 :         nic_dev->num_rss++;
     364                 :          0 : }
     365                 :            : 
     366                 :            : void
     367                 :          0 : hinic3_init_rx_queue_list(struct hinic3_nic_dev *nic_dev)
     368                 :            : {
     369                 :          0 :         nic_dev->num_rss = 0;
     370                 :          0 : }
     371                 :            : 
     372                 :            : static void
     373                 :          0 : hinic3_fill_indir_tbl(struct hinic3_nic_dev *nic_dev, uint32_t *indir_tbl)
     374                 :            : {
     375                 :          0 :         uint8_t rss_queue_count = nic_dev->num_rss;
     376                 :            :         int i = 0;
     377                 :            :         int j;
     378                 :            : 
     379         [ #  # ]:          0 :         if (rss_queue_count == 0) {
     380                 :            :                 /* Delete q_id from indir tbl. */
     381         [ #  # ]:          0 :                 for (i = 0; i < HINIC3_RSS_INDIR_SIZE; i++)
     382                 :            :                         /* Invalid value in indir tbl. */
     383                 :          0 :                         indir_tbl[i] = 0xFFFF;
     384                 :            :         } else {
     385         [ #  # ]:          0 :                 while (i < HINIC3_RSS_INDIR_SIZE)
     386   [ #  #  #  # ]:          0 :                         for (j = 0; (j < rss_queue_count) &&
     387                 :          0 :                                     (i < HINIC3_RSS_INDIR_SIZE); j++)
     388                 :          0 :                                 indir_tbl[i++] = nic_dev->rx_queue_list[j];
     389                 :            :         }
     390                 :          0 : }
     391                 :            : 
     392                 :            : int
     393                 :          0 : hinic3_refill_indir_rqid(struct hinic3_rxq *rxq)
     394                 :            : {
     395                 :          0 :         struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
     396                 :            :         uint32_t *indir_tbl;
     397                 :            :         int err;
     398                 :            : 
     399                 :          0 :         indir_tbl = rte_zmalloc(NULL, HINIC3_RSS_INDIR_SIZE * sizeof(uint32_t), 0);
     400         [ #  # ]:          0 :         if (!indir_tbl) {
     401                 :          0 :                 PMD_DRV_LOG(ERR,
     402                 :            :                             "Alloc indir_tbl mem failed, eth_dev:%s, queue_idx:%d",
     403                 :            :                             nic_dev->dev_name, rxq->q_id);
     404                 :          0 :                 return -ENOMEM;
     405                 :            :         }
     406                 :            : 
     407                 :            :         /* Build indir tbl according to the number of rss queue. */
     408                 :          0 :         hinic3_fill_indir_tbl(nic_dev, indir_tbl);
     409                 :            : 
     410                 :          0 :         err = hinic3_rss_set_indir_tbl(nic_dev->hwdev, indir_tbl,
     411                 :            :                                        HINIC3_RSS_INDIR_SIZE);
     412         [ #  # ]:          0 :         if (err) {
     413                 :          0 :                 PMD_DRV_LOG(ERR,
     414                 :            :                         "Set indirect table failed, eth_dev:%s, queue_idx:%d",
     415                 :            :                         nic_dev->dev_name, rxq->q_id);
     416                 :          0 :                 goto out;
     417                 :            :         }
     418                 :            : 
     419                 :          0 : out:
     420                 :          0 :         rte_free(indir_tbl);
     421                 :          0 :         return err;
     422                 :            : }
     423                 :            : 
     424                 :            : static int
     425                 :          0 : hinic3_init_rss_type(struct hinic3_nic_dev *nic_dev,
     426                 :            :                      struct rte_eth_rss_conf *rss_conf)
     427                 :            : {
     428                 :            :         struct hinic3_rss_type rss_type = {0};
     429                 :          0 :         uint64_t rss_hf = rss_conf->rss_hf;
     430                 :            :         int err;
     431                 :            : 
     432                 :          0 :         rss_type.ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0;
     433                 :          0 :         rss_type.tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0;
     434                 :          0 :         rss_type.ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0;
     435                 :          0 :         rss_type.ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0;
     436                 :          0 :         rss_type.tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0;
     437                 :          0 :         rss_type.tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0;
     438                 :          0 :         rss_type.udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0;
     439                 :          0 :         rss_type.udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0;
     440                 :            : 
     441                 :          0 :         err = hinic3_set_rss_type(nic_dev->hwdev, rss_type);
     442                 :          0 :         return err;
     443                 :            : }
     444                 :            : 
     445                 :            : int
     446                 :          0 : hinic3_update_rss_config(struct rte_eth_dev *dev,
     447                 :            :                          struct rte_eth_rss_conf *rss_conf)
     448                 :            : {
     449                 :          0 :         struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
     450                 :          0 :         uint8_t prio_tc[HINIC3_DCB_UP_MAX] = {0};
     451                 :            :         uint8_t num_tc = 0;
     452                 :            :         int err;
     453                 :            : 
     454         [ #  # ]:          0 :         if (rss_conf->rss_hf == 0) {
     455                 :          0 :                 rss_conf->rss_hf = HINIC3_RSS_OFFLOAD_ALL;
     456         [ #  # ]:          0 :         } else if ((rss_conf->rss_hf & HINIC3_RSS_OFFLOAD_ALL) == 0) {
     457                 :          0 :                 PMD_DRV_LOG(ERR, "Doesn't support rss hash type: %" PRIu64,
     458                 :            :                             rss_conf->rss_hf);
     459                 :          0 :                 return -EINVAL;
     460                 :            :         }
     461                 :            : 
     462                 :          0 :         err = hinic3_rss_template_alloc(nic_dev->hwdev);
     463         [ #  # ]:          0 :         if (err) {
     464                 :          0 :                 PMD_DRV_LOG(ERR, "Alloc rss template failed, err: %d", err);
     465                 :          0 :                 return err;
     466                 :            :         }
     467                 :            : 
     468                 :          0 :         err = hinic3_init_rss_key(nic_dev, rss_conf);
     469         [ #  # ]:          0 :         if (err) {
     470                 :          0 :                 PMD_DRV_LOG(ERR, "Init rss hash key failed, err: %d", err);
     471                 :          0 :                 goto init_rss_fail;
     472                 :            :         }
     473                 :            : 
     474                 :          0 :         err = hinic3_init_rss_type(nic_dev, rss_conf);
     475         [ #  # ]:          0 :         if (err) {
     476                 :          0 :                 PMD_DRV_LOG(ERR, "Init rss hash type failed, err: %d", err);
     477                 :          0 :                 goto init_rss_fail;
     478                 :            :         }
     479                 :            : 
     480                 :          0 :         err = hinic3_rss_set_hash_engine(nic_dev->hwdev,
     481                 :            :                                          HINIC3_RSS_HASH_ENGINE_TYPE_TOEP);
     482         [ #  # ]:          0 :         if (err) {
     483                 :          0 :                 PMD_DRV_LOG(ERR, "Init rss hash function failed, err: %d", err);
     484                 :          0 :                 goto init_rss_fail;
     485                 :            :         }
     486                 :            : 
     487                 :          0 :         err = hinic3_rss_cfg(nic_dev->hwdev, HINIC3_RSS_ENABLE, num_tc,
     488                 :            :                              prio_tc);
     489         [ #  # ]:          0 :         if (err) {
     490                 :          0 :                 PMD_DRV_LOG(ERR, "Enable rss failed, err: %d", err);
     491                 :          0 :                 goto init_rss_fail;
     492                 :            :         }
     493                 :            : 
     494                 :          0 :         nic_dev->rss_state = HINIC3_RSS_ENABLE;
     495                 :          0 :         return 0;
     496                 :            : 
     497                 :          0 : init_rss_fail:
     498         [ #  # ]:          0 :         if (hinic3_rss_template_free(nic_dev->hwdev))
     499                 :          0 :                 PMD_DRV_LOG(WARNING, "Free rss template failed");
     500                 :            : 
     501                 :            :         return err;
     502                 :            : }
     503                 :            : 
     504                 :            : /**
     505                 :            :  * Search given queue array to find position of given id.
     506                 :            :  * Return queue pos or queue_count if not found.
     507                 :            :  */
     508                 :            : static uint8_t
     509                 :            : hinic3_find_queue_pos_by_rq_id(uint8_t *queues, uint8_t queues_count, uint8_t queue_id)
     510                 :            : {
     511                 :            :         uint8_t pos;
     512                 :            : 
     513         [ #  # ]:          0 :         for (pos = 0; pos < queues_count; pos++) {
     514         [ #  # ]:          0 :                 if (queue_id == queues[pos])
     515                 :            :                         break;
     516                 :            :         }
     517                 :            : 
     518                 :            :         return pos;
     519                 :            : }
     520                 :            : 
     521                 :            : void
     522                 :          0 : hinic3_remove_rq_from_rx_queue_list(struct hinic3_nic_dev *nic_dev,
     523                 :            :                                     uint16_t queue_id)
     524                 :            : {
     525                 :            :         uint8_t queue_pos;
     526                 :          0 :         uint8_t rss_queue_count = nic_dev->num_rss;
     527                 :            : 
     528                 :          0 :         queue_pos = hinic3_find_queue_pos_by_rq_id(nic_dev->rx_queue_list,
     529                 :            :                                                    rss_queue_count, queue_id);
     530                 :            :         /*
     531                 :            :          * If queue was not at the end of the list,
     532                 :            :          * shift started queues up queue array list.
     533                 :            :          */
     534         [ #  # ]:          0 :         if (queue_pos < rss_queue_count) {
     535                 :          0 :                 rss_queue_count--;
     536                 :          0 :                 memmove(nic_dev->rx_queue_list + queue_pos,
     537                 :          0 :                         nic_dev->rx_queue_list + queue_pos + 1,
     538                 :          0 :                         (rss_queue_count - queue_pos) *
     539                 :            :                                 sizeof(nic_dev->rx_queue_list[0]));
     540                 :            :         }
     541                 :            : 
     542                 :            :         RTE_ASSERT(rss_queue_count < RTE_DIM(nic_dev->rx_queue_list));
     543                 :          0 :         nic_dev->num_rss = rss_queue_count;
     544                 :          0 : }
     545                 :            : 
     546                 :            : static void
     547                 :          0 : hinic3_rx_queue_release_mbufs(struct hinic3_rxq *rxq)
     548                 :            : {
     549                 :            :         uint16_t sw_ci, ci_mask, free_wqebbs;
     550                 :            :         uint16_t rx_buf_len;
     551                 :            :         uint32_t vlan_len, pkt_len;
     552                 :            :         RTE_ATOMIC(uint32_t)status;
     553                 :            :         uint32_t pkt_left_len = 0;
     554                 :            :         uint32_t nr_released = 0;
     555                 :            :         struct hinic3_rx_info *rx_info;
     556                 :            :         volatile struct hinic3_rq_cqe *rx_cqe;
     557                 :            : 
     558                 :            :         sw_ci = hinic3_get_rq_local_ci(rxq);
     559                 :          0 :         rx_info = &rxq->rx_info[sw_ci];
     560                 :          0 :         rx_cqe = &rxq->rx_cqe[sw_ci];
     561                 :            :         free_wqebbs = hinic3_get_rq_free_wqebb(rxq) + 1;
     562                 :          0 :         status = rx_cqe->status;
     563                 :            :         ci_mask = rxq->q_mask;
     564                 :            : 
     565         [ #  # ]:          0 :         while (free_wqebbs < rxq->q_depth) {
     566                 :          0 :                 rx_buf_len = rxq->buf_len;
     567         [ #  # ]:          0 :                 if (pkt_left_len != 0) {
     568                 :            :                         /* Flush continues jumbo rqe. */
     569                 :          0 :                         pkt_left_len = (pkt_left_len <= rx_buf_len)
     570         [ #  # ]:          0 :                                                ? 0 : (pkt_left_len - rx_buf_len);
     571         [ #  # ]:          0 :                 } else if (HINIC3_GET_RX_FLUSH(status)) {
     572                 :            :                         /* Flush one released rqe. */
     573                 :            :                         pkt_left_len = 0;
     574         [ #  # ]:          0 :                 } else if (HINIC3_GET_RX_DONE(status)) {
     575                 :            :                         /* Flush single packet or first jumbo rqe. */
     576                 :          0 :                         vlan_len = hinic3_hw_cpu32(rx_cqe->vlan_len);
     577                 :          0 :                         pkt_len = HINIC3_GET_RX_PKT_LEN(vlan_len);
     578                 :          0 :                         pkt_left_len = (pkt_len <= rx_buf_len)
     579         [ #  # ]:          0 :                                                ? 0 : (pkt_len - rx_buf_len);
     580                 :            :                 } else {
     581                 :            :                         break;
     582                 :            :                 }
     583                 :          0 :                 rte_pktmbuf_free(rx_info->mbuf);
     584                 :            : 
     585                 :          0 :                 rx_info->mbuf = NULL;
     586                 :          0 :                 rx_cqe->status = 0;
     587                 :          0 :                 nr_released++;
     588                 :          0 :                 free_wqebbs++;
     589                 :            : 
     590                 :            :                 /* Update ci to next cqe. */
     591                 :          0 :                 sw_ci++;
     592                 :          0 :                 sw_ci &= ci_mask;
     593                 :          0 :                 rx_info = &rxq->rx_info[sw_ci];
     594                 :          0 :                 rx_cqe = &rxq->rx_cqe[sw_ci];
     595                 :          0 :                 status = rx_cqe->status;
     596                 :            :         }
     597                 :            : 
     598                 :          0 :         hinic3_update_rq_local_ci(rxq, nr_released);
     599                 :          0 : }
     600                 :            : 
     601                 :            : int
     602                 :          0 : hinic3_poll_rq_empty(struct hinic3_rxq *rxq)
     603                 :            : {
     604                 :            :         uint64_t end;
     605                 :            :         int free_wqebb;
     606                 :            :         int err = -EFAULT;
     607                 :            : 
     608                 :          0 :         end = msecs_to_cycles(HINIC3_FLUSH_QUEUE_TIMEOUT) + cycles;
     609                 :            :         do {
     610                 :          0 :                 free_wqebb = hinic3_get_rq_free_wqebb(rxq) + 1;
     611         [ #  # ]:          0 :                 if (free_wqebb == rxq->q_depth) {
     612                 :            :                         err = 0;
     613                 :            :                         break;
     614                 :            :                 }
     615                 :          0 :                 hinic3_rx_queue_release_mbufs(rxq);
     616                 :          0 :                 rte_delay_us(1);
     617         [ #  # ]:          0 :         } while (time_before(cycles, end));
     618                 :            : 
     619                 :          0 :         return err;
     620                 :            : }
     621                 :            : 
     622                 :            : void
     623                 :          0 : hinic3_dump_cqe_status(struct hinic3_rxq *rxq, uint32_t *cqe_done_cnt,
     624                 :            :                        uint32_t *cqe_hole_cnt, uint32_t *head_ci, uint32_t *head_done)
     625                 :            : {
     626                 :            :         uint16_t sw_ci;
     627                 :            :         uint16_t avail_pkts = 0;
     628                 :            :         uint16_t hit_done = 0;
     629                 :            :         uint16_t cqe_hole = 0;
     630                 :            :         RTE_ATOMIC(uint32_t)status;
     631                 :            :         volatile struct hinic3_rq_cqe *rx_cqe;
     632                 :            : 
     633                 :            :         sw_ci = hinic3_get_rq_local_ci(rxq);
     634                 :          0 :         rx_cqe = &rxq->rx_cqe[sw_ci];
     635                 :          0 :         status = rx_cqe->status;
     636                 :          0 :         *head_done = HINIC3_GET_RX_DONE(status);
     637                 :          0 :         *head_ci = sw_ci;
     638                 :            : 
     639         [ #  # ]:          0 :         for (sw_ci = 0; sw_ci < rxq->q_depth; sw_ci++) {
     640                 :          0 :                 rx_cqe = &rxq->rx_cqe[sw_ci];
     641                 :            : 
     642                 :            :                 /* Check current ci is done. */
     643                 :          0 :                 status = rx_cqe->status;
     644         [ #  # ]:          0 :                 if (!HINIC3_GET_RX_DONE(status) ||
     645         [ #  # ]:          0 :                     !HINIC3_GET_RX_FLUSH(status)) {
     646         [ #  # ]:          0 :                         if (hit_done) {
     647                 :          0 :                                 cqe_hole++;
     648                 :            :                                 hit_done = 0;
     649                 :            :                         }
     650                 :            : 
     651                 :          0 :                         continue;
     652                 :            :                 }
     653                 :            : 
     654                 :          0 :                 avail_pkts++;
     655                 :            :                 hit_done = 1;
     656                 :            :         }
     657                 :            : 
     658                 :          0 :         *cqe_done_cnt = avail_pkts;
     659                 :          0 :         *cqe_hole_cnt = cqe_hole;
     660                 :          0 : }
     661                 :            : 
     662                 :            : int
     663                 :          0 : hinic3_stop_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq)
     664                 :            : {
     665                 :          0 :         struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
     666                 :          0 :         uint32_t cqe_done_cnt = 0;
     667                 :          0 :         uint32_t cqe_hole_cnt = 0;
     668                 :            :         uint32_t head_ci, head_done;
     669                 :            :         int err;
     670                 :            : 
     671                 :            :         /* Disable rxq intr. */
     672                 :          0 :         hinic3_dev_rx_queue_intr_disable(eth_dev, rxq->q_id);
     673                 :            : 
     674                 :            :         /* Lock dev queue switch. */
     675                 :          0 :         rte_spinlock_lock(&nic_dev->queue_list_lock);
     676                 :            : 
     677         [ #  # ]:          0 :         if (nic_dev->num_rss == 1) {
     678                 :          0 :                 err = hinic3_set_vport_enable(nic_dev->hwdev, false);
     679         [ #  # ]:          0 :                 if (err) {
     680                 :          0 :                         PMD_DRV_LOG(ERR, "%s Disable vport failed, rc:%d",
     681                 :            :                                     nic_dev->dev_name, err);
     682                 :            :                 }
     683                 :            :         }
     684                 :          0 :         hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id);
     685                 :            : 
     686                 :            :         /*
     687                 :            :          * If RSS is enable, remove q_id from rss indir table.
     688                 :            :          * If RSS is disable, no mbuf in rq, packet will be dropped.
     689                 :            :          */
     690         [ #  # ]:          0 :         if (nic_dev->rss_state == HINIC3_RSS_ENABLE) {
     691                 :          0 :                 err = hinic3_refill_indir_rqid(rxq);
     692         [ #  # ]:          0 :                 if (err) {
     693                 :          0 :                         PMD_DRV_LOG(ERR,
     694                 :            :                                     "Clear rq in indirect table failed, eth_dev:%s, queue_idx:%d",
     695                 :            :                                     nic_dev->dev_name, rxq->q_id);
     696                 :          0 :                         hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
     697                 :          0 :                         goto set_indir_failed;
     698                 :            :                 }
     699                 :            :         }
     700                 :            : 
     701                 :            :         /* Unlock dev queue list switch. */
     702                 :            :         rte_spinlock_unlock(&nic_dev->queue_list_lock);
     703                 :            : 
     704                 :            :         /* Send flush rxq cmd to device. */
     705                 :          0 :         err = hinic3_set_rq_flush(nic_dev->hwdev, rxq->q_id);
     706         [ #  # ]:          0 :         if (err) {
     707                 :          0 :                 PMD_DRV_LOG(ERR, "Flush rq failed, eth_dev:%s, queue_idx:%d",
     708                 :            :                             nic_dev->dev_name, rxq->q_id);
     709                 :          0 :                 goto rq_flush_failed;
     710                 :            :         }
     711                 :            : 
     712                 :          0 :         err = hinic3_poll_rq_empty(rxq);
     713         [ #  # ]:          0 :         if (err) {
     714                 :          0 :                 hinic3_dump_cqe_status(rxq, &cqe_done_cnt, &cqe_hole_cnt,
     715                 :            :                                        &head_ci, &head_done);
     716                 :          0 :                 PMD_DRV_LOG(ERR, "Poll rq empty timeout");
     717                 :          0 :                 PMD_DRV_LOG(ERR,
     718                 :            :                             "eth_dev:%s, queue_idx:%d, mbuf_left:%d, cqe_done:%d, cqe_hole:%d, cqe[%d].done=%d",
     719                 :            :                             nic_dev->dev_name, rxq->q_id,
     720                 :            :                             rxq->q_depth - hinic3_get_rq_free_wqebb(rxq),
     721                 :            :                             cqe_done_cnt, cqe_hole_cnt, head_ci, head_done);
     722                 :          0 :                 goto poll_rq_failed;
     723                 :            :         }
     724                 :            : 
     725                 :            :         return 0;
     726                 :            : 
     727                 :            : poll_rq_failed:
     728                 :          0 : rq_flush_failed:
     729                 :            :         rte_spinlock_lock(&nic_dev->queue_list_lock);
     730                 :          0 : set_indir_failed:
     731                 :          0 :         hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
     732         [ #  # ]:          0 :         if (nic_dev->rss_state == HINIC3_RSS_ENABLE)
     733                 :          0 :                 hinic3_refill_indir_rqid(rxq);
     734                 :            :         rte_spinlock_unlock(&nic_dev->queue_list_lock);
     735                 :          0 :         hinic3_dev_rx_queue_intr_enable(eth_dev, rxq->q_id);
     736                 :          0 :         return err;
     737                 :            : }
     738                 :            : 
     739                 :            : int
     740                 :          0 : hinic3_start_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq)
     741                 :            : {
     742                 :          0 :         struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
     743                 :            :         int err = 0;
     744                 :            : 
     745                 :            :         /* Lock dev queue switch.  */
     746                 :          0 :         rte_spinlock_lock(&nic_dev->queue_list_lock);
     747                 :          0 :         hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
     748                 :            : 
     749         [ #  # ]:          0 :         if (nic_dev->rss_state == HINIC3_RSS_ENABLE) {
     750                 :          0 :                 err = hinic3_refill_indir_rqid(rxq);
     751         [ #  # ]:          0 :                 if (err) {
     752                 :          0 :                         PMD_DRV_LOG(ERR,
     753                 :            :                                     "Refill rq to indirect table failed, eth_dev:%s, queue_idx:%d err:%d",
     754                 :            :                                     nic_dev->dev_name, rxq->q_id, err);
     755                 :          0 :                         hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id);
     756                 :            :                 }
     757                 :            :         }
     758                 :          0 :         hinic3_rearm_rxq_mbuf(rxq);
     759         [ #  # ]:          0 :         if (rxq->nic_dev->num_rss == 1) {
     760                 :          0 :                 err = hinic3_set_vport_enable(nic_dev->hwdev, true);
     761         [ #  # ]:          0 :                 if (err)
     762                 :          0 :                         PMD_DRV_LOG(ERR, "%s enable vport failed, err:%d",
     763                 :            :                                     nic_dev->dev_name, err);
     764                 :            :         }
     765                 :            : 
     766                 :            :         /* Unlock dev queue list switch. */
     767                 :            :         rte_spinlock_unlock(&nic_dev->queue_list_lock);
     768                 :            : 
     769                 :          0 :         hinic3_dev_rx_queue_intr_enable(eth_dev, rxq->q_id);
     770                 :            : 
     771                 :          0 :         return err;
     772                 :            : }
     773                 :            : 
     774                 :            : 
     775                 :            : static inline uint64_t
     776                 :            : hinic3_rx_vlan(uint32_t offload_type, uint32_t vlan_len, uint16_t *vlan_tci)
     777                 :            : {
     778                 :            :         uint16_t vlan_tag;
     779                 :            : 
     780                 :          0 :         vlan_tag = HINIC3_GET_RX_VLAN_TAG(vlan_len);
     781         [ #  # ]:          0 :         if (!HINIC3_GET_RX_VLAN_OFFLOAD_EN(offload_type) || vlan_tag == 0) {
     782                 :          0 :                 *vlan_tci = 0;
     783                 :          0 :                 return 0;
     784                 :            :         }
     785                 :            : 
     786                 :          0 :         *vlan_tci = vlan_tag;
     787                 :            : 
     788                 :          0 :         return HINIC3_PKT_RX_VLAN | HINIC3_PKT_RX_VLAN_STRIPPED;
     789                 :            : }
     790                 :            : 
     791                 :            : static inline uint64_t
     792                 :          0 : hinic3_rx_csum(uint32_t status, struct hinic3_rxq *rxq)
     793                 :            : {
     794                 :          0 :         struct hinic3_nic_dev *nic_dev = rxq->nic_dev;
     795                 :            :         uint32_t csum_err;
     796                 :            :         uint64_t flags;
     797                 :            : 
     798         [ #  # ]:          0 :         if (unlikely(!(nic_dev->rx_csum_en & HINIC3_DEFAULT_RX_CSUM_OFFLOAD)))
     799                 :            :                 return HINIC3_PKT_RX_IP_CKSUM_UNKNOWN;
     800                 :            : 
     801                 :          0 :         csum_err = HINIC3_GET_RX_CSUM_ERR(status);
     802         [ #  # ]:          0 :         if (likely(csum_err == 0))
     803                 :            :                 return (HINIC3_PKT_RX_IP_CKSUM_GOOD |
     804                 :            :                         HINIC3_PKT_RX_L4_CKSUM_GOOD);
     805                 :            : 
     806                 :            :         /*
     807                 :            :          * If bypass bit is set, all other err status indications should be
     808                 :            :          * ignored.
     809                 :            :          */
     810         [ #  # ]:          0 :         if (unlikely(csum_err & HINIC3_RX_CSUM_HW_CHECK_NONE))
     811                 :            :                 return HINIC3_PKT_RX_IP_CKSUM_UNKNOWN;
     812                 :            : 
     813                 :            :         flags = 0;
     814                 :            : 
     815                 :            :         /* IP checksum error. */
     816         [ #  # ]:          0 :         if (csum_err & HINIC3_RX_CSUM_IP_CSUM_ERR) {
     817                 :            :                 flags |= HINIC3_PKT_RX_IP_CKSUM_BAD;
     818                 :          0 :                 rxq->rxq_stats.csum_errors++;
     819                 :            :         }
     820                 :            : 
     821                 :            :         /* L4 checksum error. */
     822                 :          0 :         if ((csum_err & HINIC3_RX_CSUM_TCP_CSUM_ERR) ||
     823         [ #  # ]:          0 :             (csum_err & HINIC3_RX_CSUM_UDP_CSUM_ERR) ||
     824                 :            :             (csum_err & HINIC3_RX_CSUM_SCTP_CRC_ERR)) {
     825                 :          0 :                 flags |= HINIC3_PKT_RX_L4_CKSUM_BAD;
     826                 :          0 :                 rxq->rxq_stats.csum_errors++;
     827                 :            :         }
     828                 :            : 
     829         [ #  # ]:          0 :         if (unlikely(csum_err == HINIC3_RX_CSUM_IPSU_OTHER_ERR))
     830                 :          0 :                 rxq->rxq_stats.other_errors++;
     831                 :            : 
     832                 :            :         return flags;
     833                 :            : }
     834                 :            : 
     835                 :            : static inline uint64_t
     836                 :            : hinic3_rx_rss_hash(uint32_t offload_type, uint32_t rss_hash_value, uint32_t *rss_hash)
     837                 :            : {
     838                 :            :         uint32_t rss_type;
     839                 :            : 
     840                 :          0 :         rss_type = HINIC3_GET_RSS_TYPES(offload_type);
     841                 :          0 :         if (likely(rss_type != 0)) {
     842                 :          0 :                 *rss_hash = rss_hash_value;
     843                 :          0 :                 return HINIC3_PKT_RX_RSS_HASH;
     844                 :            :         }
     845                 :            : 
     846                 :            :         return 0;
     847                 :            : }
     848                 :            : 
     849                 :            : static void
     850                 :          0 : hinic3_recv_jumbo_pkt(struct hinic3_rxq *rxq, struct rte_mbuf *head_mbuf,
     851                 :            :                       uint32_t remain_pkt_len)
     852                 :            : {
     853                 :            :         struct rte_mbuf *cur_mbuf = NULL;
     854                 :            :         struct rte_mbuf *rxm = NULL;
     855                 :            :         struct hinic3_rx_info *rx_info = NULL;
     856                 :          0 :         uint16_t sw_ci, rx_buf_len = rxq->buf_len;
     857                 :            :         uint32_t pkt_len;
     858                 :            : 
     859         [ #  # ]:          0 :         while (remain_pkt_len > 0) {
     860                 :            :                 sw_ci = hinic3_get_rq_local_ci(rxq);
     861         [ #  # ]:          0 :                 rx_info = &rxq->rx_info[sw_ci];
     862                 :            : 
     863                 :            :                 hinic3_update_rq_local_ci(rxq, 1);
     864                 :            : 
     865                 :          0 :                 pkt_len = remain_pkt_len > rx_buf_len ? rx_buf_len
     866                 :          0 :                                                       : remain_pkt_len;
     867                 :          0 :                 remain_pkt_len -= pkt_len;
     868                 :            : 
     869                 :          0 :                 cur_mbuf = rx_info->mbuf;
     870                 :          0 :                 cur_mbuf->data_len = (uint16_t)pkt_len;
     871                 :          0 :                 cur_mbuf->next = NULL;
     872                 :            : 
     873                 :          0 :                 head_mbuf->pkt_len += cur_mbuf->data_len;
     874                 :          0 :                 head_mbuf->nb_segs++;
     875                 :            : #ifdef HINIC3_XSTAT_MBUF_USE
     876                 :            :                 rxq->rxq_stats.rx_free_mbuf_bytes++;
     877                 :            : #endif
     878         [ #  # ]:          0 :                 if (!rxm)
     879                 :          0 :                         head_mbuf->next = cur_mbuf;
     880                 :            :                 else
     881                 :          0 :                         rxm->next = cur_mbuf;
     882                 :            : 
     883                 :            :                 rxm = cur_mbuf;
     884                 :            :         }
     885                 :          0 : }
     886                 :            : 
     887                 :            : int
     888                 :          0 : hinic3_start_all_rqs(struct rte_eth_dev *eth_dev)
     889                 :            : {
     890                 :            :         struct hinic3_nic_dev *nic_dev = NULL;
     891                 :            :         struct hinic3_rxq *rxq = NULL;
     892                 :            :         int err = 0;
     893                 :            :         int i;
     894                 :            : 
     895                 :          0 :         nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
     896                 :            : 
     897         [ #  # ]:          0 :         for (i = 0; i < nic_dev->num_rqs; i++) {
     898                 :          0 :                 rxq = eth_dev->data->rx_queues[i];
     899                 :          0 :                 hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id);
     900                 :          0 :                 err = hinic3_rearm_rxq_mbuf(rxq);
     901         [ #  # ]:          0 :                 if (err) {
     902                 :          0 :                         PMD_DRV_LOG(ERR,
     903                 :            :                                     "Fail to alloc mbuf for Rx queue %d, qid = %u, need_mbuf: %d",
     904                 :            :                                     i, rxq->q_id, rxq->q_depth);
     905                 :          0 :                         goto out;
     906                 :            :                 }
     907                 :          0 :                 hinic3_dev_rx_queue_intr_enable(eth_dev, rxq->q_id);
     908         [ #  # ]:          0 :                 if (rxq->rx_deferred_start)
     909                 :          0 :                         continue;
     910                 :          0 :                 eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
     911                 :            :         }
     912                 :            : 
     913         [ #  # ]:          0 :         if (nic_dev->rss_state == HINIC3_RSS_ENABLE) {
     914                 :          0 :                 err = hinic3_refill_indir_rqid(rxq);
     915         [ #  # ]:          0 :                 if (err) {
     916                 :          0 :                         PMD_DRV_LOG(ERR,
     917                 :            :                                     "Refill rq to indirect table failed, eth_dev:%s, queue_idx:%d, err:%d",
     918                 :            :                                     rxq->nic_dev->dev_name, rxq->q_id, err);
     919                 :          0 :                         goto out;
     920                 :            :                 }
     921                 :            :         }
     922                 :            : 
     923                 :            :         return 0;
     924                 :          0 : out:
     925         [ #  # ]:          0 :         for (i = 0; i < nic_dev->num_rqs; i++) {
     926                 :          0 :                 rxq = eth_dev->data->rx_queues[i];
     927                 :          0 :                 hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id);
     928                 :          0 :                 hinic3_free_rxq_mbufs(rxq);
     929                 :          0 :                 hinic3_dev_rx_queue_intr_disable(eth_dev, rxq->q_id);
     930                 :          0 :                 eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
     931                 :            :         }
     932                 :            :         return err;
     933                 :            : }
     934                 :            : 
     935                 :            : #define HINIC3_RX_EMPTY_THRESHOLD 3
     936                 :            : uint16_t
     937                 :          0 : hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
     938                 :            : {
     939                 :            :         struct hinic3_rxq *rxq = rx_queue;
     940                 :            :         struct hinic3_rx_info *rx_info = NULL;
     941                 :            :         volatile struct hinic3_rq_cqe *rx_cqe = NULL;
     942                 :            :         struct rte_mbuf *rxm = NULL;
     943                 :            :         uint16_t sw_ci, rx_buf_len, wqebb_cnt = 0, pkts = 0;
     944                 :            :         uint32_t status, pkt_len, vlan_len, offload_type, lro_num;
     945                 :            :         uint64_t rx_bytes = 0;
     946                 :            :         uint32_t hash_value;
     947                 :            : 
     948                 :            : #ifdef HINIC3_XSTAT_PROF_RX
     949                 :            :         uint64_t t1 = rte_get_tsc_cycles();
     950                 :            :         uint64_t t2;
     951                 :            : #endif
     952         [ #  # ]:          0 :         if (((rte_get_timer_cycles() - rxq->rxq_stats.tsc) < rxq->wait_time_cycle) &&
     953         [ #  # ]:          0 :             rxq->rxq_stats.empty >= HINIC3_RX_EMPTY_THRESHOLD)
     954                 :          0 :                 goto out;
     955                 :            : 
     956                 :            :         sw_ci = hinic3_get_rq_local_ci(rxq);
     957                 :          0 :         rx_buf_len = rxq->buf_len;
     958                 :            : 
     959         [ #  # ]:          0 :         while (pkts < nb_pkts) {
     960                 :          0 :                 rx_cqe = &rxq->rx_cqe[sw_ci];
     961                 :          0 :                 status = hinic3_hw_cpu32((uint32_t)(rte_atomic_load_explicit(&rx_cqe->status,
     962                 :            :                         rte_memory_order_acquire)));
     963         [ #  # ]:          0 :                 if (!HINIC3_GET_RX_DONE(status)) {
     964                 :          0 :                         rxq->rxq_stats.empty++;
     965                 :          0 :                         break;
     966                 :            :                 }
     967                 :            : 
     968                 :          0 :                 vlan_len = hinic3_hw_cpu32(rx_cqe->vlan_len);
     969                 :            : 
     970                 :          0 :                 pkt_len = HINIC3_GET_RX_PKT_LEN(vlan_len);
     971                 :            : 
     972                 :          0 :                 rx_info = &rxq->rx_info[sw_ci];
     973                 :          0 :                 rxm = rx_info->mbuf;
     974                 :            : 
     975                 :            :                 /* 1. Next ci point and prefetch. */
     976                 :          0 :                 sw_ci++;
     977                 :          0 :                 sw_ci &= rxq->q_mask;
     978                 :            : 
     979                 :            :                 /* 2. Prefetch next mbuf first 64B. */
     980                 :          0 :                 rte_prefetch0(rxq->rx_info[sw_ci].mbuf);
     981                 :            : 
     982                 :            :                 /* 3. Jumbo frame process. */
     983         [ #  # ]:          0 :                 if (likely(pkt_len <= rx_buf_len)) {
     984                 :          0 :                         rxm->data_len = (uint16_t)pkt_len;
     985                 :          0 :                         rxm->pkt_len = pkt_len;
     986                 :          0 :                         wqebb_cnt++;
     987                 :            :                 } else {
     988                 :          0 :                         rxm->data_len = rx_buf_len;
     989                 :          0 :                         rxm->pkt_len = rx_buf_len;
     990                 :            : 
     991                 :            :                         /*
     992                 :            :                          * If receive jumbo, updating ci will be done by
     993                 :            :                          * hinic3_recv_jumbo_pkt function.
     994                 :            :                          */
     995                 :          0 :                         hinic3_update_rq_local_ci(rxq, wqebb_cnt + 1);
     996                 :            :                         wqebb_cnt = 0;
     997                 :          0 :                         hinic3_recv_jumbo_pkt(rxq, rxm, pkt_len - rx_buf_len);
     998                 :            :                         sw_ci = hinic3_get_rq_local_ci(rxq);
     999                 :            :                 }
    1000                 :            : 
    1001                 :          0 :                 rxm->data_off = RTE_PKTMBUF_HEADROOM;
    1002                 :          0 :                 rxm->port = rxq->port_id;
    1003                 :            : 
    1004                 :            :                 /* 4. Rx checksum offload. */
    1005                 :          0 :                 rxm->ol_flags |= hinic3_rx_csum(status, rxq);
    1006                 :            : 
    1007                 :            :                 /* 5. Vlan offload. */
    1008         [ #  # ]:          0 :                 offload_type = hinic3_hw_cpu32(rx_cqe->offload_type);
    1009                 :            : 
    1010                 :          0 :                 rxm->ol_flags |=
    1011                 :            :                         hinic3_rx_vlan(offload_type, vlan_len, &rxm->vlan_tci);
    1012                 :            : 
    1013                 :            :                 /* 6. RSS. */
    1014         [ #  # ]:          0 :                 hash_value = hinic3_hw_cpu32(rx_cqe->hash_val);
    1015                 :          0 :                 rxm->ol_flags |= hinic3_rx_rss_hash(offload_type, hash_value,
    1016                 :            :                                                     &rxm->hash.rss);
    1017                 :            :                 /* 8. LRO. */
    1018                 :          0 :                 lro_num = HINIC3_GET_RX_NUM_LRO(status);
    1019         [ #  # ]:          0 :                 if (unlikely(lro_num != 0)) {
    1020                 :          0 :                         rxm->ol_flags |= HINIC3_PKT_RX_LRO;
    1021                 :          0 :                         rxm->tso_segsz = pkt_len / lro_num;
    1022                 :            :                 }
    1023                 :            : 
    1024                 :          0 :                 rx_cqe->status = 0;
    1025                 :            : 
    1026                 :          0 :                 rx_bytes += pkt_len;
    1027                 :          0 :                 rx_pkts[pkts++] = rxm;
    1028                 :            :         }
    1029                 :            : 
    1030         [ #  # ]:          0 :         if (pkts) {
    1031                 :            :                 /* 9. Update local ci. */
    1032                 :            :                 hinic3_update_rq_local_ci(rxq, wqebb_cnt);
    1033                 :            : 
    1034                 :            :                 /* Update packet stats. */
    1035                 :          0 :                 rxq->rxq_stats.packets += pkts;
    1036                 :          0 :                 rxq->rxq_stats.bytes += rx_bytes;
    1037                 :          0 :                 rxq->rxq_stats.empty = 0;
    1038                 :            : #ifdef HINIC3_XSTAT_MBUF_USE
    1039                 :            :                 rxq->rxq_stats.rx_free_mbuf_bytes += pkts;
    1040                 :            : #endif
    1041                 :            :         }
    1042                 :          0 :         rxq->rxq_stats.burst_pkts = pkts;
    1043                 :          0 :         rxq->rxq_stats.tsc = rte_get_timer_cycles();
    1044                 :          0 : out:
    1045                 :            :         /* 10. Rearm mbuf to rxq. */
    1046                 :          0 :         hinic3_rearm_rxq_mbuf(rxq);
    1047                 :            : 
    1048                 :            : #ifdef HINIC3_XSTAT_PROF_RX
    1049                 :            :         /* Do profiling stats. */
    1050                 :            :         t2 = rte_get_tsc_cycles();
    1051                 :            :         rxq->rxq_stats.app_tsc = t1 - rxq->prof_rx_end_tsc;
    1052                 :            :         rxq->prof_rx_end_tsc = t2;
    1053                 :            :         rxq->rxq_stats.pmd_tsc = t2 - t1;
    1054                 :            : #endif
    1055                 :            : 
    1056                 :          0 :         return pkts;
    1057                 :            : }

Generated by: LCOV version 1.14