682 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Huawei HiNIC PCI Express Linux driver4 * Copyright(c) 2017 Huawei Technologies Co., Ltd5 */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 <net/devlink.h>16#include <asm/barrier.h>17 18#include "hinic_devlink.h"19#include "hinic_hw_if.h"20#include "hinic_hw_eqs.h"21#include "hinic_hw_api_cmd.h"22#include "hinic_hw_mgmt.h"23#include "hinic_hw_dev.h"24 25#define SYNC_MSG_ID_MASK 0x1FF26 27#define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id)28 29#define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \30 ((SYNC_MSG_ID(pf_to_mgmt) + 1) & \31 SYNC_MSG_ID_MASK))32 33#define MSG_SZ_IS_VALID(in_size) ((in_size) <= MAX_MSG_LEN)34 35#define MGMT_MSG_LEN_MIN 2036#define MGMT_MSG_LEN_STEP 1637#define MGMT_MSG_RSVD_FOR_DEV 838 39#define SEGMENT_LEN 4840 41#define MAX_PF_MGMT_BUF_SIZE 204842 43/* Data should be SEG LEN size aligned */44#define MAX_MSG_LEN 201645 46#define MSG_NOT_RESP 0xFFFF47 48#define MGMT_MSG_TIMEOUT 500049 50#define SET_FUNC_PORT_MBOX_TIMEOUT 3000051 52#define SET_FUNC_PORT_MGMT_TIMEOUT 2500053 54#define UPDATE_FW_MGMT_TIMEOUT 2000055 56#define mgmt_to_pfhwdev(pf_mgmt) \57 container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)58 59enum msg_segment_type {60 NOT_LAST_SEGMENT = 0,61 LAST_SEGMENT = 1,62};63 64enum mgmt_direction_type {65 MGMT_DIRECT_SEND = 0,66 MGMT_RESP = 1,67};68 69enum msg_ack_type {70 MSG_ACK = 0,71 MSG_NO_ACK = 1,72};73 74/**75 * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module76 * @pf_to_mgmt: PF to MGMT channel77 * @mod: module in the chip that this handler will handle its messages78 * @handle: private data for the callback79 * @callback: the handler that will handle messages80 **/81void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,82 enum hinic_mod_type mod,83 void *handle,84 void (*callback)(void *handle,85 u8 cmd, void *buf_in,86 u16 in_size, void *buf_out,87 u16 *out_size))88{89 struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];90 91 mgmt_cb->cb = callback;92 mgmt_cb->handle = handle;93 mgmt_cb->state = HINIC_MGMT_CB_ENABLED;94}95 96/**97 * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module98 * @pf_to_mgmt: PF to MGMT channel99 * @mod: module in the chip that this handler handles its messages100 **/101void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,102 enum hinic_mod_type mod)103{104 struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];105 106 mgmt_cb->state &= ~HINIC_MGMT_CB_ENABLED;107 108 while (mgmt_cb->state & HINIC_MGMT_CB_RUNNING)109 schedule();110 111 mgmt_cb->cb = NULL;112}113 114/**115 * prepare_header - prepare the header of the message116 * @pf_to_mgmt: PF to MGMT channel117 * @msg_len: the length of the message118 * @mod: module in the chip that will get the message119 * @ack_type: ask for response120 * @direction: the direction of the message121 * @cmd: command of the message122 * @msg_id: message id123 *124 * Return the prepared header value125 **/126static u64 prepare_header(struct hinic_pf_to_mgmt *pf_to_mgmt,127 u16 msg_len, enum hinic_mod_type mod,128 enum msg_ack_type ack_type,129 enum mgmt_direction_type direction,130 u16 cmd, u16 msg_id)131{132 struct hinic_hwif *hwif = pf_to_mgmt->hwif;133 134 return HINIC_MSG_HEADER_SET(msg_len, MSG_LEN) |135 HINIC_MSG_HEADER_SET(mod, MODULE) |136 HINIC_MSG_HEADER_SET(SEGMENT_LEN, SEG_LEN) |137 HINIC_MSG_HEADER_SET(ack_type, NO_ACK) |138 HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) |139 HINIC_MSG_HEADER_SET(0, SEQID) |140 HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST) |141 HINIC_MSG_HEADER_SET(direction, DIRECTION) |142 HINIC_MSG_HEADER_SET(cmd, CMD) |143 HINIC_MSG_HEADER_SET(HINIC_HWIF_PCI_INTF(hwif), PCI_INTF) |144 HINIC_MSG_HEADER_SET(HINIC_HWIF_PF_IDX(hwif), PF_IDX) |145 HINIC_MSG_HEADER_SET(msg_id, MSG_ID);146}147 148/**149 * prepare_mgmt_cmd - prepare the mgmt command150 * @mgmt_cmd: pointer to the command to prepare151 * @header: pointer of the header for the message152 * @msg: the data of the message153 * @msg_len: the length of the message154 **/155static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, u8 *msg, u16 msg_len)156{157 memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);158 159 mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;160 memcpy(mgmt_cmd, header, sizeof(*header));161 162 mgmt_cmd += sizeof(*header);163 memcpy(mgmt_cmd, msg, msg_len);164}165 166/**167 * mgmt_msg_len - calculate the total message length168 * @msg_data_len: the length of the message data169 *170 * Return the total message length171 **/172static u16 mgmt_msg_len(u16 msg_data_len)173{174 /* RSVD + HEADER_SIZE + DATA_LEN */175 u16 msg_len = MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len;176 177 if (msg_len > MGMT_MSG_LEN_MIN)178 msg_len = MGMT_MSG_LEN_MIN +179 ALIGN((msg_len - MGMT_MSG_LEN_MIN),180 MGMT_MSG_LEN_STEP);181 else182 msg_len = MGMT_MSG_LEN_MIN;183 184 return msg_len;185}186 187/**188 * send_msg_to_mgmt - send message to mgmt by API CMD189 * @pf_to_mgmt: PF to MGMT channel190 * @mod: module in the chip that will get the message191 * @cmd: command of the message192 * @data: the msg data193 * @data_len: the msg data length194 * @ack_type: ask for response195 * @direction: the direction of the original message196 * @resp_msg_id: msg id to response for197 *198 * Return 0 - Success, negative - Failure199 **/200static int send_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,201 enum hinic_mod_type mod, u8 cmd,202 u8 *data, u16 data_len,203 enum msg_ack_type ack_type,204 enum mgmt_direction_type direction,205 u16 resp_msg_id)206{207 struct hinic_api_cmd_chain *chain;208 u64 header;209 u16 msg_id;210 211 msg_id = SYNC_MSG_ID(pf_to_mgmt);212 213 if (direction == MGMT_RESP) {214 header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,215 direction, cmd, resp_msg_id);216 } else {217 SYNC_MSG_ID_INC(pf_to_mgmt);218 header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,219 direction, cmd, msg_id);220 }221 222 prepare_mgmt_cmd(pf_to_mgmt->sync_msg_buf, &header, data, data_len);223 224 chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_TO_MGMT_CPU];225 return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT,226 pf_to_mgmt->sync_msg_buf,227 mgmt_msg_len(data_len));228}229 230/**231 * msg_to_mgmt_sync - send sync message to mgmt232 * @pf_to_mgmt: PF to MGMT channel233 * @mod: module in the chip that will get the message234 * @cmd: command of the message235 * @buf_in: the msg data236 * @in_size: the msg data length237 * @buf_out: response238 * @out_size: response length239 * @direction: the direction of the original message240 * @resp_msg_id: msg id to response for241 * @timeout: time-out period of waiting for response242 *243 * Return 0 - Success, negative - Failure244 **/245static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,246 enum hinic_mod_type mod, u8 cmd,247 u8 *buf_in, u16 in_size,248 u8 *buf_out, u16 *out_size,249 enum mgmt_direction_type direction,250 u16 resp_msg_id, u32 timeout)251{252 struct hinic_hwif *hwif = pf_to_mgmt->hwif;253 struct pci_dev *pdev = hwif->pdev;254 struct hinic_recv_msg *recv_msg;255 struct completion *recv_done;256 unsigned long timeo;257 u16 msg_id;258 int err;259 260 /* Lock the sync_msg_buf */261 down(&pf_to_mgmt->sync_msg_lock);262 263 recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;264 recv_done = &recv_msg->recv_done;265 266 if (resp_msg_id == MSG_NOT_RESP)267 msg_id = SYNC_MSG_ID(pf_to_mgmt);268 else269 msg_id = resp_msg_id;270 271 init_completion(recv_done);272 273 err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,274 MSG_ACK, direction, resp_msg_id);275 if (err) {276 dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n");277 goto unlock_sync_msg;278 }279 280 timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);281 282 if (!wait_for_completion_timeout(recv_done, timeo)) {283 dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);284 hinic_dump_aeq_info(pf_to_mgmt->hwdev);285 err = -ETIMEDOUT;286 goto unlock_sync_msg;287 }288 289 smp_rmb(); /* verify reading after completion */290 291 if (recv_msg->msg_id != msg_id) {292 dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);293 err = -EFAULT;294 goto unlock_sync_msg;295 }296 297 if (buf_out && recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE) {298 memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);299 *out_size = recv_msg->msg_len;300 }301 302unlock_sync_msg:303 up(&pf_to_mgmt->sync_msg_lock);304 return err;305}306 307/**308 * msg_to_mgmt_async - send message to mgmt without response309 * @pf_to_mgmt: PF to MGMT channel310 * @mod: module in the chip that will get the message311 * @cmd: command of the message312 * @buf_in: the msg data313 * @in_size: the msg data length314 * @direction: the direction of the original message315 * @resp_msg_id: msg id to response for316 *317 * Return 0 - Success, negative - Failure318 **/319static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt,320 enum hinic_mod_type mod, u8 cmd,321 u8 *buf_in, u16 in_size,322 enum mgmt_direction_type direction,323 u16 resp_msg_id)324{325 int err;326 327 /* Lock the sync_msg_buf */328 down(&pf_to_mgmt->sync_msg_lock);329 330 err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,331 MSG_NO_ACK, direction, resp_msg_id);332 333 up(&pf_to_mgmt->sync_msg_lock);334 return err;335}336 337/**338 * hinic_msg_to_mgmt - send message to mgmt339 * @pf_to_mgmt: PF to MGMT channel340 * @mod: module in the chip that will get the message341 * @cmd: command of the message342 * @buf_in: the msg data343 * @in_size: the msg data length344 * @buf_out: response345 * @out_size: returned response length346 * @sync: sync msg or async msg347 *348 * Return 0 - Success, negative - Failure349 **/350int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,351 enum hinic_mod_type mod, u8 cmd,352 void *buf_in, u16 in_size, void *buf_out, u16 *out_size,353 enum hinic_mgmt_msg_type sync)354{355 struct hinic_hwif *hwif = pf_to_mgmt->hwif;356 struct pci_dev *pdev = hwif->pdev;357 u32 timeout = 0;358 359 if (sync != HINIC_MGMT_MSG_SYNC) {360 dev_err(&pdev->dev, "Invalid MGMT msg type\n");361 return -EINVAL;362 }363 364 if (!MSG_SZ_IS_VALID(in_size)) {365 dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");366 return -EINVAL;367 }368 369 if (HINIC_IS_VF(hwif)) {370 if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)371 timeout = SET_FUNC_PORT_MBOX_TIMEOUT;372 373 return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,374 in_size, buf_out, out_size, timeout);375 } else {376 if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)377 timeout = SET_FUNC_PORT_MGMT_TIMEOUT;378 else if (cmd == HINIC_PORT_CMD_UPDATE_FW)379 timeout = UPDATE_FW_MGMT_TIMEOUT;380 381 return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,382 buf_out, out_size, MGMT_DIRECT_SEND,383 MSG_NOT_RESP, timeout);384 }385}386 387static void recv_mgmt_msg_work_handler(struct work_struct *work)388{389 struct hinic_mgmt_msg_handle_work *mgmt_work =390 container_of(work, struct hinic_mgmt_msg_handle_work, work);391 struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;392 struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;393 u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;394 struct hinic_mgmt_cb *mgmt_cb;395 unsigned long cb_state;396 u16 out_size = 0;397 398 memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);399 400 if (mgmt_work->mod >= HINIC_MOD_MAX) {401 dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",402 mgmt_work->mod);403 kfree(mgmt_work->msg);404 kfree(mgmt_work);405 return;406 }407 408 mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];409 410 cb_state = cmpxchg(&mgmt_cb->state,411 HINIC_MGMT_CB_ENABLED,412 HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);413 414 if (cb_state == HINIC_MGMT_CB_ENABLED && mgmt_cb->cb)415 mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,416 mgmt_work->msg, mgmt_work->msg_len,417 buf_out, &out_size);418 else419 dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",420 mgmt_work->mod, mgmt_work->cmd);421 422 mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;423 424 if (!mgmt_work->async_mgmt_to_pf)425 /* MGMT sent sync msg, send the response */426 msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,427 buf_out, out_size, MGMT_RESP,428 mgmt_work->msg_id);429 430 kfree(mgmt_work->msg);431 kfree(mgmt_work);432}433 434/**435 * mgmt_recv_msg_handler - handler for message from mgmt cpu436 * @pf_to_mgmt: PF to MGMT channel437 * @recv_msg: received message details438 **/439static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,440 struct hinic_recv_msg *recv_msg)441{442 struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;443 444 mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);445 if (!mgmt_work)446 return;447 448 if (recv_msg->msg_len) {449 mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);450 if (!mgmt_work->msg) {451 kfree(mgmt_work);452 return;453 }454 }455 456 mgmt_work->pf_to_mgmt = pf_to_mgmt;457 mgmt_work->msg_len = recv_msg->msg_len;458 memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);459 mgmt_work->msg_id = recv_msg->msg_id;460 mgmt_work->mod = recv_msg->mod;461 mgmt_work->cmd = recv_msg->cmd;462 mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;463 464 INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);465 queue_work(pf_to_mgmt->workq, &mgmt_work->work);466}467 468/**469 * mgmt_resp_msg_handler - handler for a response message from mgmt cpu470 * @pf_to_mgmt: PF to MGMT channel471 * @recv_msg: received message details472 **/473static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,474 struct hinic_recv_msg *recv_msg)475{476 wmb(); /* verify writing all, before reading */477 478 complete(&recv_msg->recv_done);479}480 481/**482 * recv_mgmt_msg_handler - handler for a message from mgmt cpu483 * @pf_to_mgmt: PF to MGMT channel484 * @header: the header of the message485 * @recv_msg: received message details486 **/487static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,488 u64 *header, struct hinic_recv_msg *recv_msg)489{490 struct hinic_hwif *hwif = pf_to_mgmt->hwif;491 struct pci_dev *pdev = hwif->pdev;492 int seq_id, seg_len;493 u8 *msg_body;494 495 seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);496 seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);497 498 if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {499 dev_err(&pdev->dev, "recv big mgmt msg\n");500 return;501 }502 503 msg_body = (u8 *)header + sizeof(*header);504 memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);505 506 if (!HINIC_MSG_HEADER_GET(*header, LAST))507 return;508 509 recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);510 recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);511 recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,512 ASYNC_MGMT_TO_PF);513 recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);514 recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);515 516 if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)517 mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);518 else519 mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);520}521 522/**523 * mgmt_msg_aeqe_handler - handler for a mgmt message event524 * @handle: PF to MGMT channel525 * @data: the header of the message526 * @size: unused527 **/528static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)529{530 struct hinic_pf_to_mgmt *pf_to_mgmt = handle;531 struct hinic_recv_msg *recv_msg;532 u64 *header = (u64 *)data;533 534 recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==535 MGMT_DIRECT_SEND ?536 &pf_to_mgmt->recv_msg_from_mgmt :537 &pf_to_mgmt->recv_resp_msg_from_mgmt;538 539 recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);540}541 542/**543 * alloc_recv_msg - allocate receive message memory544 * @pf_to_mgmt: PF to MGMT channel545 * @recv_msg: pointer that will hold the allocated data546 *547 * Return 0 - Success, negative - Failure548 **/549static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,550 struct hinic_recv_msg *recv_msg)551{552 struct hinic_hwif *hwif = pf_to_mgmt->hwif;553 struct pci_dev *pdev = hwif->pdev;554 555 recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,556 GFP_KERNEL);557 if (!recv_msg->msg)558 return -ENOMEM;559 560 recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,561 GFP_KERNEL);562 if (!recv_msg->buf_out)563 return -ENOMEM;564 565 return 0;566}567 568/**569 * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel570 * @pf_to_mgmt: PF to MGMT channel571 *572 * Return 0 - Success, negative - Failure573 **/574static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)575{576 struct hinic_hwif *hwif = pf_to_mgmt->hwif;577 struct pci_dev *pdev = hwif->pdev;578 int err;579 580 err = alloc_recv_msg(pf_to_mgmt,581 &pf_to_mgmt->recv_msg_from_mgmt);582 if (err) {583 dev_err(&pdev->dev, "Failed to allocate recv msg\n");584 return err;585 }586 587 err = alloc_recv_msg(pf_to_mgmt,588 &pf_to_mgmt->recv_resp_msg_from_mgmt);589 if (err) {590 dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");591 return err;592 }593 594 pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,595 MAX_PF_MGMT_BUF_SIZE,596 GFP_KERNEL);597 if (!pf_to_mgmt->sync_msg_buf)598 return -ENOMEM;599 600 pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,601 MAX_PF_MGMT_BUF_SIZE,602 GFP_KERNEL);603 if (!pf_to_mgmt->mgmt_ack_buf)604 return -ENOMEM;605 606 return 0;607}608 609/**610 * hinic_pf_to_mgmt_init - initialize PF to MGMT channel611 * @pf_to_mgmt: PF to MGMT channel612 * @hwif: HW interface the PF to MGMT will use for accessing HW613 *614 * Return 0 - Success, negative - Failure615 **/616int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,617 struct hinic_hwif *hwif)618{619 struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);620 struct hinic_hwdev *hwdev = &pfhwdev->hwdev;621 struct pci_dev *pdev = hwif->pdev;622 int err;623 624 pf_to_mgmt->hwif = hwif;625 pf_to_mgmt->hwdev = hwdev;626 627 if (HINIC_IS_VF(hwif))628 return 0;629 630 err = hinic_health_reporters_create(hwdev->devlink_dev);631 if (err)632 return err;633 634 sema_init(&pf_to_mgmt->sync_msg_lock, 1);635 pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");636 if (!pf_to_mgmt->workq) {637 dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");638 hinic_health_reporters_destroy(hwdev->devlink_dev);639 return -ENOMEM;640 }641 pf_to_mgmt->sync_msg_id = 0;642 643 err = alloc_msg_buf(pf_to_mgmt);644 if (err) {645 dev_err(&pdev->dev, "Failed to allocate msg buffers\n");646 destroy_workqueue(pf_to_mgmt->workq);647 hinic_health_reporters_destroy(hwdev->devlink_dev);648 return err;649 }650 651 err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);652 if (err) {653 dev_err(&pdev->dev, "Failed to initialize cmd chains\n");654 destroy_workqueue(pf_to_mgmt->workq);655 hinic_health_reporters_destroy(hwdev->devlink_dev);656 return err;657 }658 659 hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,660 pf_to_mgmt,661 mgmt_msg_aeqe_handler);662 return 0;663}664 665/**666 * hinic_pf_to_mgmt_free - free PF to MGMT channel667 * @pf_to_mgmt: PF to MGMT channel668 **/669void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)670{671 struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);672 struct hinic_hwdev *hwdev = &pfhwdev->hwdev;673 674 if (HINIC_IS_VF(hwdev->hwif))675 return;676 677 hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);678 hinic_api_cmd_free(pf_to_mgmt->cmd_chain);679 destroy_workqueue(pf_to_mgmt->workq);680 hinic_health_reporters_destroy(hwdev->devlink_dev);681}682