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                5000
47 
48 #define mgmt_to_pfhwdev(pf_mgmt)        \
49 		container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
50 
51 enum msg_segment_type {
52 	NOT_LAST_SEGMENT = 0,
53 	LAST_SEGMENT     = 1,
54 };
55 
56 enum mgmt_direction_type {
57 	MGMT_DIRECT_SEND = 0,
58 	MGMT_RESP        = 1,
59 };
60 
61 enum 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  **/
73 void 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  **/
93 void 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  **/
118 static 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  **/
147 static 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  **/
164 static 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  **/
192 static 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  **/
236 static 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,
271 					 msecs_to_jiffies(MGMT_MSG_TIMEOUT))) {
272 		dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
273 		err = -ETIMEDOUT;
274 		goto unlock_sync_msg;
275 	}
276 
277 	smp_rmb();      /* verify reading after completion */
278 
279 	if (recv_msg->msg_id != msg_id) {
280 		dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);
281 		err = -EFAULT;
282 		goto unlock_sync_msg;
283 	}
284 
285 	if ((buf_out) && (recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE)) {
286 		memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);
287 		*out_size = recv_msg->msg_len;
288 	}
289 
290 unlock_sync_msg:
291 	up(&pf_to_mgmt->sync_msg_lock);
292 	return err;
293 }
294 
295 /**
296  * msg_to_mgmt_async - send message to mgmt without response
297  * @pf_to_mgmt: PF to MGMT channel
298  * @mod: module in the chip that will get the message
299  * @cmd: command of the message
300  * @buf_in: the msg data
301  * @in_size: the msg data length
302  * @direction: the direction of the original message
303  * @resp_msg_id: msg id to response for
304  *
305  * Return 0 - Success, negative - Failure
306  **/
307 static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt,
308 			     enum hinic_mod_type mod, u8 cmd,
309 			     u8 *buf_in, u16 in_size,
310 			     enum mgmt_direction_type direction,
311 			     u16 resp_msg_id)
312 {
313 	int err;
314 
315 	/* Lock the sync_msg_buf */
316 	down(&pf_to_mgmt->sync_msg_lock);
317 
318 	err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
319 			       MSG_NO_ACK, direction, resp_msg_id);
320 
321 	up(&pf_to_mgmt->sync_msg_lock);
322 	return err;
323 }
324 
325 /**
326  * hinic_msg_to_mgmt - send message to mgmt
327  * @pf_to_mgmt: PF to MGMT channel
328  * @mod: module in the chip that will get the message
329  * @cmd: command of the message
330  * @buf_in: the msg data
331  * @in_size: the msg data length
332  * @buf_out: response
333  * @out_size: returned response length
334  * @sync: sync msg or async msg
335  *
336  * Return 0 - Success, negative - Failure
337  **/
338 int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
339 		      enum hinic_mod_type mod, u8 cmd,
340 		      void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
341 		      enum hinic_mgmt_msg_type sync)
342 {
343 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
344 	struct pci_dev *pdev = hwif->pdev;
345 
346 	if (sync != HINIC_MGMT_MSG_SYNC) {
347 		dev_err(&pdev->dev, "Invalid MGMT msg type\n");
348 		return -EINVAL;
349 	}
350 
351 	if (!MSG_SZ_IS_VALID(in_size)) {
352 		dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");
353 		return -EINVAL;
354 	}
355 
356 	return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
357 				buf_out, out_size, MGMT_DIRECT_SEND,
358 				MSG_NOT_RESP);
359 }
360 
361 /**
362  * mgmt_recv_msg_handler - handler for message from mgmt cpu
363  * @pf_to_mgmt: PF to MGMT channel
364  * @recv_msg: received message details
365  **/
366 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
367 				  struct hinic_recv_msg *recv_msg)
368 {
369 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
370 	struct pci_dev *pdev = hwif->pdev;
371 	u8 *buf_out = recv_msg->buf_out;
372 	struct hinic_mgmt_cb *mgmt_cb;
373 	unsigned long cb_state;
374 	u16 out_size = 0;
375 
376 	if (recv_msg->mod >= HINIC_MOD_MAX) {
377 		dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
378 			recv_msg->mod);
379 		return;
380 	}
381 
382 	mgmt_cb = &pf_to_mgmt->mgmt_cb[recv_msg->mod];
383 
384 	cb_state = cmpxchg(&mgmt_cb->state,
385 			   HINIC_MGMT_CB_ENABLED,
386 			   HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
387 
388 	if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
389 		mgmt_cb->cb(mgmt_cb->handle, recv_msg->cmd,
390 			    recv_msg->msg, recv_msg->msg_len,
391 			    buf_out, &out_size);
392 	else
393 		dev_err(&pdev->dev, "No MGMT msg handler, mod = %d\n",
394 			recv_msg->mod);
395 
396 	mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
397 
398 	if (!recv_msg->async_mgmt_to_pf)
399 		/* MGMT sent sync msg, send the response */
400 		msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, recv_msg->cmd,
401 				  buf_out, out_size, MGMT_RESP,
402 				  recv_msg->msg_id);
403 }
404 
405 /**
406  * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
407  * @pf_to_mgmt: PF to MGMT channel
408  * @recv_msg: received message details
409  **/
410 static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
411 				  struct hinic_recv_msg *recv_msg)
412 {
413 	wmb();  /* verify writing all, before reading */
414 
415 	complete(&recv_msg->recv_done);
416 }
417 
418 /**
419  * recv_mgmt_msg_handler - handler for a message from mgmt cpu
420  * @pf_to_mgmt: PF to MGMT channel
421  * @header: the header of the message
422  * @recv_msg: received message details
423  **/
424 static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
425 				  u64 *header, struct hinic_recv_msg *recv_msg)
426 {
427 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
428 	struct pci_dev *pdev = hwif->pdev;
429 	int seq_id, seg_len;
430 	u8 *msg_body;
431 
432 	seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
433 	seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
434 
435 	if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
436 		dev_err(&pdev->dev, "recv big mgmt msg\n");
437 		return;
438 	}
439 
440 	msg_body = (u8 *)header + sizeof(*header);
441 	memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
442 
443 	if (!HINIC_MSG_HEADER_GET(*header, LAST))
444 		return;
445 
446 	recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
447 	recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
448 	recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
449 							  ASYNC_MGMT_TO_PF);
450 	recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
451 	recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
452 
453 	if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
454 		mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
455 	else
456 		mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
457 }
458 
459 /**
460  * mgmt_msg_aeqe_handler - handler for a mgmt message event
461  * @handle: PF to MGMT channel
462  * @data: the header of the message
463  * @size: unused
464  **/
465 static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
466 {
467 	struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
468 	struct hinic_recv_msg *recv_msg;
469 	u64 *header = (u64 *)data;
470 
471 	recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
472 		   MGMT_DIRECT_SEND ?
473 		   &pf_to_mgmt->recv_msg_from_mgmt :
474 		   &pf_to_mgmt->recv_resp_msg_from_mgmt;
475 
476 	recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
477 }
478 
479 /**
480  * alloc_recv_msg - allocate receive message memory
481  * @pf_to_mgmt: PF to MGMT channel
482  * @recv_msg: pointer that will hold the allocated data
483  *
484  * Return 0 - Success, negative - Failure
485  **/
486 static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
487 			  struct hinic_recv_msg *recv_msg)
488 {
489 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
490 	struct pci_dev *pdev = hwif->pdev;
491 
492 	recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
493 				     GFP_KERNEL);
494 	if (!recv_msg->msg)
495 		return -ENOMEM;
496 
497 	recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
498 					 GFP_KERNEL);
499 	if (!recv_msg->buf_out)
500 		return -ENOMEM;
501 
502 	return 0;
503 }
504 
505 /**
506  * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
507  * @pf_to_mgmt: PF to MGMT channel
508  *
509  * Return 0 - Success, negative - Failure
510  **/
511 static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
512 {
513 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
514 	struct pci_dev *pdev = hwif->pdev;
515 	int err;
516 
517 	err = alloc_recv_msg(pf_to_mgmt,
518 			     &pf_to_mgmt->recv_msg_from_mgmt);
519 	if (err) {
520 		dev_err(&pdev->dev, "Failed to allocate recv msg\n");
521 		return err;
522 	}
523 
524 	err = alloc_recv_msg(pf_to_mgmt,
525 			     &pf_to_mgmt->recv_resp_msg_from_mgmt);
526 	if (err) {
527 		dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
528 		return err;
529 	}
530 
531 	pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
532 						MAX_PF_MGMT_BUF_SIZE,
533 						GFP_KERNEL);
534 	if (!pf_to_mgmt->sync_msg_buf)
535 		return -ENOMEM;
536 
537 	return 0;
538 }
539 
540 /**
541  * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
542  * @pf_to_mgmt: PF to MGMT channel
543  * @hwif: HW interface the PF to MGMT will use for accessing HW
544  *
545  * Return 0 - Success, negative - Failure
546  **/
547 int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
548 			  struct hinic_hwif *hwif)
549 {
550 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
551 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
552 	struct pci_dev *pdev = hwif->pdev;
553 	int err;
554 
555 	pf_to_mgmt->hwif = hwif;
556 
557 	sema_init(&pf_to_mgmt->sync_msg_lock, 1);
558 	pf_to_mgmt->sync_msg_id = 0;
559 
560 	err = alloc_msg_buf(pf_to_mgmt);
561 	if (err) {
562 		dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
563 		return err;
564 	}
565 
566 	err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
567 	if (err) {
568 		dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
569 		return err;
570 	}
571 
572 	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
573 				 pf_to_mgmt,
574 				 mgmt_msg_aeqe_handler);
575 	return 0;
576 }
577 
578 /**
579  * hinic_pf_to_mgmt_free - free PF to MGMT channel
580  * @pf_to_mgmt: PF to MGMT channel
581  **/
582 void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
583 {
584 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
585 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
586 
587 	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
588 	hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
589 }
590