LCOV - code coverage report
Current view: top level - drivers/net/zxdh - zxdh_queue.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 171 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 12 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 86 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2024 ZTE Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : #include <rte_malloc.h>
       7                 :            : #include <rte_mbuf.h>
       8                 :            : 
       9                 :            : #include "zxdh_queue.h"
      10                 :            : #include "zxdh_logs.h"
      11                 :            : #include "zxdh_pci.h"
      12                 :            : #include "zxdh_common.h"
      13                 :            : #include "zxdh_msg.h"
      14                 :            : 
      15                 :            : #define ZXDH_MBUF_MIN_SIZE       sizeof(struct zxdh_net_hdr_dl)
      16                 :            : #define ZXDH_MBUF_SIZE_4K             4096
      17                 :            : #define ZXDH_RX_FREE_THRESH           32
      18                 :            : #define ZXDH_TX_FREE_THRESH           32
      19                 :            : 
      20                 :            : struct rte_mbuf *
      21                 :          0 : zxdh_queue_detach_unused(struct zxdh_virtqueue *vq)
      22                 :            : {
      23                 :            :         struct rte_mbuf *cookie = NULL;
      24                 :            :         int32_t          idx    = 0;
      25                 :            : 
      26         [ #  # ]:          0 :         if (vq == NULL)
      27                 :            :                 return NULL;
      28                 :            : 
      29         [ #  # ]:          0 :         for (idx = 0; idx < vq->vq_nentries; idx++) {
      30                 :          0 :                 cookie = vq->vq_descx[idx].cookie;
      31         [ #  # ]:          0 :                 if (cookie != NULL) {
      32                 :          0 :                         vq->vq_descx[idx].cookie = NULL;
      33                 :          0 :                         return cookie;
      34                 :            :                 }
      35                 :            :         }
      36                 :            :         return NULL;
      37                 :            : }
      38                 :            : 
      39                 :            : static int32_t
      40                 :          0 : zxdh_release_channel(struct rte_eth_dev *dev)
      41                 :            : {
      42                 :          0 :         struct zxdh_hw *hw = dev->data->dev_private;
      43                 :          0 :         uint16_t nr_vq = hw->queue_num;
      44                 :            :         uint32_t var  = 0;
      45                 :            :         uint32_t addr = 0;
      46                 :            :         uint32_t widx = 0;
      47                 :            :         uint32_t bidx = 0;
      48                 :            :         uint16_t pch  = 0;
      49                 :            :         uint16_t lch  = 0;
      50                 :            :         int32_t ret = 0;
      51                 :            : 
      52                 :          0 :         ret = zxdh_timedlock(hw, 1000);
      53         [ #  # ]:          0 :         if (ret) {
      54                 :          0 :                 PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout");
      55                 :          0 :                 return -1;
      56                 :            :         }
      57                 :            : 
      58         [ #  # ]:          0 :         for (lch = 0; lch < nr_vq; lch++) {
      59         [ #  # ]:          0 :                 if (hw->channel_context[lch].valid == 0) {
      60                 :          0 :                         PMD_DRV_LOG(DEBUG, "Logic channel %d does not need to release", lch);
      61                 :          0 :                         continue;
      62                 :            :                 }
      63                 :            : 
      64                 :          0 :                 pch  = hw->channel_context[lch].ph_chno;
      65                 :          0 :                 widx = pch / 32;
      66                 :          0 :                 bidx = pch % 32;
      67                 :            : 
      68                 :          0 :                 addr = ZXDH_QUERES_SHARE_BASE + (widx * sizeof(uint32_t));
      69                 :          0 :                 var  = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);
      70                 :          0 :                 var &= ~(1 << bidx);
      71                 :          0 :                 zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);
      72                 :            : 
      73                 :          0 :                 hw->channel_context[lch].valid = 0;
      74                 :          0 :                 hw->channel_context[lch].ph_chno = 0;
      75                 :            :         }
      76                 :            : 
      77                 :          0 :         zxdh_release_lock(hw);
      78                 :            : 
      79                 :          0 :         return 0;
      80                 :            : }
      81                 :            : 
      82                 :            : int32_t
      83                 :          0 : zxdh_get_queue_type(uint16_t vtpci_queue_idx)
      84                 :            : {
      85         [ #  # ]:          0 :         if (vtpci_queue_idx % 2 == 0)
      86                 :            :                 return ZXDH_VTNET_RQ;
      87                 :            :         else
      88                 :          0 :                 return ZXDH_VTNET_TQ;
      89                 :            : }
      90                 :            : 
      91                 :            : int32_t
      92                 :          0 : zxdh_free_queues(struct rte_eth_dev *dev)
      93                 :            : {
      94                 :          0 :         struct zxdh_hw *hw = dev->data->dev_private;
      95                 :          0 :         uint16_t nr_vq = hw->queue_num;
      96                 :            :         struct zxdh_virtqueue *vq = NULL;
      97                 :            :         int32_t queue_type = 0;
      98                 :            :         uint16_t i = 0;
      99                 :            : 
     100         [ #  # ]:          0 :         if (hw->vqs == NULL)
     101                 :            :                 return 0;
     102                 :            : 
     103         [ #  # ]:          0 :         if (zxdh_release_channel(dev) < 0) {
     104                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to clear coi table");
     105                 :          0 :                 return -1;
     106                 :            :         }
     107                 :            : 
     108         [ #  # ]:          0 :         for (i = 0; i < nr_vq; i++) {
     109                 :          0 :                 vq = hw->vqs[i];
     110         [ #  # ]:          0 :                 if (vq == NULL)
     111                 :          0 :                         continue;
     112                 :            : 
     113                 :          0 :                 ZXDH_VTPCI_OPS(hw)->del_queue(hw, vq);
     114                 :          0 :                 queue_type = zxdh_get_queue_type(i);
     115         [ #  # ]:          0 :                 if (queue_type == ZXDH_VTNET_RQ) {
     116                 :          0 :                         rte_free(vq->sw_ring);
     117                 :          0 :                         rte_memzone_free(vq->rxq.mz);
     118         [ #  # ]:          0 :                 } else if (queue_type == ZXDH_VTNET_TQ) {
     119                 :          0 :                         rte_memzone_free(vq->txq.mz);
     120                 :          0 :                         rte_memzone_free(vq->txq.zxdh_net_hdr_mz);
     121                 :            :                 }
     122                 :            : 
     123                 :          0 :                 rte_free(vq);
     124                 :          0 :                 hw->vqs[i] = NULL;
     125                 :          0 :                 PMD_DRV_LOG(DEBUG, "Release to queue %d success!", i);
     126                 :            :         }
     127                 :            : 
     128                 :          0 :         rte_free(hw->vqs);
     129                 :          0 :         hw->vqs = NULL;
     130                 :            : 
     131                 :          0 :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :            : static int
     135                 :          0 : zxdh_check_mempool(struct rte_mempool *mp, uint16_t offset, uint16_t min_length)
     136                 :            : {
     137                 :            :         uint16_t data_room_size;
     138                 :            : 
     139         [ #  # ]:          0 :         if (mp == NULL)
     140                 :            :                 return -EINVAL;
     141                 :            :         data_room_size = rte_pktmbuf_data_room_size(mp);
     142         [ #  # ]:          0 :         if (data_room_size < offset + min_length) {
     143                 :          0 :                 PMD_RX_LOG(ERR,
     144                 :            :                                    "%s mbuf_data_room_size %u < %u (%u + %u)",
     145                 :            :                                    mp->name, data_room_size,
     146                 :            :                                    offset + min_length, offset, min_length);
     147                 :          0 :                 return -EINVAL;
     148                 :            :         }
     149                 :            :         return 0;
     150                 :            : }
     151                 :            : 
     152                 :            : int32_t
     153                 :          0 : zxdh_dev_rx_queue_setup(struct rte_eth_dev *dev,
     154                 :            :                         uint16_t queue_idx,
     155                 :            :                         uint16_t nb_desc,
     156                 :            :                         uint32_t socket_id __rte_unused,
     157                 :            :                         const struct rte_eth_rxconf *rx_conf,
     158                 :            :                         struct rte_mempool *mp)
     159                 :            : {
     160                 :          0 :         struct zxdh_hw *hw = dev->data->dev_private;
     161                 :          0 :         uint16_t vtpci_logic_qidx = 2 * queue_idx + ZXDH_RQ_QUEUE_IDX;
     162                 :          0 :         struct zxdh_virtqueue *vq = hw->vqs[vtpci_logic_qidx];
     163                 :            :         int32_t ret = 0;
     164                 :            : 
     165         [ #  # ]:          0 :         if (rx_conf->rx_deferred_start) {
     166                 :          0 :                 PMD_RX_LOG(ERR, "Rx deferred start is not supported");
     167                 :          0 :                 return -EINVAL;
     168                 :            :         }
     169                 :          0 :         uint16_t rx_free_thresh = rx_conf->rx_free_thresh;
     170                 :            : 
     171         [ #  # ]:          0 :         if (rx_free_thresh == 0)
     172                 :          0 :                 rx_free_thresh = RTE_MIN(vq->vq_nentries / 4, ZXDH_RX_FREE_THRESH);
     173                 :            : 
     174                 :            :         /* rx_free_thresh must be multiples of four. */
     175         [ #  # ]:          0 :         if (rx_free_thresh & 0x3) {
     176                 :          0 :                 PMD_RX_LOG(ERR, "(rx_free_thresh=%u port=%u queue=%u)",
     177                 :            :                         rx_free_thresh, dev->data->port_id, queue_idx);
     178                 :          0 :                 return -EINVAL;
     179                 :            :         }
     180                 :            :         /* rx_free_thresh must be less than the number of RX entries */
     181         [ #  # ]:          0 :         if (rx_free_thresh >= vq->vq_nentries) {
     182                 :          0 :                 PMD_RX_LOG(ERR, "RX entries (%u). (rx_free_thresh=%u port=%u queue=%u)",
     183                 :            :                         vq->vq_nentries, rx_free_thresh, dev->data->port_id, queue_idx);
     184                 :          0 :                 return -EINVAL;
     185                 :            :         }
     186                 :          0 :         vq->vq_free_thresh = rx_free_thresh;
     187                 :            :         nb_desc = ZXDH_QUEUE_DEPTH;
     188                 :            : 
     189                 :          0 :         vq->vq_free_cnt = RTE_MIN(vq->vq_free_cnt, nb_desc);
     190                 :          0 :         struct zxdh_virtnet_rx *rxvq = &vq->rxq;
     191                 :            : 
     192                 :          0 :         rxvq->queue_id = vtpci_logic_qidx;
     193                 :            : 
     194                 :            :         int mbuf_min_size  = ZXDH_MBUF_MIN_SIZE;
     195                 :            : 
     196         [ #  # ]:          0 :         if (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
     197                 :            :                 mbuf_min_size = ZXDH_MBUF_SIZE_4K;
     198                 :            : 
     199                 :          0 :         ret = zxdh_check_mempool(mp, RTE_PKTMBUF_HEADROOM, mbuf_min_size);
     200         [ #  # ]:          0 :         if (ret != 0) {
     201                 :          0 :                 PMD_RX_LOG(ERR,
     202                 :            :                         "rxq setup but mpool size too small(<%d) failed", mbuf_min_size);
     203                 :          0 :                 return -EINVAL;
     204                 :            :         }
     205                 :          0 :         rxvq->mpool = mp;
     206         [ #  # ]:          0 :         if (queue_idx < dev->data->nb_rx_queues)
     207                 :          0 :                 dev->data->rx_queues[queue_idx] = rxvq;
     208                 :            : 
     209                 :            :         return 0;
     210                 :            : }
     211                 :            : 
     212                 :            : int32_t
     213                 :          0 : zxdh_dev_tx_queue_setup(struct rte_eth_dev *dev,
     214                 :            :                         uint16_t queue_idx,
     215                 :            :                         uint16_t nb_desc,
     216                 :            :                         uint32_t socket_id __rte_unused,
     217                 :            :                         const struct rte_eth_txconf *tx_conf)
     218                 :            : {
     219                 :          0 :         uint16_t vtpci_logic_qidx = 2 * queue_idx + ZXDH_TQ_QUEUE_IDX;
     220                 :          0 :         struct zxdh_hw *hw = dev->data->dev_private;
     221                 :          0 :         struct zxdh_virtqueue *vq = hw->vqs[vtpci_logic_qidx];
     222                 :            :         struct zxdh_virtnet_tx *txvq = NULL;
     223                 :            :         uint16_t tx_free_thresh = 0;
     224                 :            : 
     225         [ #  # ]:          0 :         if (tx_conf->tx_deferred_start) {
     226                 :          0 :                 PMD_TX_LOG(ERR, "Tx deferred start is not supported");
     227                 :          0 :                 return -EINVAL;
     228                 :            :         }
     229                 :            : 
     230                 :            :         nb_desc = ZXDH_QUEUE_DEPTH;
     231                 :            : 
     232                 :          0 :         vq->vq_free_cnt = RTE_MIN(vq->vq_free_cnt, nb_desc);
     233                 :            : 
     234                 :          0 :         txvq = &vq->txq;
     235                 :          0 :         txvq->queue_id = vtpci_logic_qidx;
     236                 :            : 
     237                 :          0 :         tx_free_thresh = tx_conf->tx_free_thresh;
     238         [ #  # ]:          0 :         if (tx_free_thresh == 0)
     239                 :          0 :                 tx_free_thresh = RTE_MIN(vq->vq_nentries / 4, ZXDH_TX_FREE_THRESH);
     240                 :            : 
     241                 :            :         /* tx_free_thresh must be less than the number of TX entries minus 3 */
     242         [ #  # ]:          0 :         if (tx_free_thresh >= (vq->vq_nentries - 3)) {
     243                 :          0 :                 PMD_TX_LOG(ERR, "TX entries - 3 (%u). (tx_free_thresh=%u port=%u queue=%u)",
     244                 :            :                                 vq->vq_nentries - 3, tx_free_thresh, dev->data->port_id, queue_idx);
     245                 :          0 :                 return -EINVAL;
     246                 :            :         }
     247                 :            : 
     248                 :          0 :         vq->vq_free_thresh = tx_free_thresh;
     249                 :            : 
     250         [ #  # ]:          0 :         if (queue_idx < dev->data->nb_tx_queues)
     251                 :          0 :                 dev->data->tx_queues[queue_idx] = txvq;
     252                 :            : 
     253                 :            :         return 0;
     254                 :            : }
     255                 :            : 
     256                 :            : int32_t
     257                 :          0 : zxdh_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
     258                 :            : {
     259                 :          0 :         struct zxdh_hw *hw = dev->data->dev_private;
     260                 :          0 :         struct zxdh_virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
     261         [ #  # ]:          0 :         struct zxdh_virtqueue *vq = rxvq->vq;
     262                 :            : 
     263                 :            :         zxdh_queue_enable_intr(vq);
     264         [ #  # ]:          0 :         zxdh_mb(hw->weak_barriers);
     265                 :          0 :         return 0;
     266                 :            : }
     267                 :            : 
     268                 :            : int32_t
     269                 :          0 : zxdh_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
     270                 :            : {
     271                 :          0 :         struct zxdh_virtnet_rx *rxvq = dev->data->rx_queues[queue_id];
     272         [ #  # ]:          0 :         struct zxdh_virtqueue  *vq      = rxvq->vq;
     273                 :            : 
     274                 :            :         zxdh_queue_disable_intr(vq);
     275                 :          0 :         return 0;
     276                 :            : }
     277                 :            : 
     278                 :          0 : int32_t zxdh_enqueue_recv_refill_packed(struct zxdh_virtqueue *vq,
     279                 :            :                         struct rte_mbuf **cookie, uint16_t num)
     280                 :            : {
     281                 :          0 :         struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
     282                 :          0 :         struct zxdh_hw *hw = vq->hw;
     283                 :            :         struct zxdh_vq_desc_extra *dxp;
     284                 :          0 :         uint16_t flags = vq->vq_packed.cached_flags;
     285                 :            :         int32_t i;
     286                 :            :         uint16_t idx;
     287                 :            : 
     288         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     289                 :          0 :                 idx = vq->vq_avail_idx;
     290                 :          0 :                 dxp = &vq->vq_descx[idx];
     291                 :          0 :                 dxp->cookie = (void *)cookie[i];
     292                 :          0 :                 dxp->ndescs = 1;
     293                 :            :                 /* rx pkt fill in data_off */
     294         [ #  # ]:          0 :                 start_dp[idx].addr = rte_mbuf_iova_get(cookie[i]) + RTE_PKTMBUF_HEADROOM;
     295                 :          0 :                 start_dp[idx].len = cookie[i]->buf_len - RTE_PKTMBUF_HEADROOM;
     296                 :          0 :                 vq->vq_desc_head_idx = dxp->next;
     297         [ #  # ]:          0 :                 if (vq->vq_desc_head_idx == ZXDH_VQ_RING_DESC_CHAIN_END)
     298                 :          0 :                         vq->vq_desc_tail_idx = vq->vq_desc_head_idx;
     299         [ #  # ]:          0 :                 zxdh_queue_store_flags_packed(&start_dp[idx], flags, hw->weak_barriers);
     300         [ #  # ]:          0 :                 if (++vq->vq_avail_idx >= vq->vq_nentries) {
     301                 :          0 :                         vq->vq_avail_idx -= vq->vq_nentries;
     302                 :          0 :                         vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     303                 :            :                         flags = vq->vq_packed.cached_flags;
     304                 :            :                 }
     305                 :            :         }
     306                 :          0 :         vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - num);
     307                 :          0 :         return 0;
     308                 :            : }
     309                 :            : 
     310                 :          0 : int32_t zxdh_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t logic_qidx)
     311                 :            : {
     312                 :          0 :         struct zxdh_hw *hw = dev->data->dev_private;
     313                 :          0 :         struct zxdh_virtqueue *vq = hw->vqs[logic_qidx];
     314                 :            :         struct zxdh_virtnet_rx *rxvq = &vq->rxq;
     315                 :            :         uint16_t desc_idx;
     316                 :            :         int32_t error = 0;
     317                 :            : 
     318                 :            :         /* Allocate blank mbufs for the each rx descriptor */
     319                 :          0 :         memset(&rxvq->fake_mbuf, 0, sizeof(rxvq->fake_mbuf));
     320         [ #  # ]:          0 :         for (desc_idx = 0; desc_idx < ZXDH_MBUF_BURST_SZ; desc_idx++)
     321                 :          0 :                 vq->sw_ring[vq->vq_nentries + desc_idx] = &rxvq->fake_mbuf;
     322                 :            : 
     323         [ #  # ]:          0 :         while (!zxdh_queue_full(vq)) {
     324                 :            :                 uint16_t free_cnt = vq->vq_free_cnt;
     325                 :            : 
     326                 :          0 :                 free_cnt = RTE_MIN(ZXDH_MBUF_BURST_SZ, free_cnt);
     327                 :          0 :                 struct rte_mbuf *new_pkts[free_cnt];
     328                 :            : 
     329         [ #  # ]:          0 :                 if (likely(rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt) == 0)) {
     330                 :          0 :                         error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
     331         [ #  # ]:          0 :                         if (unlikely(error)) {
     332                 :            :                                 int32_t i;
     333         [ #  # ]:          0 :                                 for (i = 0; i < free_cnt; i++)
     334                 :          0 :                                         rte_pktmbuf_free(new_pkts[i]);
     335                 :            :                         }
     336                 :            :                 } else {
     337                 :          0 :                         PMD_DRV_LOG(ERR, "port %d rxq %d allocated bufs from %s failed",
     338                 :            :                                 hw->port_id, logic_qidx, rxvq->mpool->name);
     339                 :          0 :                         break;
     340                 :            :                 }
     341                 :            :         }
     342                 :          0 :         return 0;
     343                 :            : }
     344                 :            : 
     345                 :          0 : void zxdh_queue_rxvq_flush(struct zxdh_virtqueue *vq)
     346                 :            : {
     347                 :            :         struct zxdh_vq_desc_extra *dxp = NULL;
     348                 :            :         uint16_t i = 0;
     349                 :          0 :         struct zxdh_vring_packed_desc *descs = vq->vq_packed.ring.desc;
     350                 :            :         int32_t cnt = 0;
     351                 :            : 
     352                 :          0 :         i = vq->vq_used_cons_idx;
     353   [ #  #  #  # ]:          0 :         while (zxdh_desc_used(&descs[i], vq) && cnt++ < vq->vq_nentries) {
     354                 :          0 :                 dxp = &vq->vq_descx[descs[i].id];
     355         [ #  # ]:          0 :                 if (dxp->cookie != NULL) {
     356                 :          0 :                         rte_pktmbuf_free(dxp->cookie);
     357                 :          0 :                         dxp->cookie = NULL;
     358                 :            :                 }
     359                 :          0 :                 vq->vq_free_cnt++;
     360                 :          0 :                 vq->vq_used_cons_idx++;
     361         [ #  # ]:          0 :                 if (vq->vq_used_cons_idx >= vq->vq_nentries) {
     362                 :          0 :                         vq->vq_used_cons_idx -= vq->vq_nentries;
     363                 :          0 :                         vq->vq_packed.used_wrap_counter ^= 1;
     364                 :            :                 }
     365                 :          0 :                 i = vq->vq_used_cons_idx;
     366                 :            :         }
     367                 :          0 : }

Generated by: LCOV version 1.14