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