LCOV - code coverage report
Current view: top level - drivers/net/hinic/base - hinic_pmd_mgmt.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 277 0.0 %
Date: 2024-01-22 15:55:54 Functions: 0 19 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 121 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2017 Huawei Technologies Co., Ltd
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "hinic_compat.h"
       6                 :            : #include "hinic_csr.h"
       7                 :            : #include "hinic_pmd_hwdev.h"
       8                 :            : #include "hinic_pmd_hwif.h"
       9                 :            : #include "hinic_pmd_mgmt.h"
      10                 :            : #include "hinic_pmd_mbox.h"
      11                 :            : 
      12                 :            : #define BUF_OUT_DEFAULT_SIZE            1
      13                 :            : 
      14                 :            : #define MAX_PF_MGMT_BUF_SIZE            2048UL
      15                 :            : 
      16                 :            : #define MGMT_MSG_SIZE_MIN               20
      17                 :            : #define MGMT_MSG_SIZE_STEP              16
      18                 :            : #define MGMT_MSG_RSVD_FOR_DEV           8
      19                 :            : 
      20                 :            : #define MGMT_MSG_TIMEOUT                5000    /* millisecond */
      21                 :            : 
      22                 :            : #define SYNC_MSG_ID_MASK                0x1FF
      23                 :            : #define ASYNC_MSG_ID_MASK               0x1FF
      24                 :            : #define ASYNC_MSG_FLAG                  0x200
      25                 :            : 
      26                 :            : #define MSG_NO_RESP                     0xFFFF
      27                 :            : 
      28                 :            : #define MAX_MSG_SZ                      2016
      29                 :            : 
      30                 :            : #define MSG_SZ_IS_VALID(in_size)        ((in_size) <= MAX_MSG_SZ)
      31                 :            : 
      32                 :            : #define SYNC_MSG_ID(pf_to_mgmt)         ((pf_to_mgmt)->sync_msg_id)
      33                 :            : 
      34                 :            : #define SYNC_MSG_ID_INC(pf_to_mgmt)     (SYNC_MSG_ID(pf_to_mgmt) = \
      35                 :            :                         (SYNC_MSG_ID(pf_to_mgmt) + 1) & SYNC_MSG_ID_MASK)
      36                 :            : 
      37                 :            : #define ASYNC_MSG_ID(pf_to_mgmt)        ((pf_to_mgmt)->async_msg_id)
      38                 :            : 
      39                 :            : #define ASYNC_MSG_ID_INC(pf_to_mgmt)    (ASYNC_MSG_ID(pf_to_mgmt) = \
      40                 :            :                         ((ASYNC_MSG_ID(pf_to_mgmt) + 1) & ASYNC_MSG_ID_MASK) \
      41                 :            :                         | ASYNC_MSG_FLAG)
      42                 :            : 
      43                 :            : #define HINIC_SEQ_ID_MAX_VAL            42
      44                 :            : #define HINIC_MSG_SEG_LEN               48
      45                 :            : 
      46                 :            : #define GET_CURR_AEQ_ELEM(eq)           GET_AEQ_ELEM((eq), (eq)->cons_idx)
      47                 :            : 
      48                 :            : #define EQ_ELEM_DESC_TYPE_SHIFT                 0
      49                 :            : #define EQ_ELEM_DESC_SRC_SHIFT                  7
      50                 :            : #define EQ_ELEM_DESC_SIZE_SHIFT                 8
      51                 :            : #define EQ_ELEM_DESC_WRAPPED_SHIFT              31
      52                 :            : 
      53                 :            : #define EQ_ELEM_DESC_TYPE_MASK                  0x7FU
      54                 :            : #define EQ_ELEM_DESC_SRC_MASK                   0x1U
      55                 :            : #define EQ_ELEM_DESC_SIZE_MASK                  0xFFU
      56                 :            : #define EQ_ELEM_DESC_WRAPPED_MASK               0x1U
      57                 :            : 
      58                 :            : #define EQ_MSIX_RESEND_TIMER_CLEAR              1
      59                 :            : 
      60                 :            : #define EQ_ELEM_DESC_GET(val, member)           \
      61                 :            :                                 (((val) >> EQ_ELEM_DESC_##member##_SHIFT) & \
      62                 :            :                                 EQ_ELEM_DESC_##member##_MASK)
      63                 :            : 
      64                 :            : #define HINIC_MGMT_CHANNEL_STATUS_SHIFT         0x0
      65                 :            : #define HINIC_MGMT_CHANNEL_STATUS_MASK          0x1
      66                 :            : 
      67                 :            : #define HINIC_GET_MGMT_CHANNEL_STATUS(val, member)      \
      68                 :            :         (((val) >> HINIC_##member##_SHIFT) & HINIC_##member##_MASK)
      69                 :            : 
      70                 :            : #define HINIC_MSG_TO_MGMT_MAX_LEN               2016
      71                 :            : 
      72                 :            : /**
      73                 :            :  * mgmt_msg_len - calculate the total message length
      74                 :            :  * @msg_data_len: the length of the message data
      75                 :            :  * Return: the total message length
      76                 :            :  */
      77                 :            : static u16 mgmt_msg_len(u16 msg_data_len)
      78                 :            : {
      79                 :            :         /* u64 - the size of the header */
      80                 :          0 :         u16 msg_size = (u16)(MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) +
      81                 :            :                              msg_data_len);
      82                 :            : 
      83                 :          0 :         if (msg_size > MGMT_MSG_SIZE_MIN)
      84                 :          0 :                 msg_size = MGMT_MSG_SIZE_MIN +
      85                 :          0 :                         ALIGN((msg_size - MGMT_MSG_SIZE_MIN),
      86                 :            :                               MGMT_MSG_SIZE_STEP);
      87                 :            :         else
      88                 :            :                 msg_size = MGMT_MSG_SIZE_MIN;
      89                 :            : 
      90                 :            :         return msg_size;
      91                 :            : }
      92                 :            : 
      93                 :            : /**
      94                 :            :  * prepare_header - prepare the header of the message
      95                 :            :  * @pf_to_mgmt: PF to MGMT channel
      96                 :            :  * @header: pointer of the header to prepare
      97                 :            :  * @msg_len: the length of the message
      98                 :            :  * @mod: module in the chip that will get the message
      99                 :            :  * @ack_type: the type to response
     100                 :            :  * @direction: the direction of the original message
     101                 :            :  * @cmd: the command to do
     102                 :            :  * @msg_id: message id
     103                 :            :  */
     104                 :          0 : static void prepare_header(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
     105                 :            :                            u64 *header, int msg_len, enum hinic_mod_type mod,
     106                 :            :                            enum hinic_msg_ack_type ack_type,
     107                 :            :                            enum hinic_msg_direction_type direction,
     108                 :            :                            u8 cmd, u32 msg_id)
     109                 :            : {
     110                 :          0 :         struct hinic_hwif *hwif = pf_to_mgmt->hwdev->hwif;
     111                 :            : 
     112                 :          0 :         *header = HINIC_MSG_HEADER_SET(msg_len, MSG_LEN) |
     113                 :          0 :                 HINIC_MSG_HEADER_SET(mod, MODULE) |
     114                 :          0 :                 HINIC_MSG_HEADER_SET(msg_len, SEG_LEN) |
     115                 :          0 :                 HINIC_MSG_HEADER_SET(ack_type, NO_ACK) |
     116                 :          0 :                 HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) |
     117                 :            :                 HINIC_MSG_HEADER_SET(0, SEQID) |
     118                 :          0 :                 HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST) |
     119                 :          0 :                 HINIC_MSG_HEADER_SET(direction, DIRECTION) |
     120                 :          0 :                 HINIC_MSG_HEADER_SET(cmd, CMD) |
     121                 :          0 :                 HINIC_MSG_HEADER_SET(HINIC_PCI_INTF_IDX(hwif), PCI_INTF_IDX) |
     122                 :          0 :                 HINIC_MSG_HEADER_SET(hwif->attr.port_to_port_idx, P2P_IDX) |
     123                 :          0 :                 HINIC_MSG_HEADER_SET(msg_id, MSG_ID);
     124                 :          0 : }
     125                 :            : 
     126                 :            : /**
     127                 :            :  * prepare_mgmt_cmd - prepare the mgmt command
     128                 :            :  * @mgmt_cmd: pointer to the command to prepare
     129                 :            :  * @header: pointer of the header to prepare
     130                 :            :  * @msg: the data of the message
     131                 :            :  * @msg_len: the length of the message
     132                 :            :  */
     133                 :          0 : static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, void *msg,
     134                 :            :                              int msg_len)
     135                 :            : {
     136                 :            :         memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
     137                 :            : 
     138                 :          0 :         mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;
     139                 :            :         memcpy(mgmt_cmd, header, sizeof(*header));
     140                 :            : 
     141                 :          0 :         mgmt_cmd += sizeof(*header);
     142                 :          0 :         memcpy(mgmt_cmd, msg, msg_len);
     143                 :          0 : }
     144                 :            : 
     145                 :            : /**
     146                 :            :  * alloc_recv_msg - allocate received message memory
     147                 :            :  * @recv_msg: pointer that will hold the allocated data
     148                 :            :  * Return: 0 - success, negative - failure
     149                 :            :  */
     150                 :          0 : static int alloc_recv_msg(struct hinic_recv_msg *recv_msg)
     151                 :            : {
     152                 :            :         int err;
     153                 :            : 
     154                 :          0 :         recv_msg->msg = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
     155         [ #  # ]:          0 :         if (!recv_msg->msg) {
     156                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate recv msg buf failed");
     157                 :          0 :                 return -ENOMEM;
     158                 :            :         }
     159                 :            : 
     160                 :          0 :         recv_msg->buf_out = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
     161         [ #  # ]:          0 :         if (!recv_msg->buf_out) {
     162                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate recv msg output buf failed");
     163                 :            :                 err = -ENOMEM;
     164                 :          0 :                 goto alloc_buf_out_err;
     165                 :            :         }
     166                 :            : 
     167                 :            :         return 0;
     168                 :            : 
     169                 :            : alloc_buf_out_err:
     170                 :          0 :         kfree(recv_msg->msg);
     171                 :          0 :         return err;
     172                 :            : }
     173                 :            : 
     174                 :            : /**
     175                 :            :  * free_recv_msg - free received message memory
     176                 :            :  * @recv_msg: pointer that holds the allocated data
     177                 :            :  */
     178                 :            : static void free_recv_msg(struct hinic_recv_msg *recv_msg)
     179                 :            : {
     180                 :          0 :         kfree(recv_msg->buf_out);
     181                 :          0 :         kfree(recv_msg->msg);
     182                 :          0 : }
     183                 :            : 
     184                 :            : /**
     185                 :            :  * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
     186                 :            :  * @pf_to_mgmt: PF to MGMT channel
     187                 :            :  * Return: 0 - success, negative - failure
     188                 :            :  */
     189                 :          0 : static int alloc_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt)
     190                 :            : {
     191                 :            :         int err;
     192                 :            : 
     193                 :          0 :         err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
     194         [ #  # ]:          0 :         if (err) {
     195                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate recv msg failed");
     196                 :          0 :                 return err;
     197                 :            :         }
     198                 :            : 
     199                 :          0 :         err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
     200         [ #  # ]:          0 :         if (err) {
     201                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate resp recv msg failed");
     202                 :          0 :                 goto alloc_msg_for_resp_err;
     203                 :            :         }
     204                 :            : 
     205                 :          0 :         pf_to_mgmt->async_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
     206         [ #  # ]:          0 :         if (!pf_to_mgmt->async_msg_buf)      {
     207                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate async msg buf failed");
     208                 :            :                 err = -ENOMEM;
     209                 :          0 :                 goto async_msg_buf_err;
     210                 :            :         }
     211                 :            : 
     212                 :          0 :         pf_to_mgmt->sync_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
     213         [ #  # ]:          0 :         if (!pf_to_mgmt->sync_msg_buf)       {
     214                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate sync msg buf failed");
     215                 :            :                 err = -ENOMEM;
     216                 :          0 :                 goto sync_msg_buf_err;
     217                 :            :         }
     218                 :            : 
     219                 :            :         return 0;
     220                 :            : 
     221                 :            : sync_msg_buf_err:
     222                 :          0 :         kfree(pf_to_mgmt->async_msg_buf);
     223                 :            : 
     224                 :          0 : async_msg_buf_err:
     225                 :            :         free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
     226                 :            : 
     227                 :          0 : alloc_msg_for_resp_err:
     228                 :            :         free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
     229                 :            : 
     230                 :          0 :         return err;
     231                 :            : }
     232                 :            : 
     233                 :            : /**
     234                 :            :  * free_msg_buf - free all the message buffers of PF to MGMT channel
     235                 :            :  * @pf_to_mgmt: PF to MGMT channel
     236                 :            :  * Return: 0 - success, negative - failure
     237                 :            :  */
     238                 :          0 : static void free_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt)
     239                 :            : {
     240                 :          0 :         kfree(pf_to_mgmt->sync_msg_buf);
     241                 :          0 :         kfree(pf_to_mgmt->async_msg_buf);
     242                 :            : 
     243                 :            :         free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
     244                 :            :         free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
     245                 :          0 : }
     246                 :            : 
     247                 :            : static int hinic_get_mgmt_channel_status(void *hwdev)
     248                 :            : {
     249                 :          0 :         struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
     250                 :            :         u32 val;
     251                 :            : 
     252         [ #  # ]:          0 :         if (hinic_func_type((struct hinic_hwdev *)hwdev) == TYPE_VF)
     253                 :            :                 return false;
     254                 :            : 
     255                 :            :         val = hinic_hwif_read_reg(hwif, HINIC_ICPL_RESERVD_ADDR);
     256                 :            : 
     257                 :          0 :         return HINIC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
     258                 :            : }
     259                 :            : 
     260                 :            : /**
     261                 :            :  * send_msg_to_mgmt_async - send async message
     262                 :            :  * @pf_to_mgmt: PF to MGMT channel
     263                 :            :  * @mod: module in the chip that will get the message
     264                 :            :  * @cmd: command of the message
     265                 :            :  * @msg: the data of the message
     266                 :            :  * @msg_len: the length of the message
     267                 :            :  * @direction: the direction of the original message
     268                 :            :  * @resp_msg_id: message id of response
     269                 :            :  * Return: 0 - success, negative - failure
     270                 :            :  */
     271                 :          0 : static int send_msg_to_mgmt_async(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
     272                 :            :                                   enum hinic_mod_type mod, u8 cmd,
     273                 :            :                                   void *msg, u16 msg_len,
     274                 :            :                                   enum hinic_msg_direction_type direction,
     275                 :            :                                   u16 resp_msg_id)
     276                 :            : {
     277                 :          0 :         void *mgmt_cmd = pf_to_mgmt->async_msg_buf;
     278                 :            :         struct hinic_api_cmd_chain *chain;
     279                 :            :         u64 header;
     280         [ #  # ]:          0 :         u16 cmd_size = mgmt_msg_len(msg_len);
     281                 :            : 
     282         [ #  # ]:          0 :         if (direction == HINIC_MSG_RESPONSE)
     283                 :          0 :                 prepare_header(pf_to_mgmt, &header, msg_len, mod, HINIC_MSG_ACK,
     284                 :            :                                direction, cmd, resp_msg_id);
     285                 :            :         else
     286                 :          0 :                 prepare_header(pf_to_mgmt, &header, msg_len, mod, HINIC_MSG_ACK,
     287                 :          0 :                                direction, cmd, ASYNC_MSG_ID(pf_to_mgmt));
     288                 :            : 
     289                 :          0 :         prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len);
     290                 :            : 
     291                 :          0 :         chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU];
     292                 :            : 
     293                 :          0 :         return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT_HOST, mgmt_cmd,
     294                 :            :                                    cmd_size);
     295                 :            : }
     296                 :            : 
     297                 :            : /**
     298                 :            :  * send_msg_to_mgmt_sync - send async message
     299                 :            :  * @pf_to_mgmt: PF to MGMT channel
     300                 :            :  * @mod: module in the chip that will get the message
     301                 :            :  * @cmd: command of the message
     302                 :            :  * @msg: the msg data
     303                 :            :  * @msg_len: the msg data length
     304                 :            :  * @ack_type: indicate mgmt command whether need ack or not
     305                 :            :  * @direction: the direction of the original message
     306                 :            :  * @resp_msg_id: msg id to response for
     307                 :            :  * Return: 0 - success, negative - failure
     308                 :            :  */
     309                 :          0 : static int send_msg_to_mgmt_sync(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
     310                 :            :                                  enum hinic_mod_type mod, u8 cmd,
     311                 :            :                                  void *msg, u16 msg_len,
     312                 :            :                                  enum hinic_msg_ack_type ack_type,
     313                 :            :                                  enum hinic_msg_direction_type direction,
     314                 :            :                                  __rte_unused u16 resp_msg_id)
     315                 :            : {
     316                 :          0 :         void *mgmt_cmd = pf_to_mgmt->sync_msg_buf;
     317                 :            :         struct hinic_api_cmd_chain *chain;
     318                 :            :         u64 header;
     319         [ #  # ]:          0 :         u16 cmd_size = mgmt_msg_len(msg_len);
     320                 :            : 
     321                 :            :         /* If fw is hot active, return failed */
     322         [ #  # ]:          0 :         if (hinic_get_mgmt_channel_status(pf_to_mgmt->hwdev)) {
     323         [ #  # ]:          0 :                 if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC)
     324                 :            :                         return HINIC_DEV_BUSY_ACTIVE_FW;
     325                 :            :                 else
     326                 :          0 :                         return -EBUSY;
     327                 :            :         }
     328                 :            : 
     329         [ #  # ]:          0 :         if (direction == HINIC_MSG_RESPONSE)
     330                 :          0 :                 prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
     331                 :            :                                direction, cmd, resp_msg_id);
     332                 :            :         else
     333                 :          0 :                 prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
     334                 :          0 :                                direction, cmd, SYNC_MSG_ID(pf_to_mgmt));
     335                 :            : 
     336                 :          0 :         prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len);
     337                 :            : 
     338                 :          0 :         chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_PMD_WRITE_TO_MGMT];
     339                 :            : 
     340                 :          0 :         return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT_HOST,
     341                 :            :                                    mgmt_cmd, cmd_size);
     342                 :            : }
     343                 :            : 
     344                 :            : /**
     345                 :            :  * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
     346                 :            :  * @hwdev: the pointer to the private hardware device object
     347                 :            :  * Return: 0 - success, negative - failure
     348                 :            :  */
     349                 :          0 : static int hinic_pf_to_mgmt_init(struct hinic_hwdev *hwdev)
     350                 :            : {
     351                 :            :         struct hinic_msg_pf_to_mgmt *pf_to_mgmt;
     352                 :            :         int err;
     353                 :            : 
     354                 :          0 :         pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL);
     355         [ #  # ]:          0 :         if (!pf_to_mgmt) {
     356                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate pf to mgmt mem failed");
     357                 :          0 :                 return -ENOMEM;
     358                 :            :         }
     359                 :            : 
     360                 :          0 :         hwdev->pf_to_mgmt = pf_to_mgmt;
     361                 :          0 :         pf_to_mgmt->hwdev = hwdev;
     362                 :            : 
     363                 :          0 :         err = hinic_mutex_init(&pf_to_mgmt->sync_msg_mutex, NULL);
     364         [ #  # ]:          0 :         if (err)
     365                 :          0 :                 goto mutex_init_err;
     366                 :            : 
     367                 :          0 :         err = alloc_msg_buf(pf_to_mgmt);
     368         [ #  # ]:          0 :         if (err) {
     369                 :          0 :                 PMD_DRV_LOG(ERR, "Allocate msg buffers failed");
     370                 :          0 :                 goto alloc_msg_buf_err;
     371                 :            :         }
     372                 :            : 
     373                 :          0 :         err = hinic_api_cmd_init(hwdev, pf_to_mgmt->cmd_chain);
     374         [ #  # ]:          0 :         if (err) {
     375                 :          0 :                 PMD_DRV_LOG(ERR, "Init the api cmd chains failed");
     376                 :          0 :                 goto api_cmd_init_err;
     377                 :            :         }
     378                 :            : 
     379                 :            :         return 0;
     380                 :            : 
     381                 :            : api_cmd_init_err:
     382                 :          0 :         free_msg_buf(pf_to_mgmt);
     383                 :            : 
     384                 :          0 : alloc_msg_buf_err:
     385                 :          0 :         hinic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex);
     386                 :            : 
     387                 :          0 : mutex_init_err:
     388                 :          0 :         kfree(pf_to_mgmt);
     389                 :            : 
     390                 :          0 :         return err;
     391                 :            : }
     392                 :            : 
     393                 :            : /**
     394                 :            :  * hinic_pf_to_mgmt_free - free PF to MGMT channel
     395                 :            :  * @hwdev: the pointer to the private hardware device object
     396                 :            :  */
     397                 :          0 : static void hinic_pf_to_mgmt_free(struct hinic_hwdev *hwdev)
     398                 :            : {
     399                 :          0 :         struct hinic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
     400                 :            : 
     401                 :          0 :         hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
     402                 :          0 :         free_msg_buf(pf_to_mgmt);
     403                 :          0 :         hinic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex);
     404                 :          0 :         kfree(pf_to_mgmt);
     405                 :          0 : }
     406                 :            : 
     407                 :            : static int
     408                 :          0 : hinic_pf_to_mgmt_sync(struct hinic_hwdev *hwdev,
     409                 :            :                 enum hinic_mod_type mod, u8 cmd, void *buf_in, u16 in_size,
     410                 :            :                 void *buf_out, u16 *out_size, u32 timeout)
     411                 :            : {
     412                 :          0 :         struct hinic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
     413                 :            :         struct hinic_recv_msg *recv_msg;
     414                 :            :         u32 timeo;
     415                 :            :         int err, i;
     416                 :            : 
     417                 :          0 :         err = hinic_mutex_lock(&pf_to_mgmt->sync_msg_mutex);
     418         [ #  # ]:          0 :         if (err)
     419                 :            :                 return err;
     420                 :            : 
     421                 :          0 :         SYNC_MSG_ID_INC(pf_to_mgmt);
     422                 :            :         recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
     423                 :            : 
     424                 :          0 :         err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
     425                 :            :                                     HINIC_MSG_ACK, HINIC_MSG_DIRECT_SEND,
     426                 :            :                                     MSG_NO_RESP);
     427         [ #  # ]:          0 :         if (err) {
     428                 :          0 :                 PMD_DRV_LOG(ERR, "Send msg to mgmt failed");
     429                 :          0 :                 goto unlock_sync_msg;
     430                 :            :         }
     431                 :            : 
     432         [ #  # ]:          0 :         timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
     433         [ #  # ]:          0 :         for (i = 0; i < pf_to_mgmt->rx_aeq->poll_retry_nr; i++) {
     434                 :          0 :                 err = hinic_aeq_poll_msg(pf_to_mgmt->rx_aeq, timeo, NULL);
     435         [ #  # ]:          0 :                 if (err) {
     436                 :          0 :                         PMD_DRV_LOG(ERR, "Poll mgmt rsp timeout, mod=%d cmd=%d msg_id=%u rc=%d",
     437                 :            :                                 mod, cmd, pf_to_mgmt->sync_msg_id, err);
     438                 :            :                         err = -ETIMEDOUT;
     439                 :          0 :                         hinic_dump_aeq_info(hwdev);
     440                 :          0 :                         goto unlock_sync_msg;
     441                 :            :                 } else {
     442   [ #  #  #  # ]:          0 :                         if (mod == recv_msg->mod && cmd == recv_msg->cmd &&
     443         [ #  # ]:          0 :                             recv_msg->msg_id == pf_to_mgmt->sync_msg_id) {
     444                 :            :                                 /* the expected response polled */
     445                 :            :                                 break;
     446                 :            :                         }
     447                 :          0 :                         PMD_DRV_LOG(ERR, "AEQ[%d] poll(mod=%d, cmd=%d, msg_id=%u) an "
     448                 :            :                                 "unexpected(mod=%d, cmd=%d, msg_id=%u) response",
     449                 :            :                                 pf_to_mgmt->rx_aeq->q_id, mod, cmd,
     450                 :            :                                 pf_to_mgmt->sync_msg_id, recv_msg->mod,
     451                 :            :                                 recv_msg->cmd, recv_msg->msg_id);
     452                 :            :                 }
     453                 :            :         }
     454                 :            : 
     455         [ #  # ]:          0 :         if (i == pf_to_mgmt->rx_aeq->poll_retry_nr) {
     456                 :          0 :                 PMD_DRV_LOG(ERR, "Get %d unexpected mgmt rsp from AEQ[%d], poll mgmt rsp failed",
     457                 :            :                         i, pf_to_mgmt->rx_aeq->q_id);
     458                 :            :                 err = -EBADMSG;
     459                 :          0 :                 goto unlock_sync_msg;
     460                 :            :         }
     461                 :            : 
     462                 :          0 :         rte_smp_rmb();
     463   [ #  #  #  # ]:          0 :         if (recv_msg->msg_len && buf_out && out_size) {
     464         [ #  # ]:          0 :                 if (recv_msg->msg_len <= *out_size) {
     465                 :          0 :                         memcpy(buf_out, recv_msg->msg,
     466                 :            :                                recv_msg->msg_len);
     467                 :          0 :                         *out_size = recv_msg->msg_len;
     468                 :            :                 } else {
     469                 :          0 :                         PMD_DRV_LOG(ERR, "Mgmt rsp's msg len: %u overflow.",
     470                 :            :                                 recv_msg->msg_len);
     471                 :            :                         err = -ERANGE;
     472                 :            :                 }
     473                 :            :         }
     474                 :            : 
     475                 :          0 : unlock_sync_msg:
     476         [ #  # ]:          0 :         if (err && out_size)
     477                 :          0 :                 *out_size = 0;
     478                 :            :         (void)hinic_mutex_unlock(&pf_to_mgmt->sync_msg_mutex);
     479                 :          0 :         return err;
     480                 :            : }
     481                 :            : 
     482                 :          0 : int hinic_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd,
     483                 :            :                            void *buf_in, u16 in_size,
     484                 :            :                            void *buf_out, u16 *out_size, u32 timeout)
     485                 :            : {
     486                 :            :         int rc = HINIC_ERROR;
     487                 :            : 
     488         [ #  # ]:          0 :         if (!hwdev || in_size > HINIC_MSG_TO_MGMT_MAX_LEN)
     489                 :            :                 return -EINVAL;
     490                 :            : 
     491         [ #  # ]:          0 :         if (hinic_func_type(hwdev) == TYPE_VF) {
     492                 :          0 :                 rc = hinic_mbox_to_pf(hwdev, mod, cmd, buf_in, in_size,
     493                 :            :                                         buf_out, out_size, timeout);
     494                 :            :         } else {
     495                 :          0 :                 rc = hinic_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size,
     496                 :            :                                                 buf_out, out_size, timeout);
     497                 :            :         }
     498                 :            : 
     499                 :            :         return rc;
     500                 :            : }
     501                 :            : 
     502                 :          0 : int hinic_msg_to_mgmt_no_ack(void *hwdev, enum hinic_mod_type mod, u8 cmd,
     503                 :            :                              void *buf_in, u16 in_size)
     504                 :            : {
     505                 :          0 :         struct hinic_msg_pf_to_mgmt *pf_to_mgmt =
     506                 :            :                                 ((struct hinic_hwdev *)hwdev)->pf_to_mgmt;
     507                 :            :         int err = -EINVAL;
     508                 :            : 
     509         [ #  # ]:          0 :         if (!MSG_SZ_IS_VALID(in_size)) {
     510                 :          0 :                 PMD_DRV_LOG(ERR, "Mgmt msg buffer size is invalid");
     511                 :          0 :                 return err;
     512                 :            :         }
     513                 :            : 
     514                 :          0 :         err = hinic_mutex_lock(&pf_to_mgmt->sync_msg_mutex);
     515         [ #  # ]:          0 :         if (err)
     516                 :            :                 return err;
     517                 :            : 
     518                 :          0 :         err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
     519                 :            :                                     HINIC_MSG_NO_ACK, HINIC_MSG_DIRECT_SEND,
     520                 :            :                                     MSG_NO_RESP);
     521                 :            : 
     522                 :            :         (void)hinic_mutex_unlock(&pf_to_mgmt->sync_msg_mutex);
     523                 :            : 
     524                 :          0 :         return err;
     525                 :            : }
     526                 :            : 
     527                 :            : static bool check_mgmt_seq_id_and_seg_len(struct hinic_recv_msg *recv_msg,
     528                 :            :                                           u8 seq_id, u8 seg_len, u16 msg_id)
     529                 :            : {
     530                 :          0 :         if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN)
     531                 :            :                 return false;
     532                 :            : 
     533         [ #  # ]:          0 :         if (seq_id == 0) {
     534                 :          0 :                 recv_msg->seq_id = seq_id;
     535                 :          0 :                 recv_msg->msg_id = msg_id;
     536                 :            :         } else {
     537         [ #  # ]:          0 :                 if ((seq_id != recv_msg->seq_id + 1) ||
     538         [ #  # ]:          0 :                         msg_id != recv_msg->msg_id) {
     539                 :          0 :                         recv_msg->seq_id = 0;
     540                 :            :                         return false;
     541                 :            :                 }
     542                 :          0 :                 recv_msg->seq_id = seq_id;
     543                 :            :         }
     544                 :            : 
     545                 :            :         return true;
     546                 :            : }
     547                 :            : 
     548                 :            : /**
     549                 :            :  * hinic_mgmt_recv_msg_handler - handler for message from mgmt cpu
     550                 :            :  * @pf_to_mgmt: PF to MGMT channel
     551                 :            :  * @recv_msg: received message details
     552                 :            :  * @param: customized parameter
     553                 :            :  */
     554                 :          0 : static void hinic_mgmt_recv_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
     555                 :            :                                         struct hinic_recv_msg *recv_msg,
     556                 :            :                                         void *param)
     557                 :            : {
     558                 :          0 :         void *buf_out = recv_msg->buf_out;
     559                 :          0 :         u16 out_size = 0;
     560                 :            : 
     561   [ #  #  #  # ]:          0 :         switch (recv_msg->mod) {
     562                 :          0 :         case HINIC_MOD_COMM:
     563                 :          0 :                 hinic_comm_async_event_handle(pf_to_mgmt->hwdev,
     564                 :          0 :                                               recv_msg->cmd, recv_msg->msg,
     565                 :          0 :                                               recv_msg->msg_len,
     566                 :            :                                               buf_out, &out_size);
     567                 :          0 :                 break;
     568                 :          0 :         case HINIC_MOD_L2NIC:
     569                 :          0 :                 hinic_l2nic_async_event_handle(pf_to_mgmt->hwdev, param,
     570                 :          0 :                                                recv_msg->cmd, recv_msg->msg,
     571                 :          0 :                                                recv_msg->msg_len,
     572                 :            :                                                buf_out, &out_size);
     573                 :          0 :                 break;
     574                 :          0 :         case HINIC_MOD_HILINK:
     575                 :          0 :                 hinic_hilink_async_event_handle(pf_to_mgmt->hwdev,
     576                 :          0 :                                                 recv_msg->cmd, recv_msg->msg,
     577                 :          0 :                                                 recv_msg->msg_len,
     578                 :            :                                                 buf_out, &out_size);
     579                 :          0 :                 break;
     580                 :          0 :         default:
     581                 :          0 :                 PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_msg->mod);
     582                 :          0 :                 break;
     583                 :            :         }
     584                 :            : 
     585         [ #  # ]:          0 :         if (!recv_msg->async_mgmt_to_pf) {
     586         [ #  # ]:          0 :                 if (!out_size)
     587                 :          0 :                         out_size = BUF_OUT_DEFAULT_SIZE;
     588                 :            : 
     589                 :            :                 /* MGMT sent sync msg, send the response */
     590                 :          0 :                 (void)send_msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod,
     591                 :          0 :                                              recv_msg->cmd, buf_out, out_size,
     592                 :            :                                              HINIC_MSG_RESPONSE,
     593                 :          0 :                                              recv_msg->msg_id);
     594                 :            :         }
     595                 :          0 : }
     596                 :            : 
     597                 :            : /**
     598                 :            :  * recv_mgmt_msg_handler - handler a message from mgmt cpu
     599                 :            :  * @pf_to_mgmt: PF to MGMT channel
     600                 :            :  * @header: the header of the message
     601                 :            :  * @recv_msg: received message details
     602                 :            :  * @param: customized parameter
     603                 :            :  * Return: 0 when aeq is response message, -1 default result,
     604                 :            :  * and when wrong message or not last message
     605                 :            :  */
     606                 :          0 : static int recv_mgmt_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
     607                 :            :                                  u8 *header, struct hinic_recv_msg *recv_msg,
     608                 :            :                                  void *param)
     609                 :            : {
     610                 :          0 :         u64 msg_header = *((u64 *)header);
     611                 :          0 :         void *msg_body = header + sizeof(msg_header);
     612                 :            :         u8 *dest_msg;
     613                 :            :         u8 seq_id, seq_len;
     614                 :            :         u8 front_id;
     615                 :            :         u16 msg_id;
     616                 :            : 
     617                 :          0 :         seq_id = HINIC_MSG_HEADER_GET(msg_header, SEQID);
     618                 :          0 :         seq_len = HINIC_MSG_HEADER_GET(msg_header, SEG_LEN);
     619                 :          0 :         front_id = recv_msg->seq_id;
     620                 :          0 :         msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID);
     621                 :            : 
     622         [ #  # ]:          0 :         if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len, msg_id)) {
     623                 :          0 :                 PMD_DRV_LOG(ERR,
     624                 :            :                         "Mgmt msg sequence and segment check failed, "
     625                 :            :                         "func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x "
     626                 :            :                         "front msg_id: %d, cur msg_id: %d",
     627                 :            :                         hinic_global_func_id(pf_to_mgmt->hwdev),
     628                 :            :                         front_id, seq_id, seq_len, recv_msg->msg_id, msg_id);
     629                 :          0 :                 return HINIC_ERROR;
     630                 :            :         }
     631                 :            : 
     632                 :          0 :         dest_msg = (u8 *)recv_msg->msg + seq_id * HINIC_MSG_SEG_LEN;
     633         [ #  # ]:          0 :         memcpy(dest_msg, msg_body, seq_len);
     634                 :            : 
     635         [ #  # ]:          0 :         if (!HINIC_MSG_HEADER_GET(msg_header, LAST))
     636                 :            :                 return HINIC_ERROR;
     637                 :            : 
     638                 :          0 :         recv_msg->cmd = HINIC_MSG_HEADER_GET(msg_header, CMD);
     639                 :          0 :         recv_msg->mod = HINIC_MSG_HEADER_GET(msg_header, MODULE);
     640                 :          0 :         recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(msg_header,
     641                 :            :                                                           ASYNC_MGMT_TO_PF);
     642                 :          0 :         recv_msg->msg_len = HINIC_MSG_HEADER_GET(msg_header, MSG_LEN);
     643                 :          0 :         recv_msg->msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID);
     644                 :            : 
     645         [ #  # ]:          0 :         if (HINIC_MSG_HEADER_GET(msg_header, DIRECTION) == HINIC_MSG_RESPONSE)
     646                 :            :                 return HINIC_OK;
     647                 :            : 
     648                 :          0 :         hinic_mgmt_recv_msg_handler(pf_to_mgmt, recv_msg, param);
     649                 :            : 
     650                 :          0 :         return HINIC_ERROR;
     651                 :            : }
     652                 :            : 
     653                 :            : /**
     654                 :            :  * hinic_mgmt_msg_aeqe_handler - handler for a mgmt message event
     655                 :            :  * @hwdev: the pointer to the private hardware device object
     656                 :            :  * @header: the header of the message
     657                 :            :  * @size: unused
     658                 :            :  * @param: customized parameter
     659                 :            :  * Return: 0 when aeq is response message,
     660                 :            :  *         -1 default result, and when wrong message or not last message
     661                 :            :  */
     662                 :            : static int hinic_mgmt_msg_aeqe_handler(void *hwdev, u8 *header,
     663                 :            :                         __rte_unused u8 size, void *param)
     664                 :            : {
     665                 :          0 :         struct hinic_msg_pf_to_mgmt *pf_to_mgmt =
     666                 :            :                                 ((struct hinic_hwdev *)hwdev)->pf_to_mgmt;
     667                 :            :         struct hinic_recv_msg *recv_msg;
     668                 :            : 
     669                 :          0 :         recv_msg = (HINIC_MSG_HEADER_GET(*(u64 *)header, DIRECTION) ==
     670                 :            :                     HINIC_MSG_DIRECT_SEND) ?
     671                 :          0 :                     &pf_to_mgmt->recv_msg_from_mgmt :
     672                 :            :                     &pf_to_mgmt->recv_resp_msg_from_mgmt;
     673                 :            : 
     674                 :          0 :         return recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg, param);
     675                 :            : }
     676                 :            : 
     677                 :          0 : static int hinic_handle_aeqe(void *handle, enum hinic_aeq_type event,
     678                 :            :                       u8 *data, u8 size, void *param)
     679                 :            : {
     680                 :            :         int rc = 0;
     681                 :            : 
     682      [ #  #  # ]:          0 :         switch (event) {
     683         [ #  # ]:          0 :         case HINIC_MSG_FROM_MGMT_CPU:
     684                 :            :                 rc = hinic_mgmt_msg_aeqe_handler(handle, data, size, param);
     685                 :          0 :                 break;
     686                 :          0 :         case HINIC_MBX_FROM_FUNC:
     687                 :          0 :                 rc = hinic_mbox_func_aeqe_handler(handle, data, size, param);
     688                 :          0 :                 break;
     689                 :          0 :         default:
     690                 :          0 :                 PMD_DRV_LOG(ERR, "Unknown event type: 0x%x, size: %d",
     691                 :            :                             event, size);
     692                 :            :                 rc = HINIC_ERROR;
     693                 :          0 :                 break;
     694                 :            :         }
     695                 :            : 
     696                 :          0 :         return rc;
     697                 :            : }
     698                 :            : 
     699                 :            : /**
     700                 :            :  * hinic_aeq_poll_msg - poll one or continue aeqe, and call dedicated process
     701                 :            :  * @eq: aeq of the chip
     702                 :            :  * @timeout: 0   - poll all aeqe in eq, used in interrupt mode,
     703                 :            :  *           > 0 - poll aeq until get aeqe with 'last' field set to 1,
     704                 :            :  *           used in polling mode.
     705                 :            :  * @param: customized parameter
     706                 :            :  * Return: 0 - Success, EIO - poll timeout, ENODEV - swe not support
     707                 :            :  */
     708                 :          0 : int hinic_aeq_poll_msg(struct hinic_eq *eq, u32 timeout, void *param)
     709                 :            : {
     710                 :            :         struct hinic_aeq_elem *aeqe_pos;
     711                 :            :         enum hinic_aeq_type event;
     712                 :            :         u32 aeqe_desc = 0;
     713                 :            :         u16 i;
     714                 :            :         u8 size;
     715                 :            :         int done = HINIC_ERROR;
     716                 :            :         int err = -EFAULT;
     717                 :            :         unsigned long end;
     718                 :            : 
     719   [ #  #  #  # ]:          0 :         for (i = 0; ((timeout == 0) && (i < eq->eq_len)) ||
     720         [ #  # ]:          0 :              ((timeout > 0) && (done != HINIC_OK) && (i < eq->eq_len)); i++) {
     721                 :            :                 err = -EIO;
     722                 :          0 :                 end = jiffies + msecs_to_jiffies(timeout);
     723                 :            :                 do {
     724                 :          0 :                         aeqe_pos = GET_CURR_AEQ_ELEM(eq);
     725                 :            :                         rte_rmb();
     726                 :            : 
     727                 :            :                         /* Data in HW is in Big endian Format */
     728         [ #  # ]:          0 :                         aeqe_desc = be32_to_cpu(aeqe_pos->desc);
     729                 :            : 
     730                 :            :                         /* HW updates wrapped bit,
     731                 :            :                          * when it adds eq element event
     732                 :            :                          */
     733                 :          0 :                         if (EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED)
     734         [ #  # ]:          0 :                             != eq->wrapped) {
     735                 :            :                                 err = 0;
     736                 :            :                                 break;
     737                 :            :                         }
     738                 :            : 
     739         [ #  # ]:          0 :                         if (timeout != 0)
     740                 :          0 :                                 usleep(1000);
     741         [ #  # ]:          0 :                 } while (time_before(jiffies, end));
     742                 :            : 
     743         [ #  # ]:          0 :                 if (err != HINIC_OK) /*poll time out*/
     744                 :            :                         break;
     745                 :            : 
     746                 :          0 :                 event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
     747         [ #  # ]:          0 :                 if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) {
     748                 :          0 :                         PMD_DRV_LOG(ERR, "AEQ sw event not support %d", event);
     749                 :          0 :                         return -ENODEV;
     750                 :            : 
     751                 :            :                 } else {
     752                 :          0 :                         size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE);
     753                 :          0 :                         done = hinic_handle_aeqe(eq->hwdev, event,
     754                 :          0 :                                                  aeqe_pos->aeqe_data,
     755                 :            :                                                  size, param);
     756                 :            :                 }
     757                 :            : 
     758                 :          0 :                 eq->cons_idx++;
     759         [ #  # ]:          0 :                 if (eq->cons_idx == eq->eq_len) {
     760                 :          0 :                         eq->cons_idx = 0;
     761                 :          0 :                         eq->wrapped = !eq->wrapped;
     762                 :            :                 }
     763                 :            :         }
     764                 :            : 
     765                 :          0 :         eq_update_ci(eq);
     766                 :            : 
     767                 :          0 :         return err;
     768                 :            : }
     769                 :            : 
     770                 :          0 : int hinic_comm_pf_to_mgmt_init(struct hinic_hwdev *hwdev)
     771                 :            : {
     772                 :            :         int rc;
     773                 :            : 
     774                 :            :         /* VF do not support send msg to mgmt directly */
     775         [ #  # ]:          0 :         if (hinic_func_type(hwdev) == TYPE_VF)
     776                 :            :                 return 0;
     777                 :            : 
     778                 :          0 :         rc = hinic_pf_to_mgmt_init(hwdev);
     779         [ #  # ]:          0 :         if (rc)
     780                 :            :                 return rc;
     781                 :            : 
     782                 :          0 :         hwdev->pf_to_mgmt->rx_aeq = &hwdev->aeqs->aeq[HINIC_MGMT_RSP_AEQN];
     783                 :            : 
     784                 :          0 :         return 0;
     785                 :            : }
     786                 :            : 
     787                 :          0 : void hinic_comm_pf_to_mgmt_free(struct hinic_hwdev *hwdev)
     788                 :            : {
     789                 :            :         /* VF do not support send msg to mgmt directly */
     790         [ #  # ]:          0 :         if (hinic_func_type(hwdev) == TYPE_VF)
     791                 :            :                 return;
     792                 :            : 
     793                 :          0 :         hinic_pf_to_mgmt_free(hwdev);
     794                 :            : }
     795                 :            : 
     796                 :          0 : void hinic_dev_handle_aeq_event(struct hinic_hwdev *hwdev, void *param)
     797                 :            : {
     798                 :          0 :         struct hinic_eq *aeq = &hwdev->aeqs->aeq[0];
     799                 :            : 
     800                 :            :         /* clear resend timer cnt register */
     801                 :          0 :         hinic_misx_intr_clear_resend_bit(hwdev, aeq->eq_irq.msix_entry_idx,
     802                 :            :                                          EQ_MSIX_RESEND_TIMER_CLEAR);
     803                 :          0 :         (void)hinic_aeq_poll_msg(aeq, 0, param);
     804                 :          0 : }

Generated by: LCOV version 1.14