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