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