dpdk/drivers/net/hinic/base/hinic_pmd_mbox.c
<<
>>
Prefs
   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_eqs.h"
  10#include "hinic_pmd_mgmt.h"
  11#include "hinic_pmd_mbox.h"
  12
  13#define HINIC_MBOX_INT_DST_FUNC_SHIFT                           0
  14#define HINIC_MBOX_INT_DST_AEQN_SHIFT                           10
  15#define HINIC_MBOX_INT_SRC_RESP_AEQN_SHIFT                      12
  16#define HINIC_MBOX_INT_STAT_DMA_SHIFT                           14
  17/* The size of data to be send (unit of 4 bytes) */
  18#define HINIC_MBOX_INT_TX_SIZE_SHIFT                            20
  19/* SO_RO(strong order, relax order)  */
  20#define HINIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT                     25
  21#define HINIC_MBOX_INT_WB_EN_SHIFT                              28
  22
  23
  24#define HINIC_MBOX_INT_DST_FUNC_MASK                            0x3FF
  25#define HINIC_MBOX_INT_DST_AEQN_MASK                            0x3
  26#define HINIC_MBOX_INT_SRC_RESP_AEQN_MASK                       0x3
  27#define HINIC_MBOX_INT_STAT_DMA_MASK                            0x3F
  28#define HINIC_MBOX_INT_TX_SIZE_MASK                             0x1F
  29#define HINIC_MBOX_INT_STAT_DMA_SO_RO_MASK                      0x3
  30#define HINIC_MBOX_INT_WB_EN_MASK                               0x1
  31
  32#define HINIC_MBOX_INT_SET(val, field)  \
  33                        (((val) & HINIC_MBOX_INT_##field##_MASK) << \
  34                        HINIC_MBOX_INT_##field##_SHIFT)
  35
  36enum hinic_mbox_tx_status {
  37        TX_DONE = 0,
  38        TX_IN_PROGRESS,
  39};
  40
  41#define HINIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT                      0
  42/* specifies the issue request for the message data.
  43 * 0 - Tx request is done;
  44 * 1 - Tx request is in process.
  45 */
  46#define HINIC_MBOX_CTRL_TX_STATUS_SHIFT                         1
  47
  48#define HINIC_MBOX_CTRL_TRIGGER_AEQE_MASK                       0x1
  49#define HINIC_MBOX_CTRL_TX_STATUS_MASK                          0x1
  50
  51#define HINIC_MBOX_CTRL_SET(val, field) \
  52                        (((val) & HINIC_MBOX_CTRL_##field##_MASK) << \
  53                        HINIC_MBOX_CTRL_##field##_SHIFT)
  54
  55#define HINIC_MBOX_HEADER_MSG_LEN_SHIFT                         0
  56#define HINIC_MBOX_HEADER_MODULE_SHIFT                          11
  57#define HINIC_MBOX_HEADER_SEG_LEN_SHIFT                         16
  58#define HINIC_MBOX_HEADER_NO_ACK_SHIFT                          22
  59#define HINIC_MBOX_HEADER_SEQID_SHIFT                           24
  60#define HINIC_MBOX_HEADER_LAST_SHIFT                            30
  61
  62#define HINIC_MBOX_HEADER_DIRECTION_SHIFT                       31
  63#define HINIC_MBOX_HEADER_CMD_SHIFT                             32
  64#define HINIC_MBOX_HEADER_MSG_ID_SHIFT                          40
  65#define HINIC_MBOX_HEADER_STATUS_SHIFT                          48
  66#define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_SHIFT                54
  67
  68#define HINIC_MBOX_HEADER_MSG_LEN_MASK                          0x7FF
  69#define HINIC_MBOX_HEADER_MODULE_MASK                           0x1F
  70#define HINIC_MBOX_HEADER_SEG_LEN_MASK                          0x3F
  71#define HINIC_MBOX_HEADER_NO_ACK_MASK                           0x1
  72#define HINIC_MBOX_HEADER_SEQID_MASK                            0x3F
  73#define HINIC_MBOX_HEADER_LAST_MASK                             0x1
  74#define HINIC_MBOX_HEADER_DIRECTION_MASK                        0x1
  75#define HINIC_MBOX_HEADER_CMD_MASK                              0xFF
  76#define HINIC_MBOX_HEADER_MSG_ID_MASK                           0xFF
  77#define HINIC_MBOX_HEADER_STATUS_MASK                           0x3F
  78#define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_MASK                 0x3FF
  79
  80#define HINIC_MBOX_HEADER_GET(val, field)       \
  81                        (((val) >> HINIC_MBOX_HEADER_##field##_SHIFT) & \
  82                        HINIC_MBOX_HEADER_##field##_MASK)
  83#define HINIC_MBOX_HEADER_SET(val, field)       \
  84                        ((u64)((val) & HINIC_MBOX_HEADER_##field##_MASK) << \
  85                        HINIC_MBOX_HEADER_##field##_SHIFT)
  86
  87#define HINIC_MBOX_COMP_TIME_MS                 8000U
  88#define MBOX_MSG_POLLING_TIMEOUT_MS             5000
  89
  90/* The size unit is Bytes */
  91#define HINIC_MBOX_DATA_SIZE                    2040
  92#define MBOX_MAX_BUF_SZ                         2048UL
  93#define MBOX_HEADER_SZ                          8
  94
  95/* MBOX size is 64B, 8B for mbox_header, 4B reserved */
  96#define MBOX_SEG_LEN                            48
  97#define MBOX_SEG_LEN_ALIGN                      4
  98#define MBOX_WB_STATUS_LEN                      16UL
  99#define MBOX_SIZE                               64
 100
 101/* mbox write back status is 16B, only first 4B is used */
 102#define MBOX_WB_STATUS_ERRCODE_MASK             0xFFFF
 103#define MBOX_WB_STATUS_MASK                     0xFF
 104#define MBOX_WB_ERROR_CODE_MASK                 0xFF00
 105#define MBOX_WB_STATUS_FINISHED_SUCCESS         0xFF
 106#define MBOX_WB_STATUS_FINISHED_WITH_ERR        0xFE
 107#define MBOX_WB_STATUS_NOT_FINISHED             0x00
 108
 109#define MBOX_STATUS_FINISHED(wb)        \
 110        (((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)
 111#define MBOX_STATUS_SUCCESS(wb)         \
 112        (((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)
 113#define MBOX_STATUS_ERRCODE(wb)         \
 114        ((wb) & MBOX_WB_ERROR_CODE_MASK)
 115
 116#define SEQ_ID_START_VAL                        0
 117
 118#define DST_AEQ_IDX_DEFAULT_VAL                 0
 119#define SRC_AEQ_IDX_DEFAULT_VAL                 0
 120#define NO_DMA_ATTRIBUTE_VAL                    0
 121
 122#define MBOX_MSG_NO_DATA_LEN                    1
 123
 124#define FUNC_ID_OFF_SET_8B              8
 125#define FUNC_ID_OFF_SET_10B             10
 126
 127#define MBOX_BODY_FROM_HDR(header)      ((u8 *)(header) + MBOX_HEADER_SZ)
 128#define MBOX_AREA(hwif)                 \
 129                ((hwif)->cfg_regs_base + HINIC_FUNC_CSR_MAILBOX_DATA_OFF)
 130
 131#define MBOX_RESPONSE_ERROR             0x1
 132#define MBOX_MSG_ID_MASK                0xFF
 133#define MBOX_MSG_ID(func_to_func)       ((func_to_func)->send_msg_id)
 134
 135enum hinic_hwif_direction_type {
 136        /* driver send msg to up or up send msg to driver*/
 137        HINIC_HWIF_DIRECT_SEND = 0,
 138        /* after driver/up send msg to each other, then up/driver ack the msg */
 139        HINIC_HWIF_RESPONSE,
 140};
 141
 142enum mbox_send_mod {
 143        MBOX_SEND_MSG_POLL = 1
 144};
 145
 146enum mbox_seg_type {
 147        NOT_LAST_SEG,
 148        LAST_SEG,
 149};
 150
 151enum mbox_ordering_type {
 152        STRONG_ORDER,
 153        RELAX_ORDER,
 154};
 155
 156enum mbox_write_back_type {
 157        NOT_WRITE_BACK = 0,
 158        WRITE_BACK,
 159};
 160
 161enum mbox_aeq_trig_type {
 162        NOT_TRIGGER,
 163        TRIGGER,
 164};
 165
 166static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
 167                                enum hinic_mod_type mod, u16 cmd, void *msg,
 168                                u16 msg_len, u16 dst_func,
 169                                enum hinic_hwif_direction_type direction,
 170                                enum hinic_mbox_ack_type ack_type,
 171                                struct mbox_msg_info *msg_info);
 172
 173static int recv_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 174                                struct hinic_recv_mbox *recv_mbox,
 175                                void *buf_out, u16 *out_size, void *param)
 176{
 177        int rc = 0;
 178        *out_size = 0;
 179
 180        switch (recv_mbox->mod) {
 181        case HINIC_MOD_COMM:
 182                hinic_comm_async_event_handle(func_to_func->hwdev,
 183                                                recv_mbox->cmd, recv_mbox->mbox,
 184                                                recv_mbox->mbox_len,
 185                                                buf_out, out_size);
 186                break;
 187        case HINIC_MOD_L2NIC:
 188                hinic_l2nic_async_event_handle(func_to_func->hwdev, param,
 189                                                recv_mbox->cmd, recv_mbox->mbox,
 190                                                recv_mbox->mbox_len,
 191                                                buf_out, out_size);
 192                break;
 193        default:
 194                PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_mbox->mod);
 195                rc = HINIC_MBOX_VF_CMD_ERROR;
 196                break;
 197        }
 198
 199        return rc;
 200}
 201
 202static void set_mbx_msg_status(struct mbox_msg_info *msg_info, int status)
 203{
 204        if (status == HINIC_DEV_BUSY_ACTIVE_FW)
 205                msg_info->status = HINIC_MBOX_PF_BUSY_ACTIVE_FW;
 206        else if (status == HINIC_MBOX_VF_CMD_ERROR)
 207                msg_info->status = HINIC_MBOX_VF_CMD_ERROR;
 208        else if (status)
 209                msg_info->status = HINIC_MBOX_PF_SEND_ERR;
 210}
 211
 212static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 213                                struct hinic_recv_mbox *recv_mbox,
 214                                u16 src_func_idx, void *param)
 215{
 216        struct hinic_hwdev *dev = func_to_func->hwdev;
 217        struct mbox_msg_info msg_info = { 0 };
 218        u16 out_size = MBOX_MAX_BUF_SZ;
 219        void *buf_out = recv_mbox->buf_out;
 220        int err = 0;
 221
 222        if (HINIC_IS_VF(dev)) {
 223                err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out,
 224                                                &out_size, param);
 225        } else {
 226                err = -EINVAL;
 227                PMD_DRV_LOG(ERR, "PMD doesn't support non-VF handle mailbox message");
 228        }
 229
 230        if (!out_size || err)
 231                out_size = MBOX_MSG_NO_DATA_LEN;
 232
 233        if (recv_mbox->ack_type == MBOX_ACK) {
 234                msg_info.msg_id = recv_mbox->msg_info.msg_id;
 235                set_mbx_msg_status(&msg_info, err);
 236                send_mbox_to_func(func_to_func, recv_mbox->mod, recv_mbox->cmd,
 237                                buf_out, out_size, src_func_idx,
 238                                HINIC_HWIF_RESPONSE, MBOX_ACK, &msg_info);
 239        }
 240}
 241
 242static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
 243                                          u8 seq_id, u8 seg_len, u8 msg_id)
 244{
 245        if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN)
 246                return false;
 247
 248        if (seq_id == 0) {
 249                recv_mbox->seq_id = seq_id;
 250                recv_mbox->msg_info.msg_id = msg_id;
 251        } else {
 252                if ((seq_id != recv_mbox->seq_id + 1) ||
 253                        msg_id != recv_mbox->msg_info.msg_id) {
 254                        recv_mbox->seq_id = 0;
 255                        return false;
 256                }
 257
 258                recv_mbox->seq_id = seq_id;
 259        }
 260
 261        return true;
 262}
 263
 264static void clear_mbox_status(struct hinic_send_mbox *mbox)
 265{
 266        /* clear mailbox write back status */
 267        *mbox->wb_status = 0;
 268        rte_wmb();
 269}
 270
 271static void mbox_copy_header(struct hinic_send_mbox *mbox, u64 *header)
 272{
 273        u32 *data = (u32 *)header;
 274        u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32);
 275
 276        for (i = 0; i < idx_max; i++)
 277                __raw_writel(*(data + i), mbox->data + i * sizeof(u32));
 278}
 279
 280static void
 281mbox_copy_send_data(struct hinic_send_mbox *mbox, void *seg, u16 seg_len)
 282{
 283        u32 *data = (u32 *)seg;
 284        u32 data_len, chk_sz = sizeof(u32);
 285        u32 i, idx_max;
 286        u8 mbox_max_buf[MBOX_SEG_LEN] = {0};
 287
 288        /* The mbox message should be aligned in 4 bytes. */
 289        if (seg_len % chk_sz) {
 290                memcpy(mbox_max_buf, seg, seg_len);
 291                data = (u32 *)mbox_max_buf;
 292        }
 293
 294        data_len = seg_len;
 295        idx_max = ALIGN(data_len, chk_sz) / chk_sz;
 296
 297        for (i = 0; i < idx_max; i++)
 298                __raw_writel(*(data + i),
 299                                mbox->data + MBOX_HEADER_SZ + i * sizeof(u32));
 300}
 301
 302static int mbox_msg_ack_aeqn(struct hinic_hwdev *hwdev)
 303{
 304        u16 aeq_num = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
 305        int msg_ack_aeqn;
 306
 307        if (aeq_num >= HINIC_MAX_AEQS - 1) {
 308                msg_ack_aeqn = HINIC_AEQN_2;
 309        } else if (aeq_num == HINIC_MIN_AEQS) {
 310                /* This is used for ovs */
 311                msg_ack_aeqn = HINIC_AEQN_1;
 312        } else {
 313                PMD_DRV_LOG(ERR, "Warning: Invalid aeq num: %d\n", aeq_num);
 314                msg_ack_aeqn = -1;
 315        }
 316
 317        return msg_ack_aeqn;
 318}
 319
 320static u16 mbox_msg_dst_aeqn(struct hinic_hwdev *hwdev,
 321                        enum hinic_hwif_direction_type seq_dir)
 322{
 323        u16 dst_aeqn;
 324
 325        if (seq_dir == HINIC_HWIF_DIRECT_SEND)
 326                dst_aeqn = HINIC_AEQN_0;
 327        else
 328                dst_aeqn = mbox_msg_ack_aeqn(hwdev);
 329
 330        return dst_aeqn;
 331}
 332
 333static int mbox_seg_ack_aeqn(struct hinic_hwdev *hwdev)
 334{
 335        return mbox_msg_ack_aeqn(hwdev);
 336}
 337
 338static void write_mbox_msg_attr(struct hinic_mbox_func_to_func *func_to_func,
 339                        u16 dst_func, u16 dst_aeqn, u16 seg_ack_aeqn,
 340                        __rte_unused u16 seg_len, int poll)
 341{
 342        u32 mbox_int, mbox_ctrl;
 343
 344        mbox_int = HINIC_MBOX_INT_SET(dst_func, DST_FUNC) |
 345                HINIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) |
 346                /* N/A in polling mode */
 347                HINIC_MBOX_INT_SET(seg_ack_aeqn, SRC_RESP_AEQN) |
 348                HINIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |
 349                HINIC_MBOX_INT_SET(ALIGN(MBOX_SIZE, MBOX_SEG_LEN_ALIGN) >> 2,
 350                                        TX_SIZE) |
 351                HINIC_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) |
 352                HINIC_MBOX_INT_SET(WRITE_BACK, WB_EN);
 353
 354        hinic_hwif_write_reg(func_to_func->hwdev->hwif,
 355                        HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, mbox_int);
 356
 357        rte_wmb();
 358        mbox_ctrl = HINIC_MBOX_CTRL_SET(TX_IN_PROGRESS, TX_STATUS);
 359
 360        if (poll)
 361                mbox_ctrl |= HINIC_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE);
 362        else
 363                mbox_ctrl |= HINIC_MBOX_CTRL_SET(TRIGGER, TRIGGER_AEQE);
 364
 365        hinic_hwif_write_reg(func_to_func->hwdev->hwif,
 366                                HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl);
 367}
 368
 369static int init_mbox_info(struct hinic_recv_mbox *mbox_info)
 370{
 371        int err;
 372
 373        mbox_info->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
 374        if (!mbox_info->mbox) {
 375                PMD_DRV_LOG(ERR, "Alloc mbox buf_in mem failed\n");
 376                return -ENOMEM;
 377        }
 378
 379        mbox_info->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
 380        if (!mbox_info->buf_out) {
 381                PMD_DRV_LOG(ERR, "Alloc mbox buf_out mem failed\n");
 382                err = -ENOMEM;
 383                goto alloc_buf_out_err;
 384        }
 385
 386        return 0;
 387
 388alloc_buf_out_err:
 389        kfree(mbox_info->mbox);
 390
 391        return err;
 392}
 393
 394static void clean_mbox_info(struct hinic_recv_mbox *mbox_info)
 395{
 396        kfree(mbox_info->buf_out);
 397        kfree(mbox_info->mbox);
 398}
 399
 400static int alloc_mbox_info(struct hinic_recv_mbox *mbox_info)
 401{
 402        u16 func_idx, i;
 403        int err;
 404
 405        for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++) {
 406                err = init_mbox_info(&mbox_info[func_idx]);
 407                if (err) {
 408                        PMD_DRV_LOG(ERR, "Initialize function[%d] mailbox information failed, err: %d",
 409                                    func_idx, err);
 410                        goto init_mbox_info_err;
 411                }
 412        }
 413
 414        return 0;
 415
 416init_mbox_info_err:
 417        for (i = 0; i < func_idx; i++)
 418                clean_mbox_info(&mbox_info[i]);
 419
 420        return err;
 421}
 422
 423static void free_mbox_info(struct hinic_recv_mbox *mbox_info)
 424{
 425        u16 func_idx;
 426
 427        for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++)
 428                clean_mbox_info(&mbox_info[func_idx]);
 429}
 430
 431static void prepare_send_mbox(struct hinic_mbox_func_to_func *func_to_func)
 432{
 433        struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
 434
 435        send_mbox->data = MBOX_AREA(func_to_func->hwdev->hwif);
 436}
 437
 438static int alloc_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
 439{
 440        struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
 441        struct hinic_hwdev *hwdev = func_to_func->hwdev;
 442        struct hinic_hwif *hwif = hwdev->hwif;
 443        u32 addr_h, addr_l;
 444
 445        send_mbox->wb_vaddr = dma_zalloc_coherent(hwdev, MBOX_WB_STATUS_LEN,
 446                                        &send_mbox->wb_paddr, SOCKET_ID_ANY);
 447        if (!send_mbox->wb_vaddr) {
 448                PMD_DRV_LOG(ERR, "Allocating memory for mailbox wb status failed");
 449                return -ENOMEM;
 450        }
 451        send_mbox->wb_status = (volatile u64 *)send_mbox->wb_vaddr;
 452
 453        addr_h = upper_32_bits(send_mbox->wb_paddr);
 454        addr_l = lower_32_bits(send_mbox->wb_paddr);
 455        hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, addr_h);
 456        hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, addr_l);
 457
 458        return 0;
 459}
 460
 461static void free_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
 462{
 463        struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
 464        struct hinic_hwdev *hwdev = func_to_func->hwdev;
 465        struct hinic_hwif *hwif = hwdev->hwif;
 466
 467        hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, 0);
 468        hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, 0);
 469
 470        dma_free_coherent(hwdev, MBOX_WB_STATUS_LEN,
 471                                send_mbox->wb_vaddr, send_mbox->wb_paddr);
 472}
 473
 474static int recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 475                void *header, struct hinic_recv_mbox *recv_mbox, void *param)
 476{
 477        u64 mbox_header = *((u64 *)header);
 478        void *mbox_body = MBOX_BODY_FROM_HDR(header);
 479        u16 src_func_idx;
 480        enum hinic_hwif_direction_type direction;
 481        u8 seq_id, seg_len;
 482        u8 msg_id;
 483        u8 front_id;
 484
 485        seq_id = HINIC_MBOX_HEADER_GET(mbox_header, SEQID);
 486        seg_len = HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN);
 487        direction = HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION);
 488        src_func_idx = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
 489        msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);
 490        front_id = recv_mbox->seq_id;
 491
 492        if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len,
 493                msg_id)) {
 494                PMD_DRV_LOG(ERR,
 495                        "Mailbox sequence and segment check failed, src func id: 0x%x, "
 496                        "front id: 0x%x, current id: 0x%x, seg len: 0x%x "
 497                        "front msg_id: %d, cur msg_id: %d",
 498                        src_func_idx, front_id, seq_id, seg_len,
 499                        recv_mbox->msg_info.msg_id, msg_id);
 500                return HINIC_ERROR;
 501        }
 502
 503        memcpy((u8 *)recv_mbox->mbox + seq_id * HINIC_MSG_SEG_LEN,
 504                mbox_body, seg_len);
 505
 506        if (!HINIC_MBOX_HEADER_GET(mbox_header, LAST))
 507                return HINIC_ERROR;
 508
 509        recv_mbox->seq_id = 0;
 510        recv_mbox->cmd = HINIC_MBOX_HEADER_GET(mbox_header, CMD);
 511        recv_mbox->mod = HINIC_MBOX_HEADER_GET(mbox_header, MODULE);
 512        recv_mbox->mbox_len = HINIC_MBOX_HEADER_GET(mbox_header, MSG_LEN);
 513        recv_mbox->ack_type = HINIC_MBOX_HEADER_GET(mbox_header, NO_ACK);
 514        recv_mbox->msg_info.msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);
 515        recv_mbox->msg_info.status = HINIC_MBOX_HEADER_GET(mbox_header, STATUS);
 516
 517        if (direction == HINIC_HWIF_RESPONSE) {
 518                if (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id &&
 519                        func_to_func->event_flag == EVENT_START) {
 520                        return HINIC_OK;
 521                }
 522
 523                PMD_DRV_LOG(ERR, "Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)",
 524                        func_to_func->send_msg_id, recv_mbox->msg_info.msg_id,
 525                        recv_mbox->msg_info.status);
 526                return HINIC_ERROR;
 527        }
 528
 529        recv_func_mbox_handler(func_to_func, recv_mbox, src_func_idx, param);
 530
 531        return HINIC_ERROR;
 532}
 533
 534/**
 535 * hinic_mbox_func_aeqe_handler - Process mbox info from func which is
 536 * sent by aeqe.
 537 *
 538 * @param handle
 539 *   Pointer to hradware nic device.
 540 * @param header
 541 *   Mbox header info.
 542 * @param size
 543 *   The size of aeqe descriptor.
 544 * @param param
 545 *   customized parameter.
 546 *
 547 * @return
 548 *   0 on success, negative error value otherwise.
 549 */
 550int hinic_mbox_func_aeqe_handler(void *handle, u8 *header,
 551                                        __rte_unused u8 size, void *param)
 552{
 553        struct hinic_mbox_func_to_func *func_to_func =
 554                                ((struct hinic_hwdev *)handle)->func_to_func;
 555        struct hinic_recv_mbox *recv_mbox;
 556        u64 mbox_header = *((u64 *)header);
 557        u16 src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
 558
 559        if (src >= HINIC_MAX_FUNCTIONS) {
 560                PMD_DRV_LOG(ERR, "Mailbox source function id: %d is invalid",
 561                                src);
 562                return HINIC_ERROR;
 563        }
 564
 565        recv_mbox = (HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION) ==
 566                        HINIC_HWIF_DIRECT_SEND) ?
 567                        &func_to_func->mbox_send[src] :
 568                        &func_to_func->mbox_resp[src];
 569
 570        return recv_mbox_handler(func_to_func, (u64 *)header, recv_mbox, param);
 571}
 572
 573static u16 get_mbox_status(struct hinic_send_mbox *mbox)
 574{
 575        /* write back is 16B, but only use first 4B */
 576        u64 wb_val = be64_to_cpu(*mbox->wb_status);
 577
 578        rte_rmb(); /* verify reading before check */
 579
 580        return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK);
 581}
 582
 583static void dump_mox_reg(struct hinic_hwdev *hwdev)
 584{
 585        u32 val;
 586
 587        val = hinic_hwif_read_reg(hwdev->hwif,
 588                                        HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF);
 589        PMD_DRV_LOG(WARNING, "Mailbox control reg: 0x%x", val);
 590        val = hinic_hwif_read_reg(hwdev->hwif,
 591                                        HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF);
 592        PMD_DRV_LOG(WARNING, "Mailbox interrupt offset: 0x%x", val);
 593}
 594
 595static int send_mbox_seg(struct hinic_mbox_func_to_func *func_to_func,
 596                         u64 header, u16 dst_func, void *seg, u16 seg_len)
 597{
 598        struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
 599        struct hinic_hwdev *hwdev = func_to_func->hwdev;
 600        u16 seq_dir = HINIC_MBOX_HEADER_GET(header, DIRECTION);
 601        u16 dst_aeqn, seg_ack_aeqn;
 602        u16 err_code, wb_status = 0;
 603        u32 cnt = 0;
 604
 605        dst_aeqn = mbox_msg_dst_aeqn(hwdev, seq_dir);
 606        seg_ack_aeqn = mbox_seg_ack_aeqn(hwdev);
 607
 608        clear_mbox_status(send_mbox);
 609
 610        mbox_copy_header(send_mbox, &header);
 611
 612        mbox_copy_send_data(send_mbox, seg, seg_len);
 613
 614        write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_ack_aeqn,
 615                                seg_len, MBOX_SEND_MSG_POLL);
 616
 617        rte_wmb();
 618
 619        while (cnt < MBOX_MSG_POLLING_TIMEOUT_MS) {
 620                wb_status = get_mbox_status(send_mbox);
 621                if (MBOX_STATUS_FINISHED(wb_status))
 622                        break;
 623
 624                rte_delay_ms(1); /* loop every ms */
 625                cnt++;
 626        }
 627
 628        if (cnt == MBOX_MSG_POLLING_TIMEOUT_MS) {
 629                PMD_DRV_LOG(ERR, "Send mailbox segment timeout, wb status: 0x%x",
 630                                wb_status);
 631                dump_mox_reg(hwdev);
 632                return -ETIMEDOUT;
 633        }
 634
 635        if (!MBOX_STATUS_SUCCESS(wb_status)) {
 636                PMD_DRV_LOG(ERR, "Send mailbox segment to function %d error, wb status: 0x%x",
 637                                dst_func, wb_status);
 638                /*
 639                 * err_code: 0 responses no errors, other values can
 640                 * refer to FS doc.
 641                 */
 642                err_code = MBOX_STATUS_ERRCODE(wb_status);
 643                return err_code ? err_code : -EFAULT;
 644        }
 645
 646        return 0;
 647}
 648
 649static void set_mbox_to_func_event(struct hinic_mbox_func_to_func *func_to_func,
 650                                   enum mbox_event_state event_flag)
 651{
 652        spin_lock(&func_to_func->mbox_lock);
 653        func_to_func->event_flag = event_flag;
 654        spin_unlock(&func_to_func->mbox_lock);
 655}
 656
 657static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
 658                                enum hinic_mod_type mod, u16 cmd, void *msg,
 659                                u16 msg_len, u16 dst_func,
 660                                enum hinic_hwif_direction_type direction,
 661                                enum hinic_mbox_ack_type ack_type,
 662                                struct mbox_msg_info *msg_info)
 663{
 664        struct hinic_hwdev *hwdev = func_to_func->hwdev;
 665        int err = 0;
 666        u32 seq_id = 0;
 667        u16 seg_len = HINIC_MSG_SEG_LEN;
 668        u16 left = msg_len;
 669        u8 *msg_seg = (u8 *)msg;
 670        u64 header = 0;
 671
 672        err = hinic_mutex_lock(&func_to_func->msg_send_mutex);
 673        if (err)
 674                return err;
 675
 676        header = HINIC_MBOX_HEADER_SET(msg_len, MSG_LEN) |
 677                HINIC_MBOX_HEADER_SET(mod, MODULE) |
 678                HINIC_MBOX_HEADER_SET(seg_len, SEG_LEN) |
 679                HINIC_MBOX_HEADER_SET(ack_type, NO_ACK) |
 680                HINIC_MBOX_HEADER_SET(SEQ_ID_START_VAL, SEQID) |
 681                HINIC_MBOX_HEADER_SET(NOT_LAST_SEG, LAST) |
 682                HINIC_MBOX_HEADER_SET(direction, DIRECTION) |
 683                HINIC_MBOX_HEADER_SET(cmd, CMD) |
 684                HINIC_MBOX_HEADER_SET(msg_info->msg_id, MSG_ID) |
 685                HINIC_MBOX_HEADER_SET(msg_info->status, STATUS) |
 686                HINIC_MBOX_HEADER_SET(hinic_global_func_id(hwdev),
 687                                        SRC_GLB_FUNC_IDX);
 688
 689        while (!(HINIC_MBOX_HEADER_GET(header, LAST))) {
 690                if (left <= HINIC_MSG_SEG_LEN) {
 691                        header &=
 692                        ~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEG_LEN_MASK,
 693                                                SEG_LEN));
 694                        header |= HINIC_MBOX_HEADER_SET(left, SEG_LEN);
 695                        header |= HINIC_MBOX_HEADER_SET(LAST_SEG, LAST);
 696
 697                        seg_len = left;
 698                }
 699
 700                err = send_mbox_seg(func_to_func, header, dst_func, msg_seg,
 701                                    seg_len);
 702                if (err) {
 703                        PMD_DRV_LOG(ERR, "Fail to send mbox seg, err: %d", err);
 704                        goto send_err;
 705                }
 706
 707                left -= HINIC_MSG_SEG_LEN;
 708                msg_seg += HINIC_MSG_SEG_LEN;
 709
 710                seq_id++;
 711                header &= ~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEQID_MASK,
 712                                                        SEQID));
 713                header |= HINIC_MBOX_HEADER_SET(seq_id, SEQID);
 714        }
 715
 716send_err:
 717        (void)hinic_mutex_unlock(&func_to_func->msg_send_mutex);
 718
 719        return err;
 720}
 721
 722static int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
 723                        enum hinic_mod_type mod, u16 cmd, u16 dst_func,
 724                        void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
 725                        u32 timeout)
 726{
 727        struct hinic_recv_mbox *mbox_for_resp =
 728                                        &func_to_func->mbox_resp[dst_func];
 729        struct mbox_msg_info msg_info = {0};
 730        u32 time;
 731        int err;
 732
 733        err = hinic_mutex_lock(&func_to_func->mbox_send_mutex);
 734        if (err)
 735                return err;
 736
 737        msg_info.msg_id = (MBOX_MSG_ID(func_to_func) + 1) & MBOX_MSG_ID_MASK;
 738        MBOX_MSG_ID(func_to_func) = msg_info.msg_id;
 739
 740        set_mbox_to_func_event(func_to_func, EVENT_START);
 741
 742        err = send_mbox_to_func(func_to_func, mod, cmd, buf_in, in_size,
 743                                dst_func, HINIC_HWIF_DIRECT_SEND,
 744                                MBOX_ACK, &msg_info);
 745        if (err)
 746                goto send_err;
 747
 748        time = msecs_to_jiffies(timeout ? timeout : HINIC_MBOX_COMP_TIME_MS);
 749        err = hinic_aeq_poll_msg(func_to_func->ack_aeq, time, NULL);
 750        if (err) {
 751                set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
 752                PMD_DRV_LOG(ERR, "Send mailbox message time out");
 753                err = -ETIMEDOUT;
 754                goto send_err;
 755        }
 756
 757        set_mbox_to_func_event(func_to_func, EVENT_END);
 758
 759        if (mbox_for_resp->msg_info.status) {
 760                err = mbox_for_resp->msg_info.status;
 761                if (err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)
 762                        PMD_DRV_LOG(ERR, "Mailbox response error: 0x%x",
 763                                        mbox_for_resp->msg_info.status);
 764                else
 765                        PMD_DRV_LOG(ERR, "Chip is in active, PF can't process VF message");
 766                goto send_err;
 767        }
 768
 769        rte_rmb();
 770
 771        if (mbox_for_resp->mbox_len && buf_out && out_size) {
 772                if (mbox_for_resp->mbox_len <= *out_size) {
 773                        memcpy(buf_out, mbox_for_resp->mbox,
 774                                mbox_for_resp->mbox_len);
 775                        *out_size = mbox_for_resp->mbox_len;
 776                } else {
 777                        PMD_DRV_LOG(ERR, "Mailbox response message len[%u] overflow",
 778                                        mbox_for_resp->mbox_len);
 779                        err = -ERANGE;
 780                }
 781        }
 782
 783send_err:
 784        if (err && out_size)
 785                *out_size = 0;
 786        (void)hinic_mutex_unlock(&func_to_func->mbox_send_mutex);
 787
 788        return err;
 789}
 790
 791static int
 792mbox_func_params_valid(__rte_unused struct hinic_mbox_func_to_func *mbox_obj,
 793                        void *buf_in, u16 in_size)
 794{
 795        if (!buf_in || !in_size)
 796                return -EINVAL;
 797
 798        if (in_size > HINIC_MBOX_DATA_SIZE) {
 799                PMD_DRV_LOG(ERR, "Mailbox message len(%d) exceed limit(%d)",
 800                                in_size, HINIC_MBOX_DATA_SIZE);
 801                return -EINVAL;
 802        }
 803
 804        return 0;
 805}
 806
 807static u8 hinic_pf_id_of_vf(void *hwdev)
 808{
 809        struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
 810        return hwif->attr.port_to_port_idx;
 811}
 812
 813/**
 814 * hinic_mbox_to_pf - Send mbox info to pf and need pf to response.
 815 *
 816 * @param hwdev
 817 *   Pointer to hardware nic device.
 818 * @param mod
 819 *   Mode type of hardware.
 820 * @param cmd
 821 *   The command sent to pf.
 822 * @param buf_in
 823 *   Input parameter.
 824 * @param in_size
 825 *   Input parameter size.
 826 * @param buf_out
 827 *   Output parameter.
 828 * @param out_size
 829 *   Output parameter size.
 830 * @param timeout
 831 *   Timeout.
 832 *
 833 * @return
 834 *   0 on success, negative error value otherwise.
 835 */
 836int hinic_mbox_to_pf(struct hinic_hwdev *hwdev,
 837                      enum hinic_mod_type mod, u8 cmd, void *buf_in,
 838                      u16 in_size, void *buf_out, u16 *out_size, u32 timeout)
 839{
 840        struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
 841        int err;
 842
 843        err = mbox_func_params_valid(func_to_func, buf_in, in_size);
 844        if (err) {
 845                PMD_DRV_LOG(ERR, "Mailbox parameters check failed: %d", err);
 846                return err;
 847        }
 848
 849        if (!HINIC_IS_VF(hwdev)) {
 850                PMD_DRV_LOG(ERR, "Input function type error, func_type: %d",
 851                                hinic_func_type(hwdev));
 852                return -EINVAL;
 853        }
 854
 855        return hinic_mbox_to_func(func_to_func, mod, cmd,
 856                                   hinic_pf_id_of_vf(hwdev), buf_in, in_size,
 857                                   buf_out, out_size, timeout);
 858}
 859
 860/**
 861 * hinic_mbox_to_pf_no_ack - Send mbox info to pf and do not need pf to response
 862 *
 863 * @param hwdev
 864 *   Pointer to hardware nic device.
 865 * @param mod
 866 *   Mode type of hardware.
 867 * @param cmd
 868 *   The command sent to pf.
 869 * @param buf_in
 870 *   Input parameter.
 871 * @param in_size
 872 *   Input parameter size.
 873 *
 874 * @return
 875 *   0 on success, negative error value otherwise.
 876 */
 877int hinic_mbox_to_pf_no_ack(struct hinic_hwdev *hwdev, enum hinic_mod_type mod,
 878                        u8 cmd, void *buf_in, u16 in_size)
 879{
 880        int err;
 881        struct mbox_msg_info msg_info = {0};
 882
 883        err = hinic_mutex_lock(&hwdev->func_to_func->mbox_send_mutex);
 884        if (err)
 885                return err;
 886
 887        err = send_mbox_to_func(hwdev->func_to_func, mod, cmd, buf_in, in_size,
 888                        hinic_pf_id_of_vf(hwdev), HINIC_HWIF_DIRECT_SEND,
 889                        MBOX_NO_ACK, &msg_info);
 890        if (err)
 891                PMD_DRV_LOG(ERR, "Send mailbox no ack failed, err: %d", err);
 892
 893        (void)hinic_mutex_unlock(&hwdev->func_to_func->mbox_send_mutex);
 894
 895        return err;
 896}
 897
 898static int hinic_func_to_func_init(struct hinic_hwdev *hwdev)
 899{
 900        struct hinic_mbox_func_to_func *func_to_func;
 901        int err;
 902
 903        func_to_func = kzalloc(sizeof(*func_to_func), GFP_KERNEL);
 904        if (!func_to_func) {
 905                PMD_DRV_LOG(ERR, "Allocating memory for func_to_func object failed");
 906                return -ENOMEM;
 907        }
 908        hwdev->func_to_func = func_to_func;
 909        func_to_func->hwdev = hwdev;
 910        (void)hinic_mutex_init(&func_to_func->mbox_send_mutex, NULL);
 911        (void)hinic_mutex_init(&func_to_func->msg_send_mutex, NULL);
 912
 913        err = alloc_mbox_info(func_to_func->mbox_send);
 914        if (err) {
 915                PMD_DRV_LOG(ERR, "Allocating memory for mailbox sending failed");
 916                goto alloc_mbox_for_send_err;
 917        }
 918
 919        err = alloc_mbox_info(func_to_func->mbox_resp);
 920        if (err) {
 921                PMD_DRV_LOG(ERR, "Allocating memory for mailbox responding failed");
 922                goto alloc_mbox_for_resp_err;
 923        }
 924
 925        err = alloc_mbox_wb_status(func_to_func);
 926        if (err)
 927                goto alloc_wb_status_err;
 928
 929        prepare_send_mbox(func_to_func);
 930
 931        return 0;
 932
 933alloc_wb_status_err:
 934        free_mbox_info(func_to_func->mbox_resp);
 935
 936alloc_mbox_for_resp_err:
 937        free_mbox_info(func_to_func->mbox_send);
 938
 939alloc_mbox_for_send_err:
 940        kfree(func_to_func);
 941
 942        return err;
 943}
 944
 945/**
 946 * hinic_comm_func_to_func_free - Uninitialize func to func resource.
 947 *
 948 * @param hwdev
 949 *   Pointer to hardware nic device.
 950 */
 951void hinic_comm_func_to_func_free(struct hinic_hwdev *hwdev)
 952{
 953        struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
 954
 955        free_mbox_wb_status(func_to_func);
 956        free_mbox_info(func_to_func->mbox_resp);
 957        free_mbox_info(func_to_func->mbox_send);
 958        (void)hinic_mutex_destroy(&func_to_func->mbox_send_mutex);
 959        (void)hinic_mutex_destroy(&func_to_func->msg_send_mutex);
 960        kfree(func_to_func);
 961}
 962
 963/**
 964 * hinic_comm_func_to_func_init - Initialize func to func resource.
 965 *
 966 * @param hwdev
 967 *   Pointer to hardware nic device.
 968 */
 969int hinic_comm_func_to_func_init(struct hinic_hwdev *hwdev)
 970{
 971        int rc;
 972        u16 msg_ack_aeqn;
 973
 974        rc = hinic_func_to_func_init(hwdev);
 975        if (rc)
 976                return rc;
 977
 978        msg_ack_aeqn = mbox_msg_ack_aeqn(hwdev);
 979
 980        hwdev->func_to_func->ack_aeq = &hwdev->aeqs->aeq[msg_ack_aeqn];
 981        hwdev->func_to_func->recv_aeq = &hwdev->aeqs->aeq[HINIC_AEQN_0];
 982
 983        return 0;
 984}
 985
 986