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