brintos

brintos / linux-shallow public Read only

0
0
Text · 18.6 KiB · 4aa1f43 Raw
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