linux/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Huawei HiNIC PCI Express Linux driver
   4 * Copyright(c) 2017 Huawei Technologies Co., Ltd
   5 */
   6
   7#include <linux/kernel.h>
   8#include <linux/types.h>
   9#include <linux/errno.h>
  10#include <linux/pci.h>
  11#include <linux/device.h>
  12#include <linux/semaphore.h>
  13#include <linux/completion.h>
  14#include <linux/slab.h>
  15#include <asm/barrier.h>
  16
  17#include "hinic_hw_if.h"
  18#include "hinic_hw_eqs.h"
  19#include "hinic_hw_api_cmd.h"
  20#include "hinic_hw_mgmt.h"
  21#include "hinic_hw_dev.h"
  22
  23#define SYNC_MSG_ID_MASK                0x1FF
  24
  25#define SYNC_MSG_ID(pf_to_mgmt)         ((pf_to_mgmt)->sync_msg_id)
  26
  27#define SYNC_MSG_ID_INC(pf_to_mgmt)     (SYNC_MSG_ID(pf_to_mgmt) = \
  28                                        ((SYNC_MSG_ID(pf_to_mgmt) + 1) & \
  29                                         SYNC_MSG_ID_MASK))
  30
  31#define MSG_SZ_IS_VALID(in_size)        ((in_size) <= MAX_MSG_LEN)
  32
  33#define MGMT_MSG_LEN_MIN                20
  34#define MGMT_MSG_LEN_STEP               16
  35#define MGMT_MSG_RSVD_FOR_DEV           8
  36
  37#define SEGMENT_LEN                     48
  38
  39#define MAX_PF_MGMT_BUF_SIZE            2048
  40
  41/* Data should be SEG LEN size aligned */
  42#define MAX_MSG_LEN                     2016
  43
  44#define MSG_NOT_RESP                    0xFFFF
  45
  46#define MGMT_MSG_TIMEOUT                1000
  47
  48#define mgmt_to_pfhwdev(pf_mgmt)        \
  49                container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
  50
  51enum msg_segment_type {
  52        NOT_LAST_SEGMENT = 0,
  53        LAST_SEGMENT     = 1,
  54};
  55
  56enum mgmt_direction_type {
  57        MGMT_DIRECT_SEND = 0,
  58        MGMT_RESP        = 1,
  59};
  60
  61enum msg_ack_type {
  62        MSG_ACK         = 0,
  63        MSG_NO_ACK      = 1,
  64};
  65
  66/**
  67 * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module
  68 * @pf_to_mgmt: PF to MGMT channel
  69 * @mod: module in the chip that this handler will handle its messages
  70 * @handle: private data for the callback
  71 * @callback: the handler that will handle messages
  72 **/
  73void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
  74                                enum hinic_mod_type mod,
  75                                void *handle,
  76                                void (*callback)(void *handle,
  77                                                 u8 cmd, void *buf_in,
  78                                                 u16 in_size, void *buf_out,
  79                                                 u16 *out_size))
  80{
  81        struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];
  82
  83        mgmt_cb->cb = callback;
  84        mgmt_cb->handle = handle;
  85        mgmt_cb->state = HINIC_MGMT_CB_ENABLED;
  86}
  87
  88/**
  89 * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module
  90 * @pf_to_mgmt: PF to MGMT channel
  91 * @mod: module in the chip that this handler handles its messages
  92 **/
  93void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
  94                                  enum hinic_mod_type mod)
  95{
  96        struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];
  97
  98        mgmt_cb->state &= ~HINIC_MGMT_CB_ENABLED;
  99
 100        while (mgmt_cb->state & HINIC_MGMT_CB_RUNNING)
 101                schedule();
 102
 103        mgmt_cb->cb = NULL;
 104}
 105
 106/**
 107 * prepare_header - prepare the header of the message
 108 * @pf_to_mgmt: PF to MGMT channel
 109 * @msg_len: the length of the message
 110 * @mod: module in the chip that will get the message
 111 * @ack_type: ask for response
 112 * @direction: the direction of the message
 113 * @cmd: command of the message
 114 * @msg_id: message id
 115 *
 116 * Return the prepared header value
 117 **/
 118static u64 prepare_header(struct hinic_pf_to_mgmt *pf_to_mgmt,
 119                          u16 msg_len, enum hinic_mod_type mod,
 120                          enum msg_ack_type ack_type,
 121                          enum mgmt_direction_type direction,
 122                          u16 cmd, u16 msg_id)
 123{
 124        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 125
 126        return HINIC_MSG_HEADER_SET(msg_len, MSG_LEN)           |
 127               HINIC_MSG_HEADER_SET(mod, MODULE)                |
 128               HINIC_MSG_HEADER_SET(SEGMENT_LEN, SEG_LEN)       |
 129               HINIC_MSG_HEADER_SET(ack_type, NO_ACK)           |
 130               HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF)        |
 131               HINIC_MSG_HEADER_SET(0, SEQID)                   |
 132               HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST)         |
 133               HINIC_MSG_HEADER_SET(direction, DIRECTION)       |
 134               HINIC_MSG_HEADER_SET(cmd, CMD)                   |
 135               HINIC_MSG_HEADER_SET(HINIC_HWIF_PCI_INTF(hwif), PCI_INTF) |
 136               HINIC_MSG_HEADER_SET(HINIC_HWIF_PF_IDX(hwif), PF_IDX)     |
 137               HINIC_MSG_HEADER_SET(msg_id, MSG_ID);
 138}
 139
 140/**
 141 * prepare_mgmt_cmd - prepare the mgmt command
 142 * @mgmt_cmd: pointer to the command to prepare
 143 * @header: pointer of the header for the message
 144 * @msg: the data of the message
 145 * @msg_len: the length of the message
 146 **/
 147static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, u8 *msg, u16 msg_len)
 148{
 149        memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
 150
 151        mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;
 152        memcpy(mgmt_cmd, header, sizeof(*header));
 153
 154        mgmt_cmd += sizeof(*header);
 155        memcpy(mgmt_cmd, msg, msg_len);
 156}
 157
 158/**
 159 * mgmt_msg_len - calculate the total message length
 160 * @msg_data_len: the length of the message data
 161 *
 162 * Return the total message length
 163 **/
 164static u16 mgmt_msg_len(u16 msg_data_len)
 165{
 166        /* RSVD + HEADER_SIZE + DATA_LEN */
 167        u16 msg_len = MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len;
 168
 169        if (msg_len > MGMT_MSG_LEN_MIN)
 170                msg_len = MGMT_MSG_LEN_MIN +
 171                           ALIGN((msg_len - MGMT_MSG_LEN_MIN),
 172                                 MGMT_MSG_LEN_STEP);
 173        else
 174                msg_len = MGMT_MSG_LEN_MIN;
 175
 176        return msg_len;
 177}
 178
 179/**
 180 * send_msg_to_mgmt - send message to mgmt by API CMD
 181 * @pf_to_mgmt: PF to MGMT channel
 182 * @mod: module in the chip that will get the message
 183 * @cmd: command of the message
 184 * @data: the msg data
 185 * @data_len: the msg data length
 186 * @ack_type: ask for response
 187 * @direction: the direction of the original message
 188 * @resp_msg_id: msg id to response for
 189 *
 190 * Return 0 - Success, negative - Failure
 191 **/
 192static int send_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
 193                            enum hinic_mod_type mod, u8 cmd,
 194                            u8 *data, u16 data_len,
 195                            enum msg_ack_type ack_type,
 196                            enum mgmt_direction_type direction,
 197                            u16 resp_msg_id)
 198{
 199        struct hinic_api_cmd_chain *chain;
 200        u64 header;
 201        u16 msg_id;
 202
 203        msg_id = SYNC_MSG_ID(pf_to_mgmt);
 204
 205        if (direction == MGMT_RESP) {
 206                header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,
 207                                        direction, cmd, resp_msg_id);
 208        } else {
 209                SYNC_MSG_ID_INC(pf_to_mgmt);
 210                header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,
 211                                        direction, cmd, msg_id);
 212        }
 213
 214        prepare_mgmt_cmd(pf_to_mgmt->sync_msg_buf, &header, data, data_len);
 215
 216        chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_TO_MGMT_CPU];
 217        return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT,
 218                                   pf_to_mgmt->sync_msg_buf,
 219                                   mgmt_msg_len(data_len));
 220}
 221
 222/**
 223 * msg_to_mgmt_sync - send sync message to mgmt
 224 * @pf_to_mgmt: PF to MGMT channel
 225 * @mod: module in the chip that will get the message
 226 * @cmd: command of the message
 227 * @buf_in: the msg data
 228 * @in_size: the msg data length
 229 * @buf_out: response
 230 * @out_size: response length
 231 * @direction: the direction of the original message
 232 * @resp_msg_id: msg id to response for
 233 *
 234 * Return 0 - Success, negative - Failure
 235 **/
 236static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
 237                            enum hinic_mod_type mod, u8 cmd,
 238                            u8 *buf_in, u16 in_size,
 239                            u8 *buf_out, u16 *out_size,
 240                            enum mgmt_direction_type direction,
 241                            u16 resp_msg_id)
 242{
 243        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 244        struct pci_dev *pdev = hwif->pdev;
 245        struct hinic_recv_msg *recv_msg;
 246        struct completion *recv_done;
 247        u16 msg_id;
 248        int err;
 249
 250        /* Lock the sync_msg_buf */
 251        down(&pf_to_mgmt->sync_msg_lock);
 252
 253        recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
 254        recv_done = &recv_msg->recv_done;
 255
 256        if (resp_msg_id == MSG_NOT_RESP)
 257                msg_id = SYNC_MSG_ID(pf_to_mgmt);
 258        else
 259                msg_id = resp_msg_id;
 260
 261        init_completion(recv_done);
 262
 263        err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
 264                               MSG_ACK, direction, resp_msg_id);
 265        if (err) {
 266                dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n");
 267                goto unlock_sync_msg;
 268        }
 269
 270        if (!wait_for_completion_timeout(recv_done, MGMT_MSG_TIMEOUT)) {
 271                dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
 272                err = -ETIMEDOUT;
 273                goto unlock_sync_msg;
 274        }
 275
 276        smp_rmb();      /* verify reading after completion */
 277
 278        if (recv_msg->msg_id != msg_id) {
 279                dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);
 280                err = -EFAULT;
 281                goto unlock_sync_msg;
 282        }
 283
 284        if ((buf_out) && (recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE)) {
 285                memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);
 286                *out_size = recv_msg->msg_len;
 287        }
 288
 289unlock_sync_msg:
 290        up(&pf_to_mgmt->sync_msg_lock);
 291        return err;
 292}
 293
 294/**
 295 * msg_to_mgmt_async - send message to mgmt without response
 296 * @pf_to_mgmt: PF to MGMT channel
 297 * @mod: module in the chip that will get the message
 298 * @cmd: command of the message
 299 * @buf_in: the msg data
 300 * @in_size: the msg data length
 301 * @direction: the direction of the original message
 302 * @resp_msg_id: msg id to response for
 303 *
 304 * Return 0 - Success, negative - Failure
 305 **/
 306static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt,
 307                             enum hinic_mod_type mod, u8 cmd,
 308                             u8 *buf_in, u16 in_size,
 309                             enum mgmt_direction_type direction,
 310                             u16 resp_msg_id)
 311{
 312        int err;
 313
 314        /* Lock the sync_msg_buf */
 315        down(&pf_to_mgmt->sync_msg_lock);
 316
 317        err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
 318                               MSG_NO_ACK, direction, resp_msg_id);
 319
 320        up(&pf_to_mgmt->sync_msg_lock);
 321        return err;
 322}
 323
 324/**
 325 * hinic_msg_to_mgmt - send message to mgmt
 326 * @pf_to_mgmt: PF to MGMT channel
 327 * @mod: module in the chip that will get the message
 328 * @cmd: command of the message
 329 * @buf_in: the msg data
 330 * @in_size: the msg data length
 331 * @buf_out: response
 332 * @out_size: returned response length
 333 * @sync: sync msg or async msg
 334 *
 335 * Return 0 - Success, negative - Failure
 336 **/
 337int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
 338                      enum hinic_mod_type mod, u8 cmd,
 339                      void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
 340                      enum hinic_mgmt_msg_type sync)
 341{
 342        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 343        struct pci_dev *pdev = hwif->pdev;
 344
 345        if (sync != HINIC_MGMT_MSG_SYNC) {
 346                dev_err(&pdev->dev, "Invalid MGMT msg type\n");
 347                return -EINVAL;
 348        }
 349
 350        if (!MSG_SZ_IS_VALID(in_size)) {
 351                dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");
 352                return -EINVAL;
 353        }
 354
 355        return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
 356                                buf_out, out_size, MGMT_DIRECT_SEND,
 357                                MSG_NOT_RESP);
 358}
 359
 360/**
 361 * mgmt_recv_msg_handler - handler for message from mgmt cpu
 362 * @pf_to_mgmt: PF to MGMT channel
 363 * @recv_msg: received message details
 364 **/
 365static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
 366                                  struct hinic_recv_msg *recv_msg)
 367{
 368        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 369        struct pci_dev *pdev = hwif->pdev;
 370        u8 *buf_out = recv_msg->buf_out;
 371        struct hinic_mgmt_cb *mgmt_cb;
 372        unsigned long cb_state;
 373        u16 out_size = 0;
 374
 375        if (recv_msg->mod >= HINIC_MOD_MAX) {
 376                dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
 377                        recv_msg->mod);
 378                return;
 379        }
 380
 381        mgmt_cb = &pf_to_mgmt->mgmt_cb[recv_msg->mod];
 382
 383        cb_state = cmpxchg(&mgmt_cb->state,
 384                           HINIC_MGMT_CB_ENABLED,
 385                           HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
 386
 387        if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
 388                mgmt_cb->cb(mgmt_cb->handle, recv_msg->cmd,
 389                            recv_msg->msg, recv_msg->msg_len,
 390                            buf_out, &out_size);
 391        else
 392                dev_err(&pdev->dev, "No MGMT msg handler, mod = %d\n",
 393                        recv_msg->mod);
 394
 395        mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
 396
 397        if (!recv_msg->async_mgmt_to_pf)
 398                /* MGMT sent sync msg, send the response */
 399                msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, recv_msg->cmd,
 400                                  buf_out, out_size, MGMT_RESP,
 401                                  recv_msg->msg_id);
 402}
 403
 404/**
 405 * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
 406 * @pf_to_mgmt: PF to MGMT channel
 407 * @recv_msg: received message details
 408 **/
 409static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
 410                                  struct hinic_recv_msg *recv_msg)
 411{
 412        wmb();  /* verify writing all, before reading */
 413
 414        complete(&recv_msg->recv_done);
 415}
 416
 417/**
 418 * recv_mgmt_msg_handler - handler for a message from mgmt cpu
 419 * @pf_to_mgmt: PF to MGMT channel
 420 * @header: the header of the message
 421 * @recv_msg: received message details
 422 **/
 423static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
 424                                  u64 *header, struct hinic_recv_msg *recv_msg)
 425{
 426        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 427        struct pci_dev *pdev = hwif->pdev;
 428        int seq_id, seg_len;
 429        u8 *msg_body;
 430
 431        seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
 432        seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
 433
 434        if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
 435                dev_err(&pdev->dev, "recv big mgmt msg\n");
 436                return;
 437        }
 438
 439        msg_body = (u8 *)header + sizeof(*header);
 440        memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
 441
 442        if (!HINIC_MSG_HEADER_GET(*header, LAST))
 443                return;
 444
 445        recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
 446        recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
 447        recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
 448                                                          ASYNC_MGMT_TO_PF);
 449        recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
 450        recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
 451
 452        if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
 453                mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
 454        else
 455                mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
 456}
 457
 458/**
 459 * mgmt_msg_aeqe_handler - handler for a mgmt message event
 460 * @handle: PF to MGMT channel
 461 * @data: the header of the message
 462 * @size: unused
 463 **/
 464static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
 465{
 466        struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
 467        struct hinic_recv_msg *recv_msg;
 468        u64 *header = (u64 *)data;
 469
 470        recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
 471                   MGMT_DIRECT_SEND ?
 472                   &pf_to_mgmt->recv_msg_from_mgmt :
 473                   &pf_to_mgmt->recv_resp_msg_from_mgmt;
 474
 475        recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
 476}
 477
 478/**
 479 * alloc_recv_msg - allocate receive message memory
 480 * @pf_to_mgmt: PF to MGMT channel
 481 * @recv_msg: pointer that will hold the allocated data
 482 *
 483 * Return 0 - Success, negative - Failure
 484 **/
 485static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
 486                          struct hinic_recv_msg *recv_msg)
 487{
 488        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 489        struct pci_dev *pdev = hwif->pdev;
 490
 491        recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
 492                                     GFP_KERNEL);
 493        if (!recv_msg->msg)
 494                return -ENOMEM;
 495
 496        recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
 497                                         GFP_KERNEL);
 498        if (!recv_msg->buf_out)
 499                return -ENOMEM;
 500
 501        return 0;
 502}
 503
 504/**
 505 * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
 506 * @pf_to_mgmt: PF to MGMT channel
 507 *
 508 * Return 0 - Success, negative - Failure
 509 **/
 510static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
 511{
 512        struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 513        struct pci_dev *pdev = hwif->pdev;
 514        int err;
 515
 516        err = alloc_recv_msg(pf_to_mgmt,
 517                             &pf_to_mgmt->recv_msg_from_mgmt);
 518        if (err) {
 519                dev_err(&pdev->dev, "Failed to allocate recv msg\n");
 520                return err;
 521        }
 522
 523        err = alloc_recv_msg(pf_to_mgmt,
 524                             &pf_to_mgmt->recv_resp_msg_from_mgmt);
 525        if (err) {
 526                dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
 527                return err;
 528        }
 529
 530        pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
 531                                                MAX_PF_MGMT_BUF_SIZE,
 532                                                GFP_KERNEL);
 533        if (!pf_to_mgmt->sync_msg_buf)
 534                return -ENOMEM;
 535
 536        return 0;
 537}
 538
 539/**
 540 * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
 541 * @pf_to_mgmt: PF to MGMT channel
 542 * @hwif: HW interface the PF to MGMT will use for accessing HW
 543 *
 544 * Return 0 - Success, negative - Failure
 545 **/
 546int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
 547                          struct hinic_hwif *hwif)
 548{
 549        struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
 550        struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 551        struct pci_dev *pdev = hwif->pdev;
 552        int err;
 553
 554        pf_to_mgmt->hwif = hwif;
 555
 556        sema_init(&pf_to_mgmt->sync_msg_lock, 1);
 557        pf_to_mgmt->sync_msg_id = 0;
 558
 559        err = alloc_msg_buf(pf_to_mgmt);
 560        if (err) {
 561                dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
 562                return err;
 563        }
 564
 565        err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
 566        if (err) {
 567                dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
 568                return err;
 569        }
 570
 571        hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
 572                                 pf_to_mgmt,
 573                                 mgmt_msg_aeqe_handler);
 574        return 0;
 575}
 576
 577/**
 578 * hinic_pf_to_mgmt_free - free PF to MGMT channel
 579 * @pf_to_mgmt: PF to MGMT channel
 580 **/
 581void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
 582{
 583        struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
 584        struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 585
 586        hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
 587        hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
 588}
 589