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 	if (HINIC_IS_VF(hwif))
365 		return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,
366 					in_size, buf_out, out_size, 0);
367 	else
368 		return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
369 				buf_out, out_size, MGMT_DIRECT_SEND,
370 				MSG_NOT_RESP, timeout);
371 }
372 
373 static void recv_mgmt_msg_work_handler(struct work_struct *work)
374 {
375 	struct hinic_mgmt_msg_handle_work *mgmt_work =
376 		container_of(work, struct hinic_mgmt_msg_handle_work, work);
377 	struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;
378 	struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
379 	u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;
380 	struct hinic_mgmt_cb *mgmt_cb;
381 	unsigned long cb_state;
382 	u16 out_size = 0;
383 
384 	memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
385 
386 	if (mgmt_work->mod >= HINIC_MOD_MAX) {
387 		dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
388 			mgmt_work->mod);
389 		kfree(mgmt_work->msg);
390 		kfree(mgmt_work);
391 		return;
392 	}
393 
394 	mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
395 
396 	cb_state = cmpxchg(&mgmt_cb->state,
397 			   HINIC_MGMT_CB_ENABLED,
398 			   HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
399 
400 	if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
401 		mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,
402 			    mgmt_work->msg, mgmt_work->msg_len,
403 			    buf_out, &out_size);
404 	else
405 		dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
406 			mgmt_work->mod, mgmt_work->cmd);
407 
408 	mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
409 
410 	if (!mgmt_work->async_mgmt_to_pf)
411 		/* MGMT sent sync msg, send the response */
412 		msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,
413 				  buf_out, out_size, MGMT_RESP,
414 				  mgmt_work->msg_id);
415 
416 	kfree(mgmt_work->msg);
417 	kfree(mgmt_work);
418 }
419 
420 /**
421  * mgmt_recv_msg_handler - handler for message from mgmt cpu
422  * @pf_to_mgmt: PF to MGMT channel
423  * @recv_msg: received message details
424  **/
425 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
426 				  struct hinic_recv_msg *recv_msg)
427 {
428 	struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
429 	struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
430 
431 	mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
432 	if (!mgmt_work) {
433 		dev_err(&pdev->dev, "Allocate mgmt work memory failed\n");
434 		return;
435 	}
436 
437 	if (recv_msg->msg_len) {
438 		mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
439 		if (!mgmt_work->msg) {
440 			dev_err(&pdev->dev, "Allocate mgmt msg memory failed\n");
441 			kfree(mgmt_work);
442 			return;
443 		}
444 	}
445 
446 	mgmt_work->pf_to_mgmt = pf_to_mgmt;
447 	mgmt_work->msg_len = recv_msg->msg_len;
448 	memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
449 	mgmt_work->msg_id = recv_msg->msg_id;
450 	mgmt_work->mod = recv_msg->mod;
451 	mgmt_work->cmd = recv_msg->cmd;
452 	mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
453 
454 	INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
455 	queue_work(pf_to_mgmt->workq, &mgmt_work->work);
456 }
457 
458 /**
459  * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
460  * @pf_to_mgmt: PF to MGMT channel
461  * @recv_msg: received message details
462  **/
463 static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
464 				  struct hinic_recv_msg *recv_msg)
465 {
466 	wmb();  /* verify writing all, before reading */
467 
468 	complete(&recv_msg->recv_done);
469 }
470 
471 /**
472  * recv_mgmt_msg_handler - handler for a message from mgmt cpu
473  * @pf_to_mgmt: PF to MGMT channel
474  * @header: the header of the message
475  * @recv_msg: received message details
476  **/
477 static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
478 				  u64 *header, struct hinic_recv_msg *recv_msg)
479 {
480 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
481 	struct pci_dev *pdev = hwif->pdev;
482 	int seq_id, seg_len;
483 	u8 *msg_body;
484 
485 	seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
486 	seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
487 
488 	if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
489 		dev_err(&pdev->dev, "recv big mgmt msg\n");
490 		return;
491 	}
492 
493 	msg_body = (u8 *)header + sizeof(*header);
494 	memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
495 
496 	if (!HINIC_MSG_HEADER_GET(*header, LAST))
497 		return;
498 
499 	recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
500 	recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
501 	recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
502 							  ASYNC_MGMT_TO_PF);
503 	recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
504 	recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
505 
506 	if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
507 		mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
508 	else
509 		mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
510 }
511 
512 /**
513  * mgmt_msg_aeqe_handler - handler for a mgmt message event
514  * @handle: PF to MGMT channel
515  * @data: the header of the message
516  * @size: unused
517  **/
518 static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
519 {
520 	struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
521 	struct hinic_recv_msg *recv_msg;
522 	u64 *header = (u64 *)data;
523 
524 	recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
525 		   MGMT_DIRECT_SEND ?
526 		   &pf_to_mgmt->recv_msg_from_mgmt :
527 		   &pf_to_mgmt->recv_resp_msg_from_mgmt;
528 
529 	recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
530 }
531 
532 /**
533  * alloc_recv_msg - allocate receive message memory
534  * @pf_to_mgmt: PF to MGMT channel
535  * @recv_msg: pointer that will hold the allocated data
536  *
537  * Return 0 - Success, negative - Failure
538  **/
539 static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
540 			  struct hinic_recv_msg *recv_msg)
541 {
542 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
543 	struct pci_dev *pdev = hwif->pdev;
544 
545 	recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
546 				     GFP_KERNEL);
547 	if (!recv_msg->msg)
548 		return -ENOMEM;
549 
550 	recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
551 					 GFP_KERNEL);
552 	if (!recv_msg->buf_out)
553 		return -ENOMEM;
554 
555 	return 0;
556 }
557 
558 /**
559  * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
560  * @pf_to_mgmt: PF to MGMT channel
561  *
562  * Return 0 - Success, negative - Failure
563  **/
564 static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
565 {
566 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
567 	struct pci_dev *pdev = hwif->pdev;
568 	int err;
569 
570 	err = alloc_recv_msg(pf_to_mgmt,
571 			     &pf_to_mgmt->recv_msg_from_mgmt);
572 	if (err) {
573 		dev_err(&pdev->dev, "Failed to allocate recv msg\n");
574 		return err;
575 	}
576 
577 	err = alloc_recv_msg(pf_to_mgmt,
578 			     &pf_to_mgmt->recv_resp_msg_from_mgmt);
579 	if (err) {
580 		dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
581 		return err;
582 	}
583 
584 	pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
585 						MAX_PF_MGMT_BUF_SIZE,
586 						GFP_KERNEL);
587 	if (!pf_to_mgmt->sync_msg_buf)
588 		return -ENOMEM;
589 
590 	pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
591 						MAX_PF_MGMT_BUF_SIZE,
592 						GFP_KERNEL);
593 	if (!pf_to_mgmt->mgmt_ack_buf)
594 		return -ENOMEM;
595 
596 	return 0;
597 }
598 
599 /**
600  * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
601  * @pf_to_mgmt: PF to MGMT channel
602  * @hwif: HW interface the PF to MGMT will use for accessing HW
603  *
604  * Return 0 - Success, negative - Failure
605  **/
606 int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
607 			  struct hinic_hwif *hwif)
608 {
609 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
610 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
611 	struct pci_dev *pdev = hwif->pdev;
612 	int err;
613 
614 	pf_to_mgmt->hwif = hwif;
615 	pf_to_mgmt->hwdev = hwdev;
616 
617 	if (HINIC_IS_VF(hwif))
618 		return 0;
619 
620 	sema_init(&pf_to_mgmt->sync_msg_lock, 1);
621 	pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
622 	if (!pf_to_mgmt->workq) {
623 		dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
624 		return -ENOMEM;
625 	}
626 	pf_to_mgmt->sync_msg_id = 0;
627 
628 	err = alloc_msg_buf(pf_to_mgmt);
629 	if (err) {
630 		dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
631 		return err;
632 	}
633 
634 	err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
635 	if (err) {
636 		dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
637 		return err;
638 	}
639 
640 	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
641 				 pf_to_mgmt,
642 				 mgmt_msg_aeqe_handler);
643 	return 0;
644 }
645 
646 /**
647  * hinic_pf_to_mgmt_free - free PF to MGMT channel
648  * @pf_to_mgmt: PF to MGMT channel
649  **/
650 void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
651 {
652 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
653 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
654 
655 	if (HINIC_IS_VF(hwdev->hwif))
656 		return;
657 
658 	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
659 	hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
660 	destroy_workqueue(pf_to_mgmt->workq);
661 }
662