Linux-libre 5.7.6-gnu
[librecmc/linux-libre.git] / drivers / net / ethernet / huawei / hinic / hinic_hw_mgmt.c
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 SET_FUNC_PORT_MGMT_TIMEOUT      25000
49
50 #define mgmt_to_pfhwdev(pf_mgmt)        \
51                 container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
52
53 enum msg_segment_type {
54         NOT_LAST_SEGMENT = 0,
55         LAST_SEGMENT     = 1,
56 };
57
58 enum mgmt_direction_type {
59         MGMT_DIRECT_SEND = 0,
60         MGMT_RESP        = 1,
61 };
62
63 enum msg_ack_type {
64         MSG_ACK         = 0,
65         MSG_NO_ACK      = 1,
66 };
67
68 /**
69  * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module
70  * @pf_to_mgmt: PF to MGMT channel
71  * @mod: module in the chip that this handler will handle its messages
72  * @handle: private data for the callback
73  * @callback: the handler that will handle messages
74  **/
75 void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
76                                 enum hinic_mod_type mod,
77                                 void *handle,
78                                 void (*callback)(void *handle,
79                                                  u8 cmd, void *buf_in,
80                                                  u16 in_size, void *buf_out,
81                                                  u16 *out_size))
82 {
83         struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];
84
85         mgmt_cb->cb = callback;
86         mgmt_cb->handle = handle;
87         mgmt_cb->state = HINIC_MGMT_CB_ENABLED;
88 }
89
90 /**
91  * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module
92  * @pf_to_mgmt: PF to MGMT channel
93  * @mod: module in the chip that this handler handles its messages
94  **/
95 void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
96                                   enum hinic_mod_type mod)
97 {
98         struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];
99
100         mgmt_cb->state &= ~HINIC_MGMT_CB_ENABLED;
101
102         while (mgmt_cb->state & HINIC_MGMT_CB_RUNNING)
103                 schedule();
104
105         mgmt_cb->cb = NULL;
106 }
107
108 /**
109  * prepare_header - prepare the header of the message
110  * @pf_to_mgmt: PF to MGMT channel
111  * @msg_len: the length of the message
112  * @mod: module in the chip that will get the message
113  * @ack_type: ask for response
114  * @direction: the direction of the message
115  * @cmd: command of the message
116  * @msg_id: message id
117  *
118  * Return the prepared header value
119  **/
120 static u64 prepare_header(struct hinic_pf_to_mgmt *pf_to_mgmt,
121                           u16 msg_len, enum hinic_mod_type mod,
122                           enum msg_ack_type ack_type,
123                           enum mgmt_direction_type direction,
124                           u16 cmd, u16 msg_id)
125 {
126         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
127
128         return HINIC_MSG_HEADER_SET(msg_len, MSG_LEN)           |
129                HINIC_MSG_HEADER_SET(mod, MODULE)                |
130                HINIC_MSG_HEADER_SET(SEGMENT_LEN, SEG_LEN)       |
131                HINIC_MSG_HEADER_SET(ack_type, NO_ACK)           |
132                HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF)        |
133                HINIC_MSG_HEADER_SET(0, SEQID)                   |
134                HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST)         |
135                HINIC_MSG_HEADER_SET(direction, DIRECTION)       |
136                HINIC_MSG_HEADER_SET(cmd, CMD)                   |
137                HINIC_MSG_HEADER_SET(HINIC_HWIF_PCI_INTF(hwif), PCI_INTF) |
138                HINIC_MSG_HEADER_SET(HINIC_HWIF_PF_IDX(hwif), PF_IDX)     |
139                HINIC_MSG_HEADER_SET(msg_id, MSG_ID);
140 }
141
142 /**
143  * prepare_mgmt_cmd - prepare the mgmt command
144  * @mgmt_cmd: pointer to the command to prepare
145  * @header: pointer of the header for the message
146  * @msg: the data of the message
147  * @msg_len: the length of the message
148  **/
149 static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, u8 *msg, u16 msg_len)
150 {
151         memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
152
153         mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;
154         memcpy(mgmt_cmd, header, sizeof(*header));
155
156         mgmt_cmd += sizeof(*header);
157         memcpy(mgmt_cmd, msg, msg_len);
158 }
159
160 /**
161  * mgmt_msg_len - calculate the total message length
162  * @msg_data_len: the length of the message data
163  *
164  * Return the total message length
165  **/
166 static u16 mgmt_msg_len(u16 msg_data_len)
167 {
168         /* RSVD + HEADER_SIZE + DATA_LEN */
169         u16 msg_len = MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len;
170
171         if (msg_len > MGMT_MSG_LEN_MIN)
172                 msg_len = MGMT_MSG_LEN_MIN +
173                            ALIGN((msg_len - MGMT_MSG_LEN_MIN),
174                                  MGMT_MSG_LEN_STEP);
175         else
176                 msg_len = MGMT_MSG_LEN_MIN;
177
178         return msg_len;
179 }
180
181 /**
182  * send_msg_to_mgmt - send message to mgmt by API CMD
183  * @pf_to_mgmt: PF to MGMT channel
184  * @mod: module in the chip that will get the message
185  * @cmd: command of the message
186  * @data: the msg data
187  * @data_len: the msg data length
188  * @ack_type: ask for response
189  * @direction: the direction of the original message
190  * @resp_msg_id: msg id to response for
191  *
192  * Return 0 - Success, negative - Failure
193  **/
194 static int send_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
195                             enum hinic_mod_type mod, u8 cmd,
196                             u8 *data, u16 data_len,
197                             enum msg_ack_type ack_type,
198                             enum mgmt_direction_type direction,
199                             u16 resp_msg_id)
200 {
201         struct hinic_api_cmd_chain *chain;
202         u64 header;
203         u16 msg_id;
204
205         msg_id = SYNC_MSG_ID(pf_to_mgmt);
206
207         if (direction == MGMT_RESP) {
208                 header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,
209                                         direction, cmd, resp_msg_id);
210         } else {
211                 SYNC_MSG_ID_INC(pf_to_mgmt);
212                 header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,
213                                         direction, cmd, msg_id);
214         }
215
216         prepare_mgmt_cmd(pf_to_mgmt->sync_msg_buf, &header, data, data_len);
217
218         chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_TO_MGMT_CPU];
219         return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT,
220                                    pf_to_mgmt->sync_msg_buf,
221                                    mgmt_msg_len(data_len));
222 }
223
224 /**
225  * msg_to_mgmt_sync - send sync message to mgmt
226  * @pf_to_mgmt: PF to MGMT channel
227  * @mod: module in the chip that will get the message
228  * @cmd: command of the message
229  * @buf_in: the msg data
230  * @in_size: the msg data length
231  * @buf_out: response
232  * @out_size: response length
233  * @direction: the direction of the original message
234  * @resp_msg_id: msg id to response for
235  *
236  * Return 0 - Success, negative - Failure
237  **/
238 static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
239                             enum hinic_mod_type mod, u8 cmd,
240                             u8 *buf_in, u16 in_size,
241                             u8 *buf_out, u16 *out_size,
242                             enum mgmt_direction_type direction,
243                             u16 resp_msg_id, u32 timeout)
244 {
245         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
246         struct pci_dev *pdev = hwif->pdev;
247         struct hinic_recv_msg *recv_msg;
248         struct completion *recv_done;
249         unsigned long timeo;
250         u16 msg_id;
251         int err;
252
253         /* Lock the sync_msg_buf */
254         down(&pf_to_mgmt->sync_msg_lock);
255
256         recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
257         recv_done = &recv_msg->recv_done;
258
259         if (resp_msg_id == MSG_NOT_RESP)
260                 msg_id = SYNC_MSG_ID(pf_to_mgmt);
261         else
262                 msg_id = resp_msg_id;
263
264         init_completion(recv_done);
265
266         err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
267                                MSG_ACK, direction, resp_msg_id);
268         if (err) {
269                 dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n");
270                 goto unlock_sync_msg;
271         }
272
273         timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
274
275         if (!wait_for_completion_timeout(recv_done, timeo)) {
276                 dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
277                 err = -ETIMEDOUT;
278                 goto unlock_sync_msg;
279         }
280
281         smp_rmb();      /* verify reading after completion */
282
283         if (recv_msg->msg_id != msg_id) {
284                 dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);
285                 err = -EFAULT;
286                 goto unlock_sync_msg;
287         }
288
289         if ((buf_out) && (recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE)) {
290                 memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);
291                 *out_size = recv_msg->msg_len;
292         }
293
294 unlock_sync_msg:
295         up(&pf_to_mgmt->sync_msg_lock);
296         return err;
297 }
298
299 /**
300  * msg_to_mgmt_async - send message to mgmt without response
301  * @pf_to_mgmt: PF to MGMT channel
302  * @mod: module in the chip that will get the message
303  * @cmd: command of the message
304  * @buf_in: the msg data
305  * @in_size: the msg data length
306  * @direction: the direction of the original message
307  * @resp_msg_id: msg id to response for
308  *
309  * Return 0 - Success, negative - Failure
310  **/
311 static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt,
312                              enum hinic_mod_type mod, u8 cmd,
313                              u8 *buf_in, u16 in_size,
314                              enum mgmt_direction_type direction,
315                              u16 resp_msg_id)
316 {
317         int err;
318
319         /* Lock the sync_msg_buf */
320         down(&pf_to_mgmt->sync_msg_lock);
321
322         err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
323                                MSG_NO_ACK, direction, resp_msg_id);
324
325         up(&pf_to_mgmt->sync_msg_lock);
326         return err;
327 }
328
329 /**
330  * hinic_msg_to_mgmt - send message to mgmt
331  * @pf_to_mgmt: PF to MGMT channel
332  * @mod: module in the chip that will get the message
333  * @cmd: command of the message
334  * @buf_in: the msg data
335  * @in_size: the msg data length
336  * @buf_out: response
337  * @out_size: returned response length
338  * @sync: sync msg or async msg
339  *
340  * Return 0 - Success, negative - Failure
341  **/
342 int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
343                       enum hinic_mod_type mod, u8 cmd,
344                       void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
345                       enum hinic_mgmt_msg_type sync)
346 {
347         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
348         struct pci_dev *pdev = hwif->pdev;
349         u32 timeout = 0;
350
351         if (sync != HINIC_MGMT_MSG_SYNC) {
352                 dev_err(&pdev->dev, "Invalid MGMT msg type\n");
353                 return -EINVAL;
354         }
355
356         if (!MSG_SZ_IS_VALID(in_size)) {
357                 dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");
358                 return -EINVAL;
359         }
360
361         if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
362                 timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
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, timeout);
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 }