1 // SPDX-License-Identifier: GPL-2.0-only
3 * Huawei HiNIC PCI Express Linux driver
4 * Copyright(c) 2017 Huawei Technologies Co., Ltd
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>
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"
25 #define SYNC_MSG_ID_MASK 0x1FF
27 #define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id)
29 #define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \
30 ((SYNC_MSG_ID(pf_to_mgmt) + 1) & \
33 #define MSG_SZ_IS_VALID(in_size) ((in_size) <= MAX_MSG_LEN)
35 #define MGMT_MSG_LEN_MIN 20
36 #define MGMT_MSG_LEN_STEP 16
37 #define MGMT_MSG_RSVD_FOR_DEV 8
39 #define SEGMENT_LEN 48
41 #define MAX_PF_MGMT_BUF_SIZE 2048
43 /* Data should be SEG LEN size aligned */
44 #define MAX_MSG_LEN 2016
46 #define MSG_NOT_RESP 0xFFFF
48 #define MGMT_MSG_TIMEOUT 5000
50 #define SET_FUNC_PORT_MBOX_TIMEOUT 30000
52 #define SET_FUNC_PORT_MGMT_TIMEOUT 25000
54 #define UPDATE_FW_MGMT_TIMEOUT 20000
56 #define mgmt_to_pfhwdev(pf_mgmt) \
57 container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
59 enum msg_segment_type
{
64 enum mgmt_direction_type
{
75 * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module
76 * @pf_to_mgmt: PF to MGMT channel
77 * @mod: module in the chip that this handler will handle its messages
78 * @handle: private data for the callback
79 * @callback: the handler that will handle messages
81 void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
82 enum hinic_mod_type mod
,
84 void (*callback
)(void *handle
,
86 u16 in_size
, void *buf_out
,
89 struct hinic_mgmt_cb
*mgmt_cb
= &pf_to_mgmt
->mgmt_cb
[mod
];
91 mgmt_cb
->cb
= callback
;
92 mgmt_cb
->handle
= handle
;
93 mgmt_cb
->state
= HINIC_MGMT_CB_ENABLED
;
97 * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module
98 * @pf_to_mgmt: PF to MGMT channel
99 * @mod: module in the chip that this handler handles its messages
101 void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
102 enum hinic_mod_type mod
)
104 struct hinic_mgmt_cb
*mgmt_cb
= &pf_to_mgmt
->mgmt_cb
[mod
];
106 mgmt_cb
->state
&= ~HINIC_MGMT_CB_ENABLED
;
108 while (mgmt_cb
->state
& HINIC_MGMT_CB_RUNNING
)
115 * prepare_header - prepare the header of the message
116 * @pf_to_mgmt: PF to MGMT channel
117 * @msg_len: the length of the message
118 * @mod: module in the chip that will get the message
119 * @ack_type: ask for response
120 * @direction: the direction of the message
121 * @cmd: command of the message
122 * @msg_id: message id
124 * Return the prepared header value
126 static 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
,
132 struct hinic_hwif
*hwif
= pf_to_mgmt
->hwif
;
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
);
149 * prepare_mgmt_cmd - prepare the mgmt command
150 * @mgmt_cmd: pointer to the command to prepare
151 * @header: pointer of the header for the message
152 * @msg: the data of the message
153 * @msg_len: the length of the message
155 static void prepare_mgmt_cmd(u8
*mgmt_cmd
, u64
*header
, u8
*msg
, u16 msg_len
)
157 memset(mgmt_cmd
, 0, MGMT_MSG_RSVD_FOR_DEV
);
159 mgmt_cmd
+= MGMT_MSG_RSVD_FOR_DEV
;
160 memcpy(mgmt_cmd
, header
, sizeof(*header
));
162 mgmt_cmd
+= sizeof(*header
);
163 memcpy(mgmt_cmd
, msg
, msg_len
);
167 * mgmt_msg_len - calculate the total message length
168 * @msg_data_len: the length of the message data
170 * Return the total message length
172 static u16
mgmt_msg_len(u16 msg_data_len
)
174 /* RSVD + HEADER_SIZE + DATA_LEN */
175 u16 msg_len
= MGMT_MSG_RSVD_FOR_DEV
+ sizeof(u64
) + msg_data_len
;
177 if (msg_len
> MGMT_MSG_LEN_MIN
)
178 msg_len
= MGMT_MSG_LEN_MIN
+
179 ALIGN((msg_len
- MGMT_MSG_LEN_MIN
),
182 msg_len
= MGMT_MSG_LEN_MIN
;
188 * send_msg_to_mgmt - send message to mgmt by API CMD
189 * @pf_to_mgmt: PF to MGMT channel
190 * @mod: module in the chip that will get the message
191 * @cmd: command of the message
192 * @data: the msg data
193 * @data_len: the msg data length
194 * @ack_type: ask for response
195 * @direction: the direction of the original message
196 * @resp_msg_id: msg id to response for
198 * Return 0 - Success, negative - Failure
200 static 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
,
207 struct hinic_api_cmd_chain
*chain
;
211 msg_id
= SYNC_MSG_ID(pf_to_mgmt
);
213 if (direction
== MGMT_RESP
) {
214 header
= prepare_header(pf_to_mgmt
, data_len
, mod
, ack_type
,
215 direction
, cmd
, resp_msg_id
);
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
);
222 prepare_mgmt_cmd(pf_to_mgmt
->sync_msg_buf
, &header
, data
, data_len
);
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
));
231 * msg_to_mgmt_sync - send sync message to mgmt
232 * @pf_to_mgmt: PF to MGMT channel
233 * @mod: module in the chip that will get the message
234 * @cmd: command of the message
235 * @buf_in: the msg data
236 * @in_size: the msg data length
238 * @out_size: response length
239 * @direction: the direction of the original message
240 * @resp_msg_id: msg id to response for
241 * @timeout: time-out period of waiting for response
243 * Return 0 - Success, negative - Failure
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
, u32 timeout
)
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
;
260 /* Lock the sync_msg_buf */
261 down(&pf_to_mgmt
->sync_msg_lock
);
263 recv_msg
= &pf_to_mgmt
->recv_resp_msg_from_mgmt
;
264 recv_done
= &recv_msg
->recv_done
;
266 if (resp_msg_id
== MSG_NOT_RESP
)
267 msg_id
= SYNC_MSG_ID(pf_to_mgmt
);
269 msg_id
= resp_msg_id
;
271 init_completion(recv_done
);
273 err
= send_msg_to_mgmt(pf_to_mgmt
, mod
, cmd
, buf_in
, in_size
,
274 MSG_ACK
, direction
, resp_msg_id
);
276 dev_err(&pdev
->dev
, "Failed to send sync msg to mgmt\n");
277 goto unlock_sync_msg
;
280 timeo
= msecs_to_jiffies(timeout
? timeout
: MGMT_MSG_TIMEOUT
);
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
);
286 goto unlock_sync_msg
;
289 smp_rmb(); /* verify reading after completion */
291 if (recv_msg
->msg_id
!= msg_id
) {
292 dev_err(&pdev
->dev
, "incorrect MSG for id = %d\n", msg_id
);
294 goto unlock_sync_msg
;
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
;
303 up(&pf_to_mgmt
->sync_msg_lock
);
308 * msg_to_mgmt_async - send message to mgmt without response
309 * @pf_to_mgmt: PF to MGMT channel
310 * @mod: module in the chip that will get the message
311 * @cmd: command of the message
312 * @buf_in: the msg data
313 * @in_size: the msg data length
314 * @direction: the direction of the original message
315 * @resp_msg_id: msg id to response for
317 * Return 0 - Success, negative - Failure
319 static 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
,
327 /* Lock the sync_msg_buf */
328 down(&pf_to_mgmt
->sync_msg_lock
);
330 err
= send_msg_to_mgmt(pf_to_mgmt
, mod
, cmd
, buf_in
, in_size
,
331 MSG_NO_ACK
, direction
, resp_msg_id
);
333 up(&pf_to_mgmt
->sync_msg_lock
);
338 * hinic_msg_to_mgmt - send message to mgmt
339 * @pf_to_mgmt: PF to MGMT channel
340 * @mod: module in the chip that will get the message
341 * @cmd: command of the message
342 * @buf_in: the msg data
343 * @in_size: the msg data length
345 * @out_size: returned response length
346 * @sync: sync msg or async msg
348 * Return 0 - Success, negative - Failure
350 int 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
)
355 struct hinic_hwif
*hwif
= pf_to_mgmt
->hwif
;
356 struct pci_dev
*pdev
= hwif
->pdev
;
359 if (sync
!= HINIC_MGMT_MSG_SYNC
) {
360 dev_err(&pdev
->dev
, "Invalid MGMT msg type\n");
364 if (!MSG_SZ_IS_VALID(in_size
)) {
365 dev_err(&pdev
->dev
, "Invalid MGMT msg buffer size\n");
369 if (HINIC_IS_VF(hwif
)) {
370 if (cmd
== HINIC_PORT_CMD_SET_FUNC_STATE
)
371 timeout
= SET_FUNC_PORT_MBOX_TIMEOUT
;
373 return hinic_mbox_to_pf(pf_to_mgmt
->hwdev
, mod
, cmd
, buf_in
,
374 in_size
, buf_out
, out_size
, timeout
);
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
;
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
);
387 static void recv_mgmt_msg_work_handler(struct work_struct
*work
)
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
;
398 memset(buf_out
, 0, MAX_PF_MGMT_BUF_SIZE
);
400 if (mgmt_work
->mod
>= HINIC_MOD_MAX
) {
401 dev_err(&pdev
->dev
, "Unknown MGMT MSG module = %d\n",
403 kfree(mgmt_work
->msg
);
408 mgmt_cb
= &pf_to_mgmt
->mgmt_cb
[mgmt_work
->mod
];
410 cb_state
= cmpxchg(&mgmt_cb
->state
,
411 HINIC_MGMT_CB_ENABLED
,
412 HINIC_MGMT_CB_ENABLED
| HINIC_MGMT_CB_RUNNING
);
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
,
419 dev_err(&pdev
->dev
, "No MGMT msg handler, mod: %d, cmd: %d\n",
420 mgmt_work
->mod
, mgmt_work
->cmd
);
422 mgmt_cb
->state
&= ~HINIC_MGMT_CB_RUNNING
;
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
,
430 kfree(mgmt_work
->msg
);
435 * mgmt_recv_msg_handler - handler for message from mgmt cpu
436 * @pf_to_mgmt: PF to MGMT channel
437 * @recv_msg: received message details
439 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
440 struct hinic_recv_msg
*recv_msg
)
442 struct hinic_mgmt_msg_handle_work
*mgmt_work
= NULL
;
443 struct pci_dev
*pdev
= pf_to_mgmt
->hwif
->pdev
;
445 mgmt_work
= kzalloc(sizeof(*mgmt_work
), GFP_KERNEL
);
447 dev_err(&pdev
->dev
, "Allocate mgmt work memory failed\n");
451 if (recv_msg
->msg_len
) {
452 mgmt_work
->msg
= kzalloc(recv_msg
->msg_len
, GFP_KERNEL
);
453 if (!mgmt_work
->msg
) {
454 dev_err(&pdev
->dev
, "Allocate mgmt msg memory failed\n");
460 mgmt_work
->pf_to_mgmt
= pf_to_mgmt
;
461 mgmt_work
->msg_len
= recv_msg
->msg_len
;
462 memcpy(mgmt_work
->msg
, recv_msg
->msg
, recv_msg
->msg_len
);
463 mgmt_work
->msg_id
= recv_msg
->msg_id
;
464 mgmt_work
->mod
= recv_msg
->mod
;
465 mgmt_work
->cmd
= recv_msg
->cmd
;
466 mgmt_work
->async_mgmt_to_pf
= recv_msg
->async_mgmt_to_pf
;
468 INIT_WORK(&mgmt_work
->work
, recv_mgmt_msg_work_handler
);
469 queue_work(pf_to_mgmt
->workq
, &mgmt_work
->work
);
473 * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
474 * @pf_to_mgmt: PF to MGMT channel
475 * @recv_msg: received message details
477 static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
478 struct hinic_recv_msg
*recv_msg
)
480 wmb(); /* verify writing all, before reading */
482 complete(&recv_msg
->recv_done
);
486 * recv_mgmt_msg_handler - handler for a message from mgmt cpu
487 * @pf_to_mgmt: PF to MGMT channel
488 * @header: the header of the message
489 * @recv_msg: received message details
491 static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
492 u64
*header
, struct hinic_recv_msg
*recv_msg
)
494 struct hinic_hwif
*hwif
= pf_to_mgmt
->hwif
;
495 struct pci_dev
*pdev
= hwif
->pdev
;
499 seq_id
= HINIC_MSG_HEADER_GET(*header
, SEQID
);
500 seg_len
= HINIC_MSG_HEADER_GET(*header
, SEG_LEN
);
502 if (seq_id
>= (MAX_MSG_LEN
/ SEGMENT_LEN
)) {
503 dev_err(&pdev
->dev
, "recv big mgmt msg\n");
507 msg_body
= (u8
*)header
+ sizeof(*header
);
508 memcpy(recv_msg
->msg
+ seq_id
* SEGMENT_LEN
, msg_body
, seg_len
);
510 if (!HINIC_MSG_HEADER_GET(*header
, LAST
))
513 recv_msg
->cmd
= HINIC_MSG_HEADER_GET(*header
, CMD
);
514 recv_msg
->mod
= HINIC_MSG_HEADER_GET(*header
, MODULE
);
515 recv_msg
->async_mgmt_to_pf
= HINIC_MSG_HEADER_GET(*header
,
517 recv_msg
->msg_len
= HINIC_MSG_HEADER_GET(*header
, MSG_LEN
);
518 recv_msg
->msg_id
= HINIC_MSG_HEADER_GET(*header
, MSG_ID
);
520 if (HINIC_MSG_HEADER_GET(*header
, DIRECTION
) == MGMT_RESP
)
521 mgmt_resp_msg_handler(pf_to_mgmt
, recv_msg
);
523 mgmt_recv_msg_handler(pf_to_mgmt
, recv_msg
);
527 * mgmt_msg_aeqe_handler - handler for a mgmt message event
528 * @handle: PF to MGMT channel
529 * @data: the header of the message
532 static void mgmt_msg_aeqe_handler(void *handle
, void *data
, u8 size
)
534 struct hinic_pf_to_mgmt
*pf_to_mgmt
= handle
;
535 struct hinic_recv_msg
*recv_msg
;
536 u64
*header
= (u64
*)data
;
538 recv_msg
= HINIC_MSG_HEADER_GET(*header
, DIRECTION
) ==
540 &pf_to_mgmt
->recv_msg_from_mgmt
:
541 &pf_to_mgmt
->recv_resp_msg_from_mgmt
;
543 recv_mgmt_msg_handler(pf_to_mgmt
, header
, recv_msg
);
547 * alloc_recv_msg - allocate receive message memory
548 * @pf_to_mgmt: PF to MGMT channel
549 * @recv_msg: pointer that will hold the allocated data
551 * Return 0 - Success, negative - Failure
553 static int alloc_recv_msg(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
554 struct hinic_recv_msg
*recv_msg
)
556 struct hinic_hwif
*hwif
= pf_to_mgmt
->hwif
;
557 struct pci_dev
*pdev
= hwif
->pdev
;
559 recv_msg
->msg
= devm_kzalloc(&pdev
->dev
, MAX_PF_MGMT_BUF_SIZE
,
564 recv_msg
->buf_out
= devm_kzalloc(&pdev
->dev
, MAX_PF_MGMT_BUF_SIZE
,
566 if (!recv_msg
->buf_out
)
573 * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
574 * @pf_to_mgmt: PF to MGMT channel
576 * Return 0 - Success, negative - Failure
578 static int alloc_msg_buf(struct hinic_pf_to_mgmt
*pf_to_mgmt
)
580 struct hinic_hwif
*hwif
= pf_to_mgmt
->hwif
;
581 struct pci_dev
*pdev
= hwif
->pdev
;
584 err
= alloc_recv_msg(pf_to_mgmt
,
585 &pf_to_mgmt
->recv_msg_from_mgmt
);
587 dev_err(&pdev
->dev
, "Failed to allocate recv msg\n");
591 err
= alloc_recv_msg(pf_to_mgmt
,
592 &pf_to_mgmt
->recv_resp_msg_from_mgmt
);
594 dev_err(&pdev
->dev
, "Failed to allocate resp recv msg\n");
598 pf_to_mgmt
->sync_msg_buf
= devm_kzalloc(&pdev
->dev
,
599 MAX_PF_MGMT_BUF_SIZE
,
601 if (!pf_to_mgmt
->sync_msg_buf
)
604 pf_to_mgmt
->mgmt_ack_buf
= devm_kzalloc(&pdev
->dev
,
605 MAX_PF_MGMT_BUF_SIZE
,
607 if (!pf_to_mgmt
->mgmt_ack_buf
)
614 * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
615 * @pf_to_mgmt: PF to MGMT channel
616 * @hwif: HW interface the PF to MGMT will use for accessing HW
618 * Return 0 - Success, negative - Failure
620 int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt
*pf_to_mgmt
,
621 struct hinic_hwif
*hwif
)
623 struct hinic_pfhwdev
*pfhwdev
= mgmt_to_pfhwdev(pf_to_mgmt
);
624 struct hinic_hwdev
*hwdev
= &pfhwdev
->hwdev
;
625 struct pci_dev
*pdev
= hwif
->pdev
;
628 pf_to_mgmt
->hwif
= hwif
;
629 pf_to_mgmt
->hwdev
= hwdev
;
631 if (HINIC_IS_VF(hwif
))
634 err
= hinic_health_reporters_create(hwdev
->devlink_dev
);
638 sema_init(&pf_to_mgmt
->sync_msg_lock
, 1);
639 pf_to_mgmt
->workq
= create_singlethread_workqueue("hinic_mgmt");
640 if (!pf_to_mgmt
->workq
) {
641 dev_err(&pdev
->dev
, "Failed to initialize MGMT workqueue\n");
642 hinic_health_reporters_destroy(hwdev
->devlink_dev
);
645 pf_to_mgmt
->sync_msg_id
= 0;
647 err
= alloc_msg_buf(pf_to_mgmt
);
649 dev_err(&pdev
->dev
, "Failed to allocate msg buffers\n");
650 hinic_health_reporters_destroy(hwdev
->devlink_dev
);
654 err
= hinic_api_cmd_init(pf_to_mgmt
->cmd_chain
, hwif
);
656 dev_err(&pdev
->dev
, "Failed to initialize cmd chains\n");
657 hinic_health_reporters_destroy(hwdev
->devlink_dev
);
661 hinic_aeq_register_hw_cb(&hwdev
->aeqs
, HINIC_MSG_FROM_MGMT_CPU
,
663 mgmt_msg_aeqe_handler
);
668 * hinic_pf_to_mgmt_free - free PF to MGMT channel
669 * @pf_to_mgmt: PF to MGMT channel
671 void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt
*pf_to_mgmt
)
673 struct hinic_pfhwdev
*pfhwdev
= mgmt_to_pfhwdev(pf_to_mgmt
);
674 struct hinic_hwdev
*hwdev
= &pfhwdev
->hwdev
;
676 if (HINIC_IS_VF(hwdev
->hwif
))
679 hinic_aeq_unregister_hw_cb(&hwdev
->aeqs
, HINIC_MSG_FROM_MGMT_CPU
);
680 hinic_api_cmd_free(pf_to_mgmt
->cmd_chain
);
681 destroy_workqueue(pf_to_mgmt
->workq
);
682 hinic_health_reporters_destroy(hwdev
->devlink_dev
);