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
59enum msg_segment_type {
60	NOT_LAST_SEGMENT = 0,
61	LAST_SEGMENT     = 1,
62};
63
64enum mgmt_direction_type {
65	MGMT_DIRECT_SEND = 0,
66	MGMT_RESP        = 1,
67};
68
69enum 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 **/
81void 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 **/
101void 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 **/
126static 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 **/
155static 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 **/
172static 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 **/
200static 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 * @timeout: time-out period of waiting for response
242 *
243 * Return 0 - Success, negative - Failure
244 **/
245static 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)
251{
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;
256	unsigned long timeo;
257	u16 msg_id;
258	int err;
259
260	/* Lock the sync_msg_buf */
261	down(&pf_to_mgmt->sync_msg_lock);
262
263	recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
264	recv_done = &recv_msg->recv_done;
265
266	if (resp_msg_id == MSG_NOT_RESP)
267		msg_id = SYNC_MSG_ID(pf_to_mgmt);
268	else
269		msg_id = resp_msg_id;
270
271	init_completion(recv_done);
272
273	err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
274			       MSG_ACK, direction, resp_msg_id);
275	if (err) {
276		dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n");
277		goto unlock_sync_msg;
278	}
279
280	timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
281
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);
285		err = -ETIMEDOUT;
286		goto unlock_sync_msg;
287	}
288
289	smp_rmb();      /* verify reading after completion */
290
291	if (recv_msg->msg_id != msg_id) {
292		dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);
293		err = -EFAULT;
294		goto unlock_sync_msg;
295	}
296
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;
300	}
301
302unlock_sync_msg:
303	up(&pf_to_mgmt->sync_msg_lock);
304	return err;
305}
306
307/**
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
316 *
317 * Return 0 - Success, negative - Failure
318 **/
319static 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,
323			     u16 resp_msg_id)
324{
325	int err;
326
327	/* Lock the sync_msg_buf */
328	down(&pf_to_mgmt->sync_msg_lock);
329
330	err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
331			       MSG_NO_ACK, direction, resp_msg_id);
332
333	up(&pf_to_mgmt->sync_msg_lock);
334	return err;
335}
336
337/**
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
344 * @buf_out: response
345 * @out_size: returned response length
346 * @sync: sync msg or async msg
347 *
348 * Return 0 - Success, negative - Failure
349 **/
350int 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)
354{
355	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
356	struct pci_dev *pdev = hwif->pdev;
357	u32 timeout = 0;
358
359	if (sync != HINIC_MGMT_MSG_SYNC) {
360		dev_err(&pdev->dev, "Invalid MGMT msg type\n");
361		return -EINVAL;
362	}
363
364	if (!MSG_SZ_IS_VALID(in_size)) {
365		dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");
366		return -EINVAL;
367	}
368
369	if (HINIC_IS_VF(hwif)) {
370		if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
371			timeout = SET_FUNC_PORT_MBOX_TIMEOUT;
372
373		return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,
374					in_size, buf_out, out_size, timeout);
375	} else {
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;
380
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);
384	}
385}
386
387static void recv_mgmt_msg_work_handler(struct work_struct *work)
388{
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;
396	u16 out_size = 0;
397
398	memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
399
400	if (mgmt_work->mod >= HINIC_MOD_MAX) {
401		dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
402			mgmt_work->mod);
403		kfree(mgmt_work->msg);
404		kfree(mgmt_work);
405		return;
406	}
407
408	mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
409
410	cb_state = cmpxchg(&mgmt_cb->state,
411			   HINIC_MGMT_CB_ENABLED,
412			   HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
413
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,
417			    buf_out, &out_size);
418	else
419		dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
420			mgmt_work->mod, mgmt_work->cmd);
421
422	mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
423
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,
428				  mgmt_work->msg_id);
429
430	kfree(mgmt_work->msg);
431	kfree(mgmt_work);
432}
433
434/**
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
438 **/
439static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
440				  struct hinic_recv_msg *recv_msg)
441{
442	struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
443
444	mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
445	if (!mgmt_work)
446		return;
447
448	if (recv_msg->msg_len) {
449		mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
450		if (!mgmt_work->msg) {
451			kfree(mgmt_work);
452			return;
453		}
454	}
455
456	mgmt_work->pf_to_mgmt = pf_to_mgmt;
457	mgmt_work->msg_len = recv_msg->msg_len;
458	memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
459	mgmt_work->msg_id = recv_msg->msg_id;
460	mgmt_work->mod = recv_msg->mod;
461	mgmt_work->cmd = recv_msg->cmd;
462	mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
463
464	INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
465	queue_work(pf_to_mgmt->workq, &mgmt_work->work);
466}
467
468/**
469 * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
470 * @pf_to_mgmt: PF to MGMT channel
471 * @recv_msg: received message details
472 **/
473static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
474				  struct hinic_recv_msg *recv_msg)
475{
476	wmb();  /* verify writing all, before reading */
477
478	complete(&recv_msg->recv_done);
479}
480
481/**
482 * recv_mgmt_msg_handler - handler for a message from mgmt cpu
483 * @pf_to_mgmt: PF to MGMT channel
484 * @header: the header of the message
485 * @recv_msg: received message details
486 **/
487static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
488				  u64 *header, struct hinic_recv_msg *recv_msg)
489{
490	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
491	struct pci_dev *pdev = hwif->pdev;
492	int seq_id, seg_len;
493	u8 *msg_body;
494
495	seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
496	seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
497
498	if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
499		dev_err(&pdev->dev, "recv big mgmt msg\n");
500		return;
501	}
502
503	msg_body = (u8 *)header + sizeof(*header);
504	memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
505
506	if (!HINIC_MSG_HEADER_GET(*header, LAST))
507		return;
508
509	recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
510	recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
511	recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
512							  ASYNC_MGMT_TO_PF);
513	recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
514	recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
515
516	if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
517		mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
518	else
519		mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
520}
521
522/**
523 * mgmt_msg_aeqe_handler - handler for a mgmt message event
524 * @handle: PF to MGMT channel
525 * @data: the header of the message
526 * @size: unused
527 **/
528static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
529{
530	struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
531	struct hinic_recv_msg *recv_msg;
532	u64 *header = (u64 *)data;
533
534	recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
535		   MGMT_DIRECT_SEND ?
536		   &pf_to_mgmt->recv_msg_from_mgmt :
537		   &pf_to_mgmt->recv_resp_msg_from_mgmt;
538
539	recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
540}
541
542/**
543 * alloc_recv_msg - allocate receive message memory
544 * @pf_to_mgmt: PF to MGMT channel
545 * @recv_msg: pointer that will hold the allocated data
546 *
547 * Return 0 - Success, negative - Failure
548 **/
549static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
550			  struct hinic_recv_msg *recv_msg)
551{
552	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
553	struct pci_dev *pdev = hwif->pdev;
554
555	recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
556				     GFP_KERNEL);
557	if (!recv_msg->msg)
558		return -ENOMEM;
559
560	recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
561					 GFP_KERNEL);
562	if (!recv_msg->buf_out)
563		return -ENOMEM;
564
565	return 0;
566}
567
568/**
569 * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
570 * @pf_to_mgmt: PF to MGMT channel
571 *
572 * Return 0 - Success, negative - Failure
573 **/
574static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
575{
576	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
577	struct pci_dev *pdev = hwif->pdev;
578	int err;
579
580	err = alloc_recv_msg(pf_to_mgmt,
581			     &pf_to_mgmt->recv_msg_from_mgmt);
582	if (err) {
583		dev_err(&pdev->dev, "Failed to allocate recv msg\n");
584		return err;
585	}
586
587	err = alloc_recv_msg(pf_to_mgmt,
588			     &pf_to_mgmt->recv_resp_msg_from_mgmt);
589	if (err) {
590		dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
591		return err;
592	}
593
594	pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
595						MAX_PF_MGMT_BUF_SIZE,
596						GFP_KERNEL);
597	if (!pf_to_mgmt->sync_msg_buf)
598		return -ENOMEM;
599
600	pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
601						MAX_PF_MGMT_BUF_SIZE,
602						GFP_KERNEL);
603	if (!pf_to_mgmt->mgmt_ack_buf)
604		return -ENOMEM;
605
606	return 0;
607}
608
609/**
610 * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
611 * @pf_to_mgmt: PF to MGMT channel
612 * @hwif: HW interface the PF to MGMT will use for accessing HW
613 *
614 * Return 0 - Success, negative - Failure
615 **/
616int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
617			  struct hinic_hwif *hwif)
618{
619	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
620	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
621	struct pci_dev *pdev = hwif->pdev;
622	int err;
623
624	pf_to_mgmt->hwif = hwif;
625	pf_to_mgmt->hwdev = hwdev;
626
627	if (HINIC_IS_VF(hwif))
628		return 0;
629
630	err = hinic_health_reporters_create(hwdev->devlink_dev);
631	if (err)
632		return err;
633
634	sema_init(&pf_to_mgmt->sync_msg_lock, 1);
635	pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
636	if (!pf_to_mgmt->workq) {
637		dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
638		hinic_health_reporters_destroy(hwdev->devlink_dev);
639		return -ENOMEM;
640	}
641	pf_to_mgmt->sync_msg_id = 0;
642
643	err = alloc_msg_buf(pf_to_mgmt);
644	if (err) {
645		dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
646		destroy_workqueue(pf_to_mgmt->workq);
647		hinic_health_reporters_destroy(hwdev->devlink_dev);
648		return err;
649	}
650
651	err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
652	if (err) {
653		dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
654		destroy_workqueue(pf_to_mgmt->workq);
655		hinic_health_reporters_destroy(hwdev->devlink_dev);
656		return err;
657	}
658
659	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
660				 pf_to_mgmt,
661				 mgmt_msg_aeqe_handler);
662	return 0;
663}
664
665/**
666 * hinic_pf_to_mgmt_free - free PF to MGMT channel
667 * @pf_to_mgmt: PF to MGMT channel
668 **/
669void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
670{
671	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
672	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
673
674	if (HINIC_IS_VF(hwdev->hwif))
675		return;
676
677	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
678	hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
679	destroy_workqueue(pf_to_mgmt->workq);
680	hinic_health_reporters_destroy(hwdev->devlink_dev);
681}
682