LCOV - code coverage report
Current view: top level - drivers/net/hinic3/base - hinic3_cmdq.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 303 0.0 %
Date: 2025-11-01 17:50:34 Functions: 0 21 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 102 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 "hinic3_compat.h"
       6                 :            : #include "hinic3_cmd.h"
       7                 :            : #include "hinic3_cmdq.h"
       8                 :            : #include "hinic3_hwdev.h"
       9                 :            : #include "hinic3_hwif.h"
      10                 :            : #include "hinic3_mgmt.h"
      11                 :            : #include "hinic3_wq.h"
      12                 :            : #include "hinic3_nic_cfg.h"
      13                 :            : 
      14                 :            : #define CMDQ_CMD_TIMEOUT 5000 /**< Millisecond. */
      15                 :            : 
      16                 :            : #define UPPER_8_BITS(data) (((data) >> 8) & 0xFF)
      17                 :            : #define LOWER_8_BITS(data) ((data) & 0xFF)
      18                 :            : 
      19                 :            : #define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0
      20                 :            : #define CMDQ_DB_INFO_HI_PROD_IDX_MASK  0xFFU
      21                 :            : 
      22                 :            : #define CMDQ_DB_INFO_SET(val, member)                  \
      23                 :            :         ((((uint32_t)(val)) & CMDQ_DB_INFO_##member##_MASK) \
      24                 :            :          << CMDQ_DB_INFO_##member##_SHIFT)
      25                 :            : #define CMDQ_DB_INFO_UPPER_32(val) ((uint64_t)(val) << 32)
      26                 :            : 
      27                 :            : #define CMDQ_DB_HEAD_QUEUE_TYPE_SHIFT 23
      28                 :            : #define CMDQ_DB_HEAD_CMDQ_TYPE_SHIFT  24
      29                 :            : #define CMDQ_DB_HEAD_SRC_TYPE_SHIFT   27
      30                 :            : #define CMDQ_DB_HEAD_QUEUE_TYPE_MASK  0x1U
      31                 :            : #define CMDQ_DB_HEAD_CMDQ_TYPE_MASK   0x7U
      32                 :            : #define CMDQ_DB_HEAD_SRC_TYPE_MASK    0x1FU
      33                 :            : #define CMDQ_DB_HEAD_SET(val, member)                  \
      34                 :            :         ((((uint32_t)(val)) & CMDQ_DB_HEAD_##member##_MASK) \
      35                 :            :          << CMDQ_DB_HEAD_##member##_SHIFT)
      36                 :            : 
      37                 :            : #define CMDQ_CTRL_PI_SHIFT          0
      38                 :            : #define CMDQ_CTRL_CMD_SHIFT         16
      39                 :            : #define CMDQ_CTRL_MOD_SHIFT         24
      40                 :            : #define CMDQ_CTRL_ACK_TYPE_SHIFT    29
      41                 :            : #define CMDQ_CTRL_HW_BUSY_BIT_SHIFT 31
      42                 :            : 
      43                 :            : #define CMDQ_CTRL_PI_MASK          0xFFFFU
      44                 :            : #define CMDQ_CTRL_CMD_MASK         0xFFU
      45                 :            : #define CMDQ_CTRL_MOD_MASK         0x1FU
      46                 :            : #define CMDQ_CTRL_ACK_TYPE_MASK    0x3U
      47                 :            : #define CMDQ_CTRL_HW_BUSY_BIT_MASK 0x1U
      48                 :            : 
      49                 :            : #define CMDQ_CTRL_SET(val, member) \
      50                 :            :         (((uint32_t)(val) & CMDQ_CTRL_##member##_MASK) << CMDQ_CTRL_##member##_SHIFT)
      51                 :            : 
      52                 :            : #define CMDQ_CTRL_GET(val, member) \
      53                 :            :         (((val) >> CMDQ_CTRL_##member##_SHIFT) & CMDQ_CTRL_##member##_MASK)
      54                 :            : 
      55                 :            : #define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT       0
      56                 :            : #define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT      15
      57                 :            : #define CMDQ_WQE_HEADER_DATA_FMT_SHIFT          22
      58                 :            : #define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT      23
      59                 :            : #define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT 27
      60                 :            : #define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT          29
      61                 :            : #define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT       31
      62                 :            : 
      63                 :            : #define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK       0xFFU
      64                 :            : #define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK      0x1U
      65                 :            : #define CMDQ_WQE_HEADER_DATA_FMT_MASK          0x1U
      66                 :            : #define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK      0x1U
      67                 :            : #define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK 0x3U
      68                 :            : #define CMDQ_WQE_HEADER_CTRL_LEN_MASK          0x3U
      69                 :            : #define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK       0x1U
      70                 :            : 
      71                 :            : #define CMDQ_WQE_HEADER_SET(val, member)                \
      72                 :            :         (((uint32_t)(val) & CMDQ_WQE_HEADER_##member##_MASK) \
      73                 :            :          << CMDQ_WQE_HEADER_##member##_SHIFT)
      74                 :            : 
      75                 :            : #define CMDQ_WQE_HEADER_GET(val, member)               \
      76                 :            :         (((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) & \
      77                 :            :          CMDQ_WQE_HEADER_##member##_MASK)
      78                 :            : 
      79                 :            : #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0
      80                 :            : #define CMDQ_CTXT_EQ_ID_SHIFT             53
      81                 :            : #define CMDQ_CTXT_CEQ_ARM_SHIFT           61
      82                 :            : #define CMDQ_CTXT_CEQ_EN_SHIFT            62
      83                 :            : #define CMDQ_CTXT_HW_BUSY_BIT_SHIFT       63
      84                 :            : 
      85                 :            : #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF
      86                 :            : #define CMDQ_CTXT_EQ_ID_MASK             0xFF
      87                 :            : #define CMDQ_CTXT_CEQ_ARM_MASK           0x1
      88                 :            : #define CMDQ_CTXT_CEQ_EN_MASK            0x1
      89                 :            : #define CMDQ_CTXT_HW_BUSY_BIT_MASK       0x1
      90                 :            : 
      91                 :            : #define CMDQ_CTXT_PAGE_INFO_SET(val, member) \
      92                 :            :         (((uint64_t)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
      93                 :            : 
      94                 :            : #define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0
      95                 :            : #define CMDQ_CTXT_CI_SHIFT           52
      96                 :            : 
      97                 :            : #define CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF
      98                 :            : #define CMDQ_CTXT_CI_MASK           0xFFF
      99                 :            : 
     100                 :            : #define CMDQ_CTXT_BLOCK_INFO_SET(val, member) \
     101                 :            :         (((uint64_t)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
     102                 :            : 
     103                 :            : #define SAVED_DATA_ARM_SHIFT 31
     104                 :            : 
     105                 :            : #define SAVED_DATA_ARM_MASK 0x1U
     106                 :            : 
     107                 :            : #define SAVED_DATA_SET(val, member) \
     108                 :            :         (((val) & SAVED_DATA_##member##_MASK) << SAVED_DATA_##member##_SHIFT)
     109                 :            : 
     110                 :            : #define SAVED_DATA_CLEAR(val, member) \
     111                 :            :         ((val) & (~(SAVED_DATA_##member##_MASK << SAVED_DATA_##member##_SHIFT)))
     112                 :            : 
     113                 :            : #define WQE_ERRCODE_VAL_SHIFT 0
     114                 :            : 
     115                 :            : #define WQE_ERRCODE_VAL_MASK 0x7FFFFFFF
     116                 :            : 
     117                 :            : #define WQE_ERRCODE_GET(val, member) \
     118                 :            :         (((val) >> WQE_ERRCODE_##member##_SHIFT) & WQE_ERRCODE_##member##_MASK)
     119                 :            : 
     120                 :            : #define WQE_COMPLETED(ctrl_info) CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT)
     121                 :            : 
     122                 :            : #define WQE_HEADER(wqe) ((struct hinic3_cmdq_header *)(wqe))
     123                 :            : 
     124                 :            : #define CMDQ_DB_PI_OFF(pi) (LOWER_8_BITS(pi) << 3)
     125                 :            : 
     126                 :            : #define CMDQ_DB_ADDR(db_base, pi) ((db_base) + CMDQ_DB_PI_OFF(pi))
     127                 :            : 
     128                 :            : #define CMDQ_PFN(addr, page_size) ((addr) >> (rte_log2_u32(page_size)))
     129                 :            : 
     130                 :            : #define FIRST_DATA_TO_WRITE_LAST sizeof(uint64_t)
     131                 :            : 
     132                 :            : #define WQE_LCMD_SIZE 64
     133                 :            : #define WQE_SCMD_SIZE 64
     134                 :            : 
     135                 :            : #define COMPLETE_LEN 3
     136                 :            : 
     137                 :            : #define CMDQ_WQEBB_SIZE  64
     138                 :            : #define CMDQ_WQEBB_SHIFT 6
     139                 :            : 
     140                 :            : #define CMDQ_WQE_SIZE 64
     141                 :            : 
     142                 :            : #define HINIC3_CMDQ_WQ_BUF_SIZE 4096
     143                 :            : 
     144                 :            : #define WQE_NUM_WQEBBS(wqe_size, wq)                                 \
     145                 :            :         ({                                                           \
     146                 :            :                 typeof(wq) __wq = (wq);                              \
     147                 :            :                 (uint16_t)(RTE_ALIGN((uint32_t)(wqe_size), __wq->wqebb_size) / \
     148                 :            :                       __wq->wqebb_size);                             \
     149                 :            :         })
     150                 :            : 
     151                 :            : #define cmdq_to_cmdqs(cmdq)                                                   \
     152                 :            :         ({                                                                    \
     153                 :            :                 typeof(cmdq) __cmdq = (cmdq);                                 \
     154                 :            :                 container_of(__cmdq - __cmdq->cmdq_type, struct hinic3_cmdqs, \
     155                 :            :                              __cmdq[0]);                                      \
     156                 :            :         })
     157                 :            : 
     158                 :            : #define WAIT_CMDQ_ENABLE_TIMEOUT 300
     159                 :            : 
     160                 :            : static int hinic3_cmdq_poll_msg(struct hinic3_cmdq *cmdq, uint32_t timeout);
     161                 :            : 
     162                 :            : bool
     163                 :          0 : hinic3_cmdq_idle(struct hinic3_cmdq *cmdq)
     164                 :            : {
     165                 :          0 :         struct hinic3_wq *wq = cmdq->wq;
     166                 :            : 
     167                 :          0 :         return rte_atomic_load_explicit(&wq->delta, rte_memory_order_seq_cst) ==
     168                 :          0 :                wq->q_depth;
     169                 :            : }
     170                 :            : 
     171                 :            : struct hinic3_cmd_buf *
     172                 :          0 : hinic3_alloc_cmd_buf(struct hinic3_hwdev *hwdev)
     173                 :            : {
     174                 :          0 :         struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
     175                 :            :         struct hinic3_cmd_buf *cmd_buf;
     176                 :            : 
     177                 :          0 :         cmd_buf = rte_zmalloc(NULL, sizeof(*cmd_buf), 0);
     178         [ #  # ]:          0 :         if (!cmd_buf) {
     179                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate cmd buffer failed");
     180                 :          0 :                 return NULL;
     181                 :            :         }
     182                 :            : 
     183                 :          0 :         cmd_buf->mbuf = rte_pktmbuf_alloc(cmdqs->cmd_buf_pool);
     184         [ #  # ]:          0 :         if (!cmd_buf->mbuf) {
     185                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate cmd from the pool failed");
     186                 :          0 :                 goto alloc_pci_buf_err;
     187                 :            :         }
     188                 :            : 
     189                 :          0 :         cmd_buf->dma_addr = rte_mbuf_data_iova(cmd_buf->mbuf);
     190                 :          0 :         cmd_buf->buf = rte_pktmbuf_mtod(cmd_buf->mbuf, void *);
     191                 :            : 
     192                 :          0 :         return cmd_buf;
     193                 :            : 
     194                 :            : alloc_pci_buf_err:
     195                 :          0 :         rte_free(cmd_buf);
     196                 :          0 :         return NULL;
     197                 :            : }
     198                 :            : 
     199                 :            : void
     200                 :          0 : hinic3_free_cmd_buf(struct hinic3_cmd_buf *cmd_buf)
     201                 :            : {
     202                 :          0 :         rte_pktmbuf_free(cmd_buf->mbuf);
     203                 :          0 :         rte_free(cmd_buf);
     204                 :          0 : }
     205                 :            : 
     206                 :            : static uint32_t
     207                 :            : cmdq_wqe_size(enum cmdq_wqe_type wqe_type)
     208                 :            : {
     209                 :            :         uint32_t wqe_size = 0;
     210                 :            : 
     211                 :            :         switch (wqe_type) {
     212                 :            :         case WQE_LCMD_TYPE:
     213                 :            :                 wqe_size = WQE_LCMD_SIZE;
     214                 :            :                 break;
     215                 :            :         case WQE_SCMD_TYPE:
     216                 :            :                 wqe_size = WQE_SCMD_SIZE;
     217                 :            :                 break;
     218                 :            :         }
     219                 :            : 
     220                 :            :         return wqe_size;
     221                 :            : }
     222                 :            : 
     223                 :            : static uint32_t
     224                 :            : cmdq_get_wqe_size(enum bufdesc_len len)
     225                 :            : {
     226                 :            :         uint32_t wqe_size = 0;
     227                 :            : 
     228                 :          0 :         switch (len) {
     229                 :            :         case BUFDESC_LCMD_LEN:
     230                 :            :                 wqe_size = WQE_LCMD_SIZE;
     231                 :            :                 break;
     232                 :            :         case BUFDESC_SCMD_LEN:
     233                 :            :                 wqe_size = WQE_SCMD_SIZE;
     234                 :            :                 break;
     235                 :          0 :         default:
     236                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid bufdesc_len");
     237                 :            :                 break;
     238                 :            :         }
     239                 :            : 
     240                 :            :         return wqe_size;
     241                 :            : }
     242                 :            : 
     243                 :            : static void
     244                 :            : cmdq_set_completion(struct hinic3_cmdq_completion *complete,
     245                 :            :                     struct hinic3_cmd_buf *buf_out)
     246                 :            : {
     247                 :            :         struct hinic3_sge_resp *sge_resp = &complete->sge_resp;
     248                 :            : 
     249                 :          0 :         hinic3_set_sge(&sge_resp->sge, buf_out->dma_addr, HINIC3_CMDQ_BUF_SIZE);
     250                 :          0 : }
     251                 :            : 
     252                 :            : static void
     253                 :            : cmdq_set_lcmd_bufdesc(struct hinic3_cmdq_wqe_lcmd *wqe,
     254                 :            :                       struct hinic3_cmd_buf *buf_in)
     255                 :            : {
     256                 :          0 :         hinic3_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size);
     257                 :            : }
     258                 :            : 
     259                 :            : static void
     260                 :          0 : cmdq_set_db(struct hinic3_cmdq *cmdq, enum hinic3_cmdq_type cmdq_type,
     261                 :            :             uint16_t prod_idx)
     262                 :            : {
     263                 :          0 :         uint64_t db = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX);
     264                 :            : 
     265                 :          0 :         db = CMDQ_DB_INFO_UPPER_32(db) |
     266                 :          0 :              CMDQ_DB_HEAD_SET(HINIC3_DB_CMDQ_TYPE, QUEUE_TYPE) |
     267                 :          0 :              CMDQ_DB_HEAD_SET(cmdq_type, CMDQ_TYPE) |
     268                 :            :              CMDQ_DB_HEAD_SET(HINIC3_DB_SRC_CMDQ_TYPE, SRC_TYPE);
     269                 :            : 
     270                 :            :         /**< Write all before the doorbell. */
     271                 :            :         rte_atomic_thread_fence(rte_memory_order_release);
     272                 :            :         /* Hardware will do endianness converting. */
     273                 :          0 :         rte_write64(db, CMDQ_DB_ADDR(cmdq->db_base, prod_idx));
     274                 :          0 : }
     275                 :            : 
     276                 :            : static void
     277                 :          0 : cmdq_wqe_fill(void *dst, void *src)
     278                 :            : {
     279                 :          0 :         memcpy((void *)((uint8_t *)dst + FIRST_DATA_TO_WRITE_LAST),
     280                 :          0 :                (void *)((uint8_t *)src + FIRST_DATA_TO_WRITE_LAST),
     281                 :            :                CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST);
     282                 :            : 
     283                 :            :         /* The first 8 bytes should be written last. */
     284                 :            :         rte_atomic_thread_fence(rte_memory_order_release);
     285                 :            : 
     286                 :          0 :         *(uint64_t *)dst = *(uint64_t *)src;
     287                 :          0 : }
     288                 :            : 
     289                 :            : static void
     290                 :          0 : cmdq_prepare_wqe_ctrl(struct hinic3_cmdq_wqe *wqe, int wrapped,
     291                 :            :                       enum hinic3_mod_type mod, uint8_t cmd, uint16_t prod_idx,
     292                 :            :                       enum completion_format complete_format,
     293                 :            :                       enum data_format local_data_format,
     294                 :            :                       enum bufdesc_len buf_len)
     295                 :            : {
     296                 :            :         struct hinic3_ctrl *ctrl = NULL;
     297                 :            :         enum ctrl_sect_len ctrl_len;
     298                 :            :         struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = NULL;
     299                 :            :         struct hinic3_cmdq_wqe_scmd *wqe_scmd = NULL;
     300                 :          0 :         uint32_t saved_data = WQE_HEADER(wqe)->saved_data;
     301                 :            : 
     302         [ #  # ]:          0 :         if (local_data_format == DATA_SGE) {
     303                 :            :                 wqe_lcmd = &wqe->wqe_lcmd;
     304                 :            : 
     305                 :          0 :                 wqe_lcmd->status.status_info = 0;
     306                 :          0 :                 ctrl = &wqe_lcmd->ctrl;
     307                 :            :                 ctrl_len = CTRL_SECT_LEN;
     308                 :            :         } else {
     309                 :            :                 wqe_scmd = &wqe->inline_wqe.wqe_scmd;
     310                 :            : 
     311                 :          0 :                 wqe_scmd->status.status_info = 0;
     312                 :          0 :                 ctrl = &wqe_scmd->ctrl;
     313                 :            :                 ctrl_len = CTRL_DIRECT_SECT_LEN;
     314                 :            :         }
     315                 :            : 
     316                 :          0 :         ctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI) |
     317                 :          0 :                           CMDQ_CTRL_SET(cmd, CMD) | CMDQ_CTRL_SET(mod, MOD) |
     318                 :            :                           CMDQ_CTRL_SET(HINIC3_ACK_TYPE_CMDQ, ACK_TYPE);
     319                 :            : 
     320                 :          0 :         WQE_HEADER(wqe)->header_info =
     321                 :          0 :                 CMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) |
     322                 :          0 :                 CMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) |
     323                 :          0 :                 CMDQ_WQE_HEADER_SET(local_data_format, DATA_FMT) |
     324                 :            :                 CMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ) |
     325                 :          0 :                 CMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) |
     326                 :          0 :                 CMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN) |
     327                 :          0 :                 CMDQ_WQE_HEADER_SET((uint32_t)wrapped, HW_BUSY_BIT);
     328                 :            : 
     329                 :          0 :         saved_data &= SAVED_DATA_CLEAR(saved_data, ARM);
     330         [ #  # ]:          0 :         if (cmd == CMDQ_SET_ARM_CMD && mod == HINIC3_MOD_COMM)
     331                 :          0 :                 WQE_HEADER(wqe)->saved_data = saved_data |
     332                 :            :                                               SAVED_DATA_SET(1, ARM);
     333                 :            :         else
     334                 :          0 :                 WQE_HEADER(wqe)->saved_data = saved_data;
     335                 :          0 : }
     336                 :            : 
     337                 :            : static void
     338                 :          0 : cmdq_set_lcmd_wqe(struct hinic3_cmdq_wqe *wqe, enum cmdq_cmd_type cmd_type,
     339                 :            :                   struct hinic3_cmd_buf *buf_in, struct hinic3_cmd_buf *buf_out,
     340                 :            :                   int wrapped, enum hinic3_mod_type mod, uint8_t cmd, uint16_t prod_idx)
     341                 :            : {
     342                 :            :         struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd;
     343                 :            :         enum completion_format complete_format = COMPLETE_DIRECT;
     344                 :            : 
     345   [ #  #  #  # ]:          0 :         switch (cmd_type) {
     346                 :          0 :         case SYNC_CMD_DIRECT_RESP:
     347                 :            :                 complete_format = COMPLETE_DIRECT;
     348                 :          0 :                 wqe_lcmd->completion.direct_resp = 0;
     349                 :          0 :                 break;
     350                 :          0 :         case SYNC_CMD_SGE_RESP:
     351         [ #  # ]:          0 :                 if (buf_out) {
     352                 :            :                         complete_format = COMPLETE_SGE;
     353                 :            :                         cmdq_set_completion(&wqe_lcmd->completion, buf_out);
     354                 :            :                 }
     355                 :            :                 break;
     356                 :          0 :         case ASYNC_CMD:
     357                 :            :                 complete_format = COMPLETE_DIRECT;
     358                 :          0 :                 wqe_lcmd->completion.direct_resp = 0;
     359                 :          0 :                 wqe_lcmd->buf_desc.saved_async_buf = (uint64_t)(buf_in);
     360                 :          0 :                 break;
     361                 :          0 :         default:
     362                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid cmdq_cmd_type");
     363                 :          0 :                 break;
     364                 :            :         }
     365                 :            : 
     366                 :          0 :         cmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, complete_format,
     367                 :            :                               DATA_SGE, BUFDESC_LCMD_LEN);
     368                 :            : 
     369                 :            :         cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);
     370                 :          0 : }
     371                 :            : 
     372                 :            : /**
     373                 :            :  * Prepare necessary context for command queue, send a synchronous command with
     374                 :            :  * a direct response to hardware. It waits for completion of command by polling
     375                 :            :  * command queue for a response.
     376                 :            :  *
     377                 :            :  * @param[in] cmdq
     378                 :            :  * The command queue object that represents the queue to send the command to.
     379                 :            :  * @param[in] mod
     380                 :            :  * The module type that the command belongs to.
     381                 :            :  * @param[in] cmd
     382                 :            :  * The command to be executed.
     383                 :            :  * @param[in] buf_in
     384                 :            :  * The input buffer containing the command parameters.
     385                 :            :  * @param[out] out_param
     386                 :            :  * A pointer to the location where the response data will be stored, if
     387                 :            :  * available.
     388                 :            :  * @param[in] timeout
     389                 :            :  * The timeout value (ms) to wait for the command completion. If zero, a default
     390                 :            :  * timeout will be used.
     391                 :            :  *
     392                 :            :  * @return
     393                 :            :  * 0 on success, non-zero on failure.
     394                 :            :  * - -EBUSY: The command queue is busy.
     395                 :            :  * - -ETIMEDOUT: The command did not complete within the specified timeout.
     396                 :            :  */
     397                 :            : static int
     398                 :          0 : cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, enum hinic3_mod_type mod,
     399                 :            :                           uint8_t cmd, struct hinic3_cmd_buf *buf_in,
     400                 :            :                           uint64_t *out_param, uint32_t timeout)
     401                 :            : {
     402                 :            :         struct hinic3_cmdq_wqe wqe;
     403                 :          0 :         struct hinic3_wq *wq = cmdq->wq;
     404                 :            :         struct hinic3_cmdq_wqe *curr_wqe = NULL;
     405                 :            :         struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = NULL;
     406                 :            :         uint16_t curr_prod_idx, next_prod_idx, num_wqebbs;
     407                 :            :         uint32_t timeo, wqe_size;
     408                 :            :         int wrapped, err;
     409                 :            : 
     410                 :            :         wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
     411                 :          0 :         num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
     412                 :            : 
     413                 :            :         /* ensure thread safety and maintain wrapped and doorbell index correct. */
     414                 :          0 :         rte_spinlock_lock(&cmdq->cmdq_lock);
     415                 :            : 
     416                 :          0 :         curr_wqe = hinic3_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
     417         [ #  # ]:          0 :         if (curr_wqe == NULL) {
     418                 :            :                 err = -EBUSY;
     419                 :          0 :                 goto cmdq_unlock;
     420                 :            :         }
     421                 :            : 
     422                 :            :         memset(&wqe, 0, sizeof(wqe));
     423                 :          0 :         wrapped = cmdq->wrapped;
     424                 :            : 
     425                 :          0 :         next_prod_idx = curr_prod_idx + num_wqebbs;
     426         [ #  # ]:          0 :         if (next_prod_idx >= wq->q_depth) {
     427                 :          0 :                 cmdq->wrapped = !cmdq->wrapped;
     428                 :          0 :                 next_prod_idx -= wq->q_depth;
     429                 :            :         }
     430                 :            : 
     431                 :          0 :         cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL, wrapped,
     432                 :            :                           mod, cmd, curr_prod_idx);
     433                 :            : 
     434                 :            : 
     435                 :            :         hinic3_cpu_to_hw(&wqe, wqe_size);
     436                 :            : 
     437                 :            :         /* Cmdq wqe is not shadow, therefore wqe will be written to wq. */
     438                 :          0 :         cmdq_wqe_fill(curr_wqe, &wqe);
     439                 :            : 
     440                 :          0 :         cmdq->cmd_infos[curr_prod_idx].cmd_type = HINIC3_CMD_TYPE_DIRECT_RESP;
     441                 :            : 
     442                 :          0 :         cmdq_set_db(cmdq, HINIC3_CMDQ_SYNC, next_prod_idx);
     443                 :            : 
     444         [ #  # ]:          0 :         timeo = timeout ? timeout : CMDQ_CMD_TIMEOUT;
     445                 :          0 :         err = hinic3_cmdq_poll_msg(cmdq, timeo);
     446         [ #  # ]:          0 :         if (err) {
     447                 :          0 :                 PMD_DRV_LOG(ERR, "Cmdq poll msg ack failed, prod idx: 0x%x",
     448                 :            :                             curr_prod_idx);
     449                 :            :                 err = -ETIMEDOUT;
     450                 :          0 :                 goto cmdq_unlock;
     451                 :            :         }
     452                 :            : 
     453                 :          0 :         rte_smp_rmb(); /*Ensure all cmdq return messages are completed*/
     454                 :            : 
     455         [ #  # ]:          0 :         if (out_param) {
     456                 :            :                 wqe_lcmd = &curr_wqe->wqe_lcmd;
     457         [ #  # ]:          0 :                 *out_param = rte_cpu_to_be_64(wqe_lcmd->completion.direct_resp);
     458                 :            :         }
     459                 :            : 
     460         [ #  # ]:          0 :         if (cmdq->errcode[curr_prod_idx])
     461                 :            :                 err = cmdq->errcode[curr_prod_idx];
     462                 :            : 
     463                 :          0 : cmdq_unlock:
     464                 :            :         rte_spinlock_unlock(&cmdq->cmdq_lock);
     465                 :            : 
     466                 :          0 :         return err;
     467                 :            : }
     468                 :            : 
     469                 :            : /**
     470                 :            :  * Send a synchronous command with detailed response and wait for the
     471                 :            :  * completion.
     472                 :            :  *
     473                 :            :  * @param[in] cmdq
     474                 :            :  * The command queue object representing the queue to send the command to.
     475                 :            :  * @param[in] mod
     476                 :            :  * The module type that the command belongs to.
     477                 :            :  * @param[in] cmd
     478                 :            :  * The command to be executed.
     479                 :            :  * @param[in] buf_in
     480                 :            :  * The input buffer containing the parameters for the command.
     481                 :            :  * @param[out] buf_out
     482                 :            :  * The output buffer where the detailed response from the hardware will be
     483                 :            :  * stored.
     484                 :            :  * @param[in] timeout
     485                 :            :  * The timeout value (ms) to wait for the command completion. If zero, a default
     486                 :            :  * timeout will be used.
     487                 :            :  *
     488                 :            :  * @return
     489                 :            :  * 0 on success, non-zero on failure.
     490                 :            :  * - -EBUSY: The command queue is busy.
     491                 :            :  * - -ETIMEDOUT: The command did not complete within the specified timeout.
     492                 :            :  */
     493                 :            : static int
     494                 :          0 : cmdq_sync_cmd_detail_resp(struct hinic3_cmdq *cmdq, enum hinic3_mod_type mod,
     495                 :            :                           uint8_t cmd, struct hinic3_cmd_buf *buf_in,
     496                 :            :                           struct hinic3_cmd_buf *buf_out, uint32_t timeout)
     497                 :            : {
     498                 :            :         struct hinic3_cmdq_wqe wqe;
     499                 :          0 :         struct hinic3_wq *wq = cmdq->wq;
     500                 :            :         struct hinic3_cmdq_wqe *curr_wqe = NULL;
     501                 :            :         uint16_t curr_prod_idx, next_prod_idx, num_wqebbs;
     502                 :            :         uint32_t timeo, wqe_size;
     503                 :            :         int wrapped, err;
     504                 :            : 
     505                 :            :         wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
     506                 :          0 :         num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
     507                 :            : 
     508                 :            :         /* ensure thread safety and maintain wrapped and doorbell index correct. */
     509                 :          0 :         rte_spinlock_lock(&cmdq->cmdq_lock);
     510                 :            : 
     511                 :          0 :         curr_wqe = hinic3_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
     512         [ #  # ]:          0 :         if (curr_wqe == NULL) {
     513                 :            :                 err = -EBUSY;
     514                 :          0 :                 goto cmdq_unlock;
     515                 :            :         }
     516                 :            : 
     517                 :            :         memset(&wqe, 0, sizeof(wqe));
     518                 :          0 :         wrapped = cmdq->wrapped;
     519                 :            : 
     520                 :          0 :         next_prod_idx = curr_prod_idx + num_wqebbs;
     521         [ #  # ]:          0 :         if (next_prod_idx >= wq->q_depth) {
     522                 :          0 :                 cmdq->wrapped = !cmdq->wrapped;
     523                 :          0 :                 next_prod_idx -= wq->q_depth;
     524                 :            :         }
     525                 :            : 
     526                 :          0 :         cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_SGE_RESP, buf_in, buf_out, wrapped,
     527                 :            :                           mod, cmd, curr_prod_idx);
     528                 :            : 
     529                 :            :         hinic3_cpu_to_hw(&wqe, wqe_size);
     530                 :            : 
     531                 :            :         /* Cmdq wqe is not shadow, therefore wqe will be written to wq. */
     532                 :          0 :         cmdq_wqe_fill(curr_wqe, &wqe);
     533                 :            : 
     534                 :          0 :         cmdq->cmd_infos[curr_prod_idx].cmd_type = HINIC3_CMD_TYPE_SGE_RESP;
     535                 :            : 
     536                 :          0 :         cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx);
     537                 :            : 
     538         [ #  # ]:          0 :         timeo = timeout ? timeout : CMDQ_CMD_TIMEOUT;
     539                 :          0 :         err = hinic3_cmdq_poll_msg(cmdq, timeo);
     540         [ #  # ]:          0 :         if (err) {
     541                 :          0 :                 PMD_DRV_LOG(ERR, "Cmdq poll msg ack failed, prod idx: 0x%x",
     542                 :            :                             curr_prod_idx);
     543                 :            :                 err = -ETIMEDOUT;
     544                 :          0 :                 goto cmdq_unlock;
     545                 :            :         }
     546                 :            : 
     547                 :          0 :         rte_smp_rmb(); /*Ensure all cmdq return messages are completed*/
     548                 :            : 
     549         [ #  # ]:          0 :         if (cmdq->errcode[curr_prod_idx])
     550                 :            :                 err = cmdq->errcode[curr_prod_idx];
     551                 :            : 
     552                 :          0 : cmdq_unlock:
     553                 :            :         rte_spinlock_unlock(&cmdq->cmdq_lock);
     554                 :            : 
     555                 :          0 :         return err;
     556                 :            : }
     557                 :            : 
     558                 :            : static int
     559                 :          0 : cmdq_params_valid(struct hinic3_hwdev *hwdev, struct hinic3_cmd_buf *buf_in)
     560                 :            : {
     561         [ #  # ]:          0 :         if (!buf_in || !hwdev) {
     562                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid CMDQ buffer or hwdev is NULL");
     563                 :          0 :                 return -EINVAL;
     564                 :            :         }
     565                 :            : 
     566         [ #  # ]:          0 :         if (buf_in->size == 0 || buf_in->size > HINIC3_CMDQ_BUF_SIZE) {
     567                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid CMDQ buffer size: 0x%x",
     568                 :            :                             buf_in->size);
     569                 :          0 :                 return -EINVAL;
     570                 :            :         }
     571                 :            : 
     572                 :            :         return 0;
     573                 :            : }
     574                 :            : 
     575                 :            : static int
     576                 :          0 : wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs)
     577                 :            : {
     578                 :            :         uint64_t end;
     579                 :            : 
     580                 :          0 :         end = cycles + msecs_to_cycles(WAIT_CMDQ_ENABLE_TIMEOUT);
     581                 :            :         do {
     582         [ #  # ]:          0 :                 if (cmdqs->status & HINIC3_CMDQ_ENABLE)
     583                 :            :                         return 0;
     584         [ #  # ]:          0 :         } while (time_before(cycles, end));
     585                 :            : 
     586                 :            :         return -EBUSY;
     587                 :            : }
     588                 :            : 
     589                 :            : int
     590                 :          0 : hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, enum hinic3_mod_type mod, uint8_t cmd,
     591                 :            :                         struct hinic3_cmd_buf *buf_in, uint64_t *out_param, uint32_t timeout)
     592                 :            : {
     593                 :          0 :         struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
     594                 :            :         int err;
     595                 :            : 
     596                 :          0 :         err = cmdq_params_valid(hwdev, buf_in);
     597         [ #  # ]:          0 :         if (err) {
     598                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid cmdq parameters");
     599                 :          0 :                 return err;
     600                 :            :         }
     601                 :            : 
     602                 :          0 :         err = wait_cmdqs_enable(cmdqs);
     603         [ #  # ]:          0 :         if (err) {
     604                 :          0 :                 PMD_DRV_LOG(ERR, "Cmdq is disabled");
     605                 :          0 :                 return err;
     606                 :            :         }
     607                 :            : 
     608                 :          0 :         return cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod,
     609                 :            :                                          cmd, buf_in, out_param, timeout);
     610                 :            : }
     611                 :            : 
     612                 :            : int
     613                 :          0 : hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, enum hinic3_mod_type mod, uint8_t cmd,
     614                 :            :                 struct hinic3_cmd_buf *buf_in, struct hinic3_cmd_buf *buf_out, uint32_t timeout)
     615                 :            : {
     616                 :          0 :         struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
     617                 :            :         int err;
     618                 :            : 
     619                 :          0 :         err = cmdq_params_valid(hwdev, buf_in);
     620         [ #  # ]:          0 :         if (err) {
     621                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid cmdq parameters");
     622                 :          0 :                 return err;
     623                 :            :         }
     624                 :            : 
     625                 :          0 :         err = wait_cmdqs_enable(cmdqs);
     626         [ #  # ]:          0 :         if (err) {
     627                 :          0 :                 PMD_DRV_LOG(ERR, "Cmdq is disabled");
     628                 :          0 :                 return err;
     629                 :            :         }
     630                 :            : 
     631                 :          0 :         return cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod,
     632                 :            :                                          cmd, buf_in, buf_out, timeout);
     633                 :            : }
     634                 :            : 
     635                 :            : static void
     636                 :            : cmdq_update_errcode(struct hinic3_cmdq *cmdq, uint16_t prod_idx, int errcode)
     637                 :            : {
     638                 :          0 :         cmdq->errcode[prod_idx] = errcode;
     639                 :            : }
     640                 :            : 
     641                 :            : static void
     642                 :          0 : clear_wqe_complete_bit(struct hinic3_cmdq *cmdq, struct hinic3_cmdq_wqe *wqe)
     643                 :            : {
     644                 :            :         struct hinic3_ctrl *ctrl = NULL;
     645                 :          0 :         uint32_t header_info = hinic3_hw_cpu32(WQE_HEADER(wqe)->header_info);
     646                 :          0 :         int buf_len = CMDQ_WQE_HEADER_GET(header_info, BUFDESC_LEN);
     647         [ #  # ]:          0 :         uint32_t wqe_size = cmdq_get_wqe_size(buf_len);
     648                 :            :         uint16_t num_wqebbs;
     649                 :            : 
     650                 :            :         if (wqe_size == WQE_LCMD_SIZE)
     651                 :          0 :                 ctrl = &wqe->wqe_lcmd.ctrl;
     652                 :            :         else
     653                 :          0 :                 ctrl = &wqe->inline_wqe.wqe_scmd.ctrl;
     654                 :            : 
     655                 :            :         /* Clear HW busy bit. */
     656                 :          0 :         ctrl->ctrl_info = 0;
     657                 :            : 
     658                 :            :         rte_atomic_thread_fence(rte_memory_order_release); /**< Verify wqe is cleared. */
     659                 :            : 
     660                 :          0 :         num_wqebbs = WQE_NUM_WQEBBS(wqe_size, cmdq->wq);
     661                 :          0 :         hinic3_put_wqe(cmdq->wq, num_wqebbs);
     662                 :          0 : }
     663                 :            : 
     664                 :            : static void
     665                 :            : cmdq_init_queue_ctxt(struct hinic3_cmdq *cmdq,
     666                 :            :                      struct hinic3_cmdq_ctxt_info *ctxt_info)
     667                 :            : {
     668                 :          0 :         struct hinic3_wq *wq = cmdq->wq;
     669                 :            :         uint64_t wq_first_page_paddr, pfn;
     670                 :            : 
     671                 :          0 :         uint16_t start_ci = (uint16_t)(wq->cons_idx);
     672                 :            : 
     673                 :            :         /* The data in the HW is in Big Endian Format. */
     674                 :          0 :         wq_first_page_paddr = wq->queue_buf_paddr;
     675                 :            : 
     676                 :          0 :         pfn = CMDQ_PFN(wq_first_page_paddr, RTE_PGSIZE_4K);
     677                 :          0 :         ctxt_info->curr_wqe_page_pfn =
     678                 :            :                 CMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) |
     679                 :            :                 CMDQ_CTXT_PAGE_INFO_SET(0, CEQ_EN) |
     680                 :            :                 CMDQ_CTXT_PAGE_INFO_SET(0, CEQ_ARM) |
     681                 :          0 :                 CMDQ_CTXT_PAGE_INFO_SET(HINIC3_CEQ_ID_CMDQ, EQ_ID) |
     682                 :            :                 CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN);
     683                 :            : 
     684                 :          0 :         ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) |
     685                 :            :                                   CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN);
     686                 :            : }
     687                 :            : 
     688                 :            : static int
     689                 :          0 : init_cmdq(struct hinic3_cmdq *cmdq, struct hinic3_hwdev *hwdev,
     690                 :            :           struct hinic3_wq *wq, enum hinic3_cmdq_type q_type)
     691                 :            : {
     692                 :            :         int err = 0;
     693                 :            :         size_t errcode_size;
     694                 :            :         size_t cmd_infos_size;
     695                 :            : 
     696                 :          0 :         cmdq->wq = wq;
     697                 :          0 :         cmdq->cmdq_type = q_type;
     698                 :          0 :         cmdq->wrapped = 1;
     699                 :            : 
     700                 :            :         rte_spinlock_init(&cmdq->cmdq_lock);
     701                 :            : 
     702                 :          0 :         errcode_size = wq->q_depth * sizeof(*cmdq->errcode);
     703                 :          0 :         cmdq->errcode = rte_zmalloc(NULL, errcode_size, 0);
     704         [ #  # ]:          0 :         if (!cmdq->errcode) {
     705                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate errcode for cmdq failed");
     706                 :          0 :                 return -ENOMEM;
     707                 :            :         }
     708                 :            : 
     709                 :          0 :         cmd_infos_size = wq->q_depth * sizeof(*cmdq->cmd_infos);
     710                 :          0 :         cmdq->cmd_infos = rte_zmalloc(NULL, cmd_infos_size, 0);
     711         [ #  # ]:          0 :         if (!cmdq->cmd_infos) {
     712                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate cmd info for cmdq failed");
     713                 :            :                 err = -ENOMEM;
     714                 :          0 :                 goto cmd_infos_err;
     715                 :            :         }
     716                 :            : 
     717                 :          0 :         cmdq->db_base = hwdev->cmdqs->cmdqs_db_base;
     718                 :            : 
     719                 :          0 :         return 0;
     720                 :            : 
     721                 :            : cmd_infos_err:
     722                 :          0 :         rte_free(cmdq->errcode);
     723                 :            : 
     724                 :          0 :         return err;
     725                 :            : }
     726                 :            : 
     727                 :            : static void
     728                 :            : free_cmdq(struct hinic3_cmdq *cmdq)
     729                 :            : {
     730                 :          0 :         rte_free(cmdq->cmd_infos);
     731                 :          0 :         rte_free(cmdq->errcode);
     732                 :            : }
     733                 :            : 
     734                 :            : static int
     735                 :          0 : hinic3_set_cmdq_ctxts(struct hinic3_hwdev *hwdev)
     736                 :            : {
     737                 :          0 :         struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
     738                 :            :         struct hinic3_cmd_cmdq_ctxt cmdq_ctxt;
     739                 :            :         enum hinic3_cmdq_type cmdq_type;
     740                 :          0 :         uint16_t out_size = sizeof(cmdq_ctxt);
     741                 :            :         int err;
     742                 :            : 
     743         [ #  # ]:          0 :         for (cmdq_type = HINIC3_CMDQ_SYNC; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++) {
     744                 :            :                 memset(&cmdq_ctxt, 0, sizeof(cmdq_ctxt));
     745                 :          0 :                 cmdq_ctxt.ctxt_info = cmdqs->cmdq[cmdq_type].cmdq_ctxt;
     746                 :          0 :                 cmdq_ctxt.func_idx = hinic3_global_func_id(hwdev);
     747                 :          0 :                 cmdq_ctxt.cmdq_id = cmdq_type;
     748                 :            : 
     749                 :          0 :                 err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_COMM,
     750                 :            :                                               HINIC3_MGMT_CMD_SET_CMDQ_CTXT,
     751                 :            :                                               &cmdq_ctxt, sizeof(cmdq_ctxt),
     752                 :            :                                               &cmdq_ctxt, &out_size);
     753                 :            : 
     754   [ #  #  #  #  :          0 :                 if (err || !out_size || cmdq_ctxt.status) {
                   #  # ]
     755                 :          0 :                         PMD_DRV_LOG(ERR,
     756                 :            :                                     "Set cmdq ctxt failed, err: %d, status: 0x%x, out_size: 0x%x",
     757                 :            :                                     err, cmdq_ctxt.status, out_size);
     758                 :          0 :                         return -EFAULT;
     759                 :            :                 }
     760                 :            :         }
     761                 :            : 
     762                 :          0 :         cmdqs->status |= HINIC3_CMDQ_ENABLE;
     763                 :            : 
     764                 :          0 :         return 0;
     765                 :            : }
     766                 :            : 
     767                 :            : int
     768                 :          0 : hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev)
     769                 :            : {
     770                 :          0 :         struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
     771                 :            :         enum hinic3_cmdq_type cmdq_type;
     772                 :            : 
     773         [ #  # ]:          0 :         for (cmdq_type = HINIC3_CMDQ_SYNC; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++) {
     774                 :          0 :                 cmdqs->cmdq[cmdq_type].wrapped = 1;
     775                 :          0 :                 hinic3_wq_wqe_pg_clear(cmdqs->cmdq[cmdq_type].wq);
     776                 :            :         }
     777                 :            : 
     778                 :          0 :         return hinic3_set_cmdq_ctxts(hwdev);
     779                 :            : }
     780                 :            : 
     781                 :            : static int
     782                 :          0 : hinic3_set_cmdqs(struct hinic3_hwdev *hwdev, struct hinic3_cmdqs *cmdqs)
     783                 :            : {
     784                 :          0 :         void *db_base = NULL;
     785                 :            :         enum hinic3_cmdq_type type, cmdq_type;
     786                 :            :         int err;
     787                 :            : 
     788                 :          0 :         err = hinic3_alloc_db_addr(hwdev, &db_base, HINIC3_DB_TYPE_CMDQ);
     789         [ #  # ]:          0 :         if (err) {
     790                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to allocate doorbell address");
     791                 :          0 :                 goto alloc_db_err;
     792                 :            :         }
     793                 :            : 
     794                 :          0 :         cmdqs->cmdqs_db_base = (uint8_t *)db_base;
     795                 :            : 
     796         [ #  # ]:          0 :         for (cmdq_type = HINIC3_CMDQ_SYNC; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++) {
     797                 :          0 :                 err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,
     798                 :          0 :                                 &cmdqs->saved_wqs[cmdq_type], cmdq_type);
     799         [ #  # ]:          0 :                 if (err) {
     800                 :          0 :                         PMD_DRV_LOG(ERR, "Initialize cmdq failed");
     801                 :          0 :                         goto init_cmdq_err;
     802                 :            :                 }
     803                 :            : 
     804                 :            :                 cmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type],
     805                 :            :                                      &cmdqs->cmdq[cmdq_type].cmdq_ctxt);
     806                 :            :         }
     807                 :            : 
     808                 :          0 :         err = hinic3_set_cmdq_ctxts(hwdev);
     809         [ #  # ]:          0 :         if (err)
     810                 :          0 :                 goto init_cmdq_err;
     811                 :            : 
     812                 :            :         return 0;
     813                 :            : 
     814                 :          0 : init_cmdq_err:
     815         [ #  # ]:          0 :         for (type = HINIC3_CMDQ_SYNC; type < cmdq_type; type++)
     816                 :            :                 free_cmdq(&cmdqs->cmdq[type]);
     817                 :            : 
     818                 :          0 : alloc_db_err:
     819                 :          0 :         hinic3_cmdq_free(cmdqs->saved_wqs, HINIC3_MAX_CMDQ_TYPES);
     820                 :          0 :         return -ENOMEM;
     821                 :            : }
     822                 :            : 
     823                 :            : int
     824                 :          0 : hinic3_init_cmdqs(struct hinic3_hwdev *hwdev)
     825                 :            : {
     826                 :            :         struct hinic3_cmdqs *cmdqs = NULL;
     827                 :            :         size_t saved_wqs_size;
     828                 :            :         char cmdq_pool_name[RTE_MEMPOOL_NAMESIZE];
     829                 :            :         int err;
     830                 :            : 
     831                 :          0 :         cmdqs = rte_zmalloc(NULL, sizeof(*cmdqs), 0);
     832         [ #  # ]:          0 :         if (!cmdqs)
     833                 :            :                 return -ENOMEM;
     834                 :            : 
     835                 :          0 :         hwdev->cmdqs = cmdqs;
     836                 :          0 :         cmdqs->hwdev = hwdev;
     837                 :            : 
     838                 :            :         saved_wqs_size = HINIC3_MAX_CMDQ_TYPES * sizeof(struct hinic3_wq);
     839                 :          0 :         cmdqs->saved_wqs = rte_zmalloc(NULL, saved_wqs_size, 0);
     840         [ #  # ]:          0 :         if (!cmdqs->saved_wqs) {
     841                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate saved wqs failed");
     842                 :            :                 err = -ENOMEM;
     843                 :          0 :                 goto alloc_wqs_err;
     844                 :            :         }
     845                 :            : 
     846                 :            :         memset(cmdq_pool_name, 0, RTE_MEMPOOL_NAMESIZE);
     847                 :          0 :         snprintf(cmdq_pool_name, sizeof(cmdq_pool_name), "hinic3_cmdq_%u",
     848                 :          0 :                        hwdev->port_id);
     849                 :            : 
     850                 :          0 :         cmdqs->cmd_buf_pool = rte_pktmbuf_pool_create(cmdq_pool_name,
     851                 :            :                 HINIC3_CMDQ_DEPTH * HINIC3_MAX_CMDQ_TYPES, 0, 0,
     852                 :          0 :                 HINIC3_CMDQ_BUF_SIZE, (int)rte_socket_id());
     853         [ #  # ]:          0 :         if (!cmdqs->cmd_buf_pool) {
     854                 :          0 :                 PMD_DRV_LOG(ERR, "Create cmdq buffer pool failed");
     855                 :            :                 err = -ENOMEM;
     856                 :          0 :                 goto pool_create_err;
     857                 :            :         }
     858                 :            : 
     859                 :          0 :         err = hinic3_cmdq_alloc(cmdqs->saved_wqs, hwdev, HINIC3_MAX_CMDQ_TYPES,
     860                 :            :                                 HINIC3_CMDQ_WQ_BUF_SIZE, CMDQ_WQEBB_SHIFT,
     861                 :            :                                 HINIC3_CMDQ_DEPTH);
     862         [ #  # ]:          0 :         if (err) {
     863                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate cmdq failed");
     864                 :          0 :                 goto cmdq_alloc_err;
     865                 :            :         }
     866                 :            : 
     867                 :          0 :         err = hinic3_set_cmdqs(hwdev, cmdqs);
     868         [ #  # ]:          0 :         if (err) {
     869                 :          0 :                 PMD_DRV_LOG(ERR, "set_cmdqs failed");
     870                 :          0 :                 goto cmdq_alloc_err;
     871                 :            :         }
     872                 :            :         return 0;
     873                 :            : 
     874                 :          0 : cmdq_alloc_err:
     875                 :          0 :         rte_mempool_free(cmdqs->cmd_buf_pool);
     876                 :            : 
     877                 :          0 : pool_create_err:
     878                 :          0 :         rte_free(cmdqs->saved_wqs);
     879                 :            : 
     880                 :          0 : alloc_wqs_err:
     881                 :          0 :         rte_free(cmdqs);
     882                 :            : 
     883                 :          0 :         return err;
     884                 :            : }
     885                 :            : 
     886                 :            : void
     887                 :          0 : hinic3_free_cmdqs(struct hinic3_hwdev *hwdev)
     888                 :            : {
     889                 :          0 :         struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
     890                 :            :         enum hinic3_cmdq_type cmdq_type = HINIC3_CMDQ_SYNC;
     891                 :            : 
     892                 :          0 :         cmdqs->status &= ~HINIC3_CMDQ_ENABLE;
     893                 :            : 
     894         [ #  # ]:          0 :         for (; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++)
     895                 :            :                 free_cmdq(&cmdqs->cmdq[cmdq_type]);
     896                 :            : 
     897                 :          0 :         hinic3_cmdq_free(cmdqs->saved_wqs, HINIC3_MAX_CMDQ_TYPES);
     898                 :          0 :         rte_mempool_free(cmdqs->cmd_buf_pool);
     899                 :          0 :         rte_free(cmdqs->saved_wqs);
     900                 :          0 :         rte_free(cmdqs);
     901                 :          0 : }
     902                 :            : 
     903                 :            : static int
     904                 :          0 : hinic3_cmdq_poll_msg(struct hinic3_cmdq *cmdq, uint32_t timeout)
     905                 :            : {
     906                 :            :         struct hinic3_cmdq_wqe *wqe = NULL;
     907                 :            :         struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = NULL;
     908                 :            :         struct hinic3_ctrl *ctrl = NULL;
     909                 :            :         struct hinic3_cmdq_cmd_info *cmd_info = NULL;
     910                 :            :         uint32_t status_info, ctrl_info;
     911                 :            :         uint16_t ci;
     912                 :            :         int errcode;
     913                 :            :         uint64_t end;
     914                 :            :         int done = 0;
     915                 :            :         int err = 0;
     916                 :            : 
     917                 :          0 :         wqe = hinic3_read_wqe(cmdq->wq, 1, &ci);
     918         [ #  # ]:          0 :         if (!wqe) {
     919                 :          0 :                 PMD_DRV_LOG(ERR, "No outstanding cmdq msg");
     920                 :          0 :                 return -EINVAL;
     921                 :            :         }
     922                 :            : 
     923                 :          0 :         cmd_info = &cmdq->cmd_infos[ci];
     924         [ #  # ]:          0 :         if (cmd_info->cmd_type == HINIC3_CMD_TYPE_NONE) {
     925                 :          0 :                 PMD_DRV_LOG(ERR,
     926                 :            :                             "Cmdq msg has not been filled and send to hw, or get TMO msg ack. cmdq ci: %u",
     927                 :            :                             ci);
     928                 :          0 :                 return -EINVAL;
     929                 :            :         }
     930                 :            : 
     931                 :            :         /* Only arm bit is using scmd wqe, the wqe is lcmd. */
     932                 :            :         wqe_lcmd = &wqe->wqe_lcmd;
     933                 :            :         ctrl = &wqe_lcmd->ctrl;
     934                 :          0 :         end = cycles + msecs_to_cycles(timeout);
     935                 :            :         do {
     936                 :          0 :                 ctrl_info = hinic3_hw_cpu32((ctrl)->ctrl_info);
     937         [ #  # ]:          0 :                 if (WQE_COMPLETED(ctrl_info)) {
     938                 :            :                         done = 1;
     939                 :            :                         break;
     940                 :            :                 }
     941                 :            : 
     942                 :          0 :                 rte_delay_us(1);
     943         [ #  # ]:          0 :         } while (time_before(cycles, end));
     944                 :            : 
     945         [ #  # ]:          0 :         if (done) {
     946                 :          0 :                 status_info = hinic3_hw_cpu32(wqe_lcmd->status.status_info);
     947                 :          0 :                 errcode = WQE_ERRCODE_GET(status_info, VAL);
     948                 :          0 :                 cmdq_update_errcode(cmdq, ci, errcode);
     949                 :          0 :                 clear_wqe_complete_bit(cmdq, wqe);
     950                 :            :                 err = 0;
     951                 :            :         } else {
     952                 :          0 :                 PMD_DRV_LOG(ERR, "Poll cmdq msg time out, ci: %u", ci);
     953                 :            :                 err = -ETIMEDOUT;
     954                 :            :         }
     955                 :            : 
     956                 :            :         /* Set this cmd invalid. */
     957                 :          0 :         cmd_info->cmd_type = HINIC3_CMD_TYPE_NONE;
     958                 :            : 
     959                 :          0 :         return err;
     960                 :            : }

Generated by: LCOV version 1.14