12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a5564e7eSAviad Krawczyk /*
3a5564e7eSAviad Krawczyk  * Huawei HiNIC PCI Express Linux driver
4a5564e7eSAviad Krawczyk  * Copyright(c) 2017 Huawei Technologies Co., Ltd
5a5564e7eSAviad Krawczyk  */
6a5564e7eSAviad Krawczyk 
7a5564e7eSAviad Krawczyk #include <linux/kernel.h>
8a5564e7eSAviad Krawczyk #include <linux/types.h>
9a5564e7eSAviad Krawczyk #include <linux/errno.h>
106dd8b682SAviad Krawczyk #include <linux/pci.h>
116dd8b682SAviad Krawczyk #include <linux/device.h>
126dd8b682SAviad Krawczyk #include <linux/semaphore.h>
136dd8b682SAviad Krawczyk #include <linux/completion.h>
146dd8b682SAviad Krawczyk #include <linux/slab.h>
15c15850c7SLuo bin #include <net/devlink.h>
166dd8b682SAviad Krawczyk #include <asm/barrier.h>
17a5564e7eSAviad Krawczyk 
18c15850c7SLuo bin #include "hinic_devlink.h"
19a5564e7eSAviad Krawczyk #include "hinic_hw_if.h"
20a5564e7eSAviad Krawczyk #include "hinic_hw_eqs.h"
21eabf0fadSAviad Krawczyk #include "hinic_hw_api_cmd.h"
22a5564e7eSAviad Krawczyk #include "hinic_hw_mgmt.h"
23a5564e7eSAviad Krawczyk #include "hinic_hw_dev.h"
24a5564e7eSAviad Krawczyk 
256dd8b682SAviad Krawczyk #define SYNC_MSG_ID_MASK                0x1FF
266dd8b682SAviad Krawczyk 
276dd8b682SAviad Krawczyk #define SYNC_MSG_ID(pf_to_mgmt)         ((pf_to_mgmt)->sync_msg_id)
286dd8b682SAviad Krawczyk 
296dd8b682SAviad Krawczyk #define SYNC_MSG_ID_INC(pf_to_mgmt)     (SYNC_MSG_ID(pf_to_mgmt) = \
306dd8b682SAviad Krawczyk 					((SYNC_MSG_ID(pf_to_mgmt) + 1) & \
316dd8b682SAviad Krawczyk 					 SYNC_MSG_ID_MASK))
326dd8b682SAviad Krawczyk 
336dd8b682SAviad Krawczyk #define MSG_SZ_IS_VALID(in_size)        ((in_size) <= MAX_MSG_LEN)
346dd8b682SAviad Krawczyk 
356dd8b682SAviad Krawczyk #define MGMT_MSG_LEN_MIN                20
366dd8b682SAviad Krawczyk #define MGMT_MSG_LEN_STEP               16
376dd8b682SAviad Krawczyk #define MGMT_MSG_RSVD_FOR_DEV           8
386dd8b682SAviad Krawczyk 
396dd8b682SAviad Krawczyk #define SEGMENT_LEN                     48
406dd8b682SAviad Krawczyk 
416dd8b682SAviad Krawczyk #define MAX_PF_MGMT_BUF_SIZE            2048
426dd8b682SAviad Krawczyk 
436dd8b682SAviad Krawczyk /* Data should be SEG LEN size aligned */
446dd8b682SAviad Krawczyk #define MAX_MSG_LEN                     2016
456dd8b682SAviad Krawczyk 
466dd8b682SAviad Krawczyk #define MSG_NOT_RESP                    0xFFFF
476dd8b682SAviad Krawczyk 
480da7c322SLuo bin #define MGMT_MSG_TIMEOUT                5000
496dd8b682SAviad Krawczyk 
504e4269ebSLuo bin #define SET_FUNC_PORT_MBOX_TIMEOUT	30000
514e4269ebSLuo bin 
52e8a1b0efSLuo bin #define SET_FUNC_PORT_MGMT_TIMEOUT	25000
53e8a1b0efSLuo bin 
540c97ee5fSLuo bin #define UPDATE_FW_MGMT_TIMEOUT		20000
550c97ee5fSLuo bin 
56a5564e7eSAviad Krawczyk #define mgmt_to_pfhwdev(pf_mgmt)        \
57a5564e7eSAviad Krawczyk 		container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
58a5564e7eSAviad Krawczyk 
596dd8b682SAviad Krawczyk enum msg_segment_type {
606dd8b682SAviad Krawczyk 	NOT_LAST_SEGMENT = 0,
616dd8b682SAviad Krawczyk 	LAST_SEGMENT     = 1,
626dd8b682SAviad Krawczyk };
636dd8b682SAviad Krawczyk 
646dd8b682SAviad Krawczyk enum mgmt_direction_type {
656dd8b682SAviad Krawczyk 	MGMT_DIRECT_SEND = 0,
666dd8b682SAviad Krawczyk 	MGMT_RESP        = 1,
676dd8b682SAviad Krawczyk };
686dd8b682SAviad Krawczyk 
696dd8b682SAviad Krawczyk enum msg_ack_type {
706dd8b682SAviad Krawczyk 	MSG_ACK         = 0,
716dd8b682SAviad Krawczyk 	MSG_NO_ACK      = 1,
726dd8b682SAviad Krawczyk };
736dd8b682SAviad Krawczyk 
746dd8b682SAviad Krawczyk /**
75c4d06d2dSAviad Krawczyk  * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module
76c4d06d2dSAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
77c4d06d2dSAviad Krawczyk  * @mod: module in the chip that this handler will handle its messages
78c4d06d2dSAviad Krawczyk  * @handle: private data for the callback
79c4d06d2dSAviad Krawczyk  * @callback: the handler that will handle messages
80c4d06d2dSAviad Krawczyk  **/
hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,void * handle,void (* callback)(void * handle,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size))81c4d06d2dSAviad Krawczyk void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
82c4d06d2dSAviad Krawczyk 				enum hinic_mod_type mod,
83c4d06d2dSAviad Krawczyk 				void *handle,
84c4d06d2dSAviad Krawczyk 				void (*callback)(void *handle,
85c4d06d2dSAviad Krawczyk 						 u8 cmd, void *buf_in,
86c4d06d2dSAviad Krawczyk 						 u16 in_size, void *buf_out,
87c4d06d2dSAviad Krawczyk 						 u16 *out_size))
88c4d06d2dSAviad Krawczyk {
89c4d06d2dSAviad Krawczyk 	struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];
90c4d06d2dSAviad Krawczyk 
91c4d06d2dSAviad Krawczyk 	mgmt_cb->cb = callback;
92c4d06d2dSAviad Krawczyk 	mgmt_cb->handle = handle;
93c4d06d2dSAviad Krawczyk 	mgmt_cb->state = HINIC_MGMT_CB_ENABLED;
94c4d06d2dSAviad Krawczyk }
95c4d06d2dSAviad Krawczyk 
96c4d06d2dSAviad Krawczyk /**
97c4d06d2dSAviad Krawczyk  * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module
98c4d06d2dSAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
99c4d06d2dSAviad Krawczyk  * @mod: module in the chip that this handler handles its messages
100c4d06d2dSAviad Krawczyk  **/
hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod)101c4d06d2dSAviad Krawczyk void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,
102c4d06d2dSAviad Krawczyk 				  enum hinic_mod_type mod)
103c4d06d2dSAviad Krawczyk {
104c4d06d2dSAviad Krawczyk 	struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod];
105c4d06d2dSAviad Krawczyk 
106c4d06d2dSAviad Krawczyk 	mgmt_cb->state &= ~HINIC_MGMT_CB_ENABLED;
107c4d06d2dSAviad Krawczyk 
108c4d06d2dSAviad Krawczyk 	while (mgmt_cb->state & HINIC_MGMT_CB_RUNNING)
109c4d06d2dSAviad Krawczyk 		schedule();
110c4d06d2dSAviad Krawczyk 
111c4d06d2dSAviad Krawczyk 	mgmt_cb->cb = NULL;
112c4d06d2dSAviad Krawczyk }
113c4d06d2dSAviad Krawczyk 
114c4d06d2dSAviad Krawczyk /**
1156dd8b682SAviad Krawczyk  * prepare_header - prepare the header of the message
1166dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
1176dd8b682SAviad Krawczyk  * @msg_len: the length of the message
1186dd8b682SAviad Krawczyk  * @mod: module in the chip that will get the message
1196dd8b682SAviad Krawczyk  * @ack_type: ask for response
1206dd8b682SAviad Krawczyk  * @direction: the direction of the message
1216dd8b682SAviad Krawczyk  * @cmd: command of the message
1226dd8b682SAviad Krawczyk  * @msg_id: message id
1236dd8b682SAviad Krawczyk  *
1246dd8b682SAviad Krawczyk  * Return the prepared header value
1256dd8b682SAviad Krawczyk  **/
prepare_header(struct hinic_pf_to_mgmt * pf_to_mgmt,u16 msg_len,enum hinic_mod_type mod,enum msg_ack_type ack_type,enum mgmt_direction_type direction,u16 cmd,u16 msg_id)1266dd8b682SAviad Krawczyk static u64 prepare_header(struct hinic_pf_to_mgmt *pf_to_mgmt,
1276dd8b682SAviad Krawczyk 			  u16 msg_len, enum hinic_mod_type mod,
1286dd8b682SAviad Krawczyk 			  enum msg_ack_type ack_type,
1296dd8b682SAviad Krawczyk 			  enum mgmt_direction_type direction,
1306dd8b682SAviad Krawczyk 			  u16 cmd, u16 msg_id)
1316dd8b682SAviad Krawczyk {
1326dd8b682SAviad Krawczyk 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
1336dd8b682SAviad Krawczyk 
1346dd8b682SAviad Krawczyk 	return HINIC_MSG_HEADER_SET(msg_len, MSG_LEN)           |
1356dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(mod, MODULE)                |
1366dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(SEGMENT_LEN, SEG_LEN)       |
1376dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(ack_type, NO_ACK)           |
1386dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF)        |
1396dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(0, SEQID)                   |
1406dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST)         |
1416dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(direction, DIRECTION)       |
1426dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(cmd, CMD)                   |
1436dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(HINIC_HWIF_PCI_INTF(hwif), PCI_INTF) |
1446dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(HINIC_HWIF_PF_IDX(hwif), PF_IDX)     |
1456dd8b682SAviad Krawczyk 	       HINIC_MSG_HEADER_SET(msg_id, MSG_ID);
1466dd8b682SAviad Krawczyk }
1476dd8b682SAviad Krawczyk 
1486dd8b682SAviad Krawczyk /**
1496dd8b682SAviad Krawczyk  * prepare_mgmt_cmd - prepare the mgmt command
1506dd8b682SAviad Krawczyk  * @mgmt_cmd: pointer to the command to prepare
1516dd8b682SAviad Krawczyk  * @header: pointer of the header for the message
1526dd8b682SAviad Krawczyk  * @msg: the data of the message
1536dd8b682SAviad Krawczyk  * @msg_len: the length of the message
1546dd8b682SAviad Krawczyk  **/
prepare_mgmt_cmd(u8 * mgmt_cmd,u64 * header,u8 * msg,u16 msg_len)1556dd8b682SAviad Krawczyk static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, u8 *msg, u16 msg_len)
1566dd8b682SAviad Krawczyk {
1576dd8b682SAviad Krawczyk 	memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
1586dd8b682SAviad Krawczyk 
1596dd8b682SAviad Krawczyk 	mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;
1606dd8b682SAviad Krawczyk 	memcpy(mgmt_cmd, header, sizeof(*header));
1616dd8b682SAviad Krawczyk 
1626dd8b682SAviad Krawczyk 	mgmt_cmd += sizeof(*header);
1636dd8b682SAviad Krawczyk 	memcpy(mgmt_cmd, msg, msg_len);
1646dd8b682SAviad Krawczyk }
1656dd8b682SAviad Krawczyk 
1666dd8b682SAviad Krawczyk /**
1676dd8b682SAviad Krawczyk  * mgmt_msg_len - calculate the total message length
1686dd8b682SAviad Krawczyk  * @msg_data_len: the length of the message data
1696dd8b682SAviad Krawczyk  *
1706dd8b682SAviad Krawczyk  * Return the total message length
1716dd8b682SAviad Krawczyk  **/
mgmt_msg_len(u16 msg_data_len)1726dd8b682SAviad Krawczyk static u16 mgmt_msg_len(u16 msg_data_len)
1736dd8b682SAviad Krawczyk {
1746dd8b682SAviad Krawczyk 	/* RSVD + HEADER_SIZE + DATA_LEN */
1756dd8b682SAviad Krawczyk 	u16 msg_len = MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len;
1766dd8b682SAviad Krawczyk 
1776dd8b682SAviad Krawczyk 	if (msg_len > MGMT_MSG_LEN_MIN)
1786dd8b682SAviad Krawczyk 		msg_len = MGMT_MSG_LEN_MIN +
1796dd8b682SAviad Krawczyk 			   ALIGN((msg_len - MGMT_MSG_LEN_MIN),
1806dd8b682SAviad Krawczyk 				 MGMT_MSG_LEN_STEP);
1816dd8b682SAviad Krawczyk 	else
1826dd8b682SAviad Krawczyk 		msg_len = MGMT_MSG_LEN_MIN;
1836dd8b682SAviad Krawczyk 
1846dd8b682SAviad Krawczyk 	return msg_len;
1856dd8b682SAviad Krawczyk }
1866dd8b682SAviad Krawczyk 
1876dd8b682SAviad Krawczyk /**
1886dd8b682SAviad Krawczyk  * send_msg_to_mgmt - send message to mgmt by API CMD
1896dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
1906dd8b682SAviad Krawczyk  * @mod: module in the chip that will get the message
1916dd8b682SAviad Krawczyk  * @cmd: command of the message
1926dd8b682SAviad Krawczyk  * @data: the msg data
1936dd8b682SAviad Krawczyk  * @data_len: the msg data length
1946dd8b682SAviad Krawczyk  * @ack_type: ask for response
1956dd8b682SAviad Krawczyk  * @direction: the direction of the original message
1966dd8b682SAviad Krawczyk  * @resp_msg_id: msg id to response for
1976dd8b682SAviad Krawczyk  *
1986dd8b682SAviad Krawczyk  * Return 0 - Success, negative - Failure
1996dd8b682SAviad Krawczyk  **/
send_msg_to_mgmt(struct hinic_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,u8 cmd,u8 * data,u16 data_len,enum msg_ack_type ack_type,enum mgmt_direction_type direction,u16 resp_msg_id)2006dd8b682SAviad Krawczyk static int send_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
2016dd8b682SAviad Krawczyk 			    enum hinic_mod_type mod, u8 cmd,
2026dd8b682SAviad Krawczyk 			    u8 *data, u16 data_len,
2036dd8b682SAviad Krawczyk 			    enum msg_ack_type ack_type,
2046dd8b682SAviad Krawczyk 			    enum mgmt_direction_type direction,
2056dd8b682SAviad Krawczyk 			    u16 resp_msg_id)
2066dd8b682SAviad Krawczyk {
2076dd8b682SAviad Krawczyk 	struct hinic_api_cmd_chain *chain;
2086dd8b682SAviad Krawczyk 	u64 header;
2096dd8b682SAviad Krawczyk 	u16 msg_id;
2106dd8b682SAviad Krawczyk 
2116dd8b682SAviad Krawczyk 	msg_id = SYNC_MSG_ID(pf_to_mgmt);
2126dd8b682SAviad Krawczyk 
2136dd8b682SAviad Krawczyk 	if (direction == MGMT_RESP) {
2146dd8b682SAviad Krawczyk 		header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,
2156dd8b682SAviad Krawczyk 					direction, cmd, resp_msg_id);
2166dd8b682SAviad Krawczyk 	} else {
2176dd8b682SAviad Krawczyk 		SYNC_MSG_ID_INC(pf_to_mgmt);
2186dd8b682SAviad Krawczyk 		header = prepare_header(pf_to_mgmt, data_len, mod, ack_type,
2196dd8b682SAviad Krawczyk 					direction, cmd, msg_id);
2206dd8b682SAviad Krawczyk 	}
2216dd8b682SAviad Krawczyk 
2226dd8b682SAviad Krawczyk 	prepare_mgmt_cmd(pf_to_mgmt->sync_msg_buf, &header, data, data_len);
2236dd8b682SAviad Krawczyk 
2246dd8b682SAviad Krawczyk 	chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_TO_MGMT_CPU];
2256dd8b682SAviad Krawczyk 	return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT,
2266dd8b682SAviad Krawczyk 				   pf_to_mgmt->sync_msg_buf,
2276dd8b682SAviad Krawczyk 				   mgmt_msg_len(data_len));
2286dd8b682SAviad Krawczyk }
2296dd8b682SAviad Krawczyk 
2306dd8b682SAviad Krawczyk /**
2316dd8b682SAviad Krawczyk  * msg_to_mgmt_sync - send sync message to mgmt
2326dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
2336dd8b682SAviad Krawczyk  * @mod: module in the chip that will get the message
2346dd8b682SAviad Krawczyk  * @cmd: command of the message
2356dd8b682SAviad Krawczyk  * @buf_in: the msg data
2366dd8b682SAviad Krawczyk  * @in_size: the msg data length
2376dd8b682SAviad Krawczyk  * @buf_out: response
2386dd8b682SAviad Krawczyk  * @out_size: response length
2396dd8b682SAviad Krawczyk  * @direction: the direction of the original message
2406dd8b682SAviad Krawczyk  * @resp_msg_id: msg id to response for
241b1b6c110SLuo bin  * @timeout: time-out period of waiting for response
2426dd8b682SAviad Krawczyk  *
2436dd8b682SAviad Krawczyk  * Return 0 - Success, negative - Failure
2446dd8b682SAviad Krawczyk  **/
msg_to_mgmt_sync(struct hinic_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,u8 cmd,u8 * buf_in,u16 in_size,u8 * buf_out,u16 * out_size,enum mgmt_direction_type direction,u16 resp_msg_id,u32 timeout)2456dd8b682SAviad Krawczyk static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
2466dd8b682SAviad Krawczyk 			    enum hinic_mod_type mod, u8 cmd,
2476dd8b682SAviad Krawczyk 			    u8 *buf_in, u16 in_size,
2486dd8b682SAviad Krawczyk 			    u8 *buf_out, u16 *out_size,
2496dd8b682SAviad Krawczyk 			    enum mgmt_direction_type direction,
250e8a1b0efSLuo bin 			    u16 resp_msg_id, u32 timeout)
2516dd8b682SAviad Krawczyk {
2526dd8b682SAviad Krawczyk 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
2536dd8b682SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
2546dd8b682SAviad Krawczyk 	struct hinic_recv_msg *recv_msg;
2556dd8b682SAviad Krawczyk 	struct completion *recv_done;
256e8a1b0efSLuo bin 	unsigned long timeo;
2576dd8b682SAviad Krawczyk 	u16 msg_id;
2586dd8b682SAviad Krawczyk 	int err;
2596dd8b682SAviad Krawczyk 
2606dd8b682SAviad Krawczyk 	/* Lock the sync_msg_buf */
2616dd8b682SAviad Krawczyk 	down(&pf_to_mgmt->sync_msg_lock);
2626dd8b682SAviad Krawczyk 
2636dd8b682SAviad Krawczyk 	recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
2646dd8b682SAviad Krawczyk 	recv_done = &recv_msg->recv_done;
2656dd8b682SAviad Krawczyk 
2666dd8b682SAviad Krawczyk 	if (resp_msg_id == MSG_NOT_RESP)
2676dd8b682SAviad Krawczyk 		msg_id = SYNC_MSG_ID(pf_to_mgmt);
2686dd8b682SAviad Krawczyk 	else
2696dd8b682SAviad Krawczyk 		msg_id = resp_msg_id;
2706dd8b682SAviad Krawczyk 
2716dd8b682SAviad Krawczyk 	init_completion(recv_done);
2726dd8b682SAviad Krawczyk 
2736dd8b682SAviad Krawczyk 	err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
2746dd8b682SAviad Krawczyk 			       MSG_ACK, direction, resp_msg_id);
2756dd8b682SAviad Krawczyk 	if (err) {
2766dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n");
2776dd8b682SAviad Krawczyk 		goto unlock_sync_msg;
2786dd8b682SAviad Krawczyk 	}
2796dd8b682SAviad Krawczyk 
280e8a1b0efSLuo bin 	timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
281e8a1b0efSLuo bin 
282e8a1b0efSLuo bin 	if (!wait_for_completion_timeout(recv_done, timeo)) {
2836dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
28490f86b8aSLuo bin 		hinic_dump_aeq_info(pf_to_mgmt->hwdev);
2856dd8b682SAviad Krawczyk 		err = -ETIMEDOUT;
2866dd8b682SAviad Krawczyk 		goto unlock_sync_msg;
2876dd8b682SAviad Krawczyk 	}
2886dd8b682SAviad Krawczyk 
2896dd8b682SAviad Krawczyk 	smp_rmb();      /* verify reading after completion */
2906dd8b682SAviad Krawczyk 
2916dd8b682SAviad Krawczyk 	if (recv_msg->msg_id != msg_id) {
2926dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);
2936dd8b682SAviad Krawczyk 		err = -EFAULT;
2946dd8b682SAviad Krawczyk 		goto unlock_sync_msg;
2956dd8b682SAviad Krawczyk 	}
2966dd8b682SAviad Krawczyk 
297c8ad5df6SGuangbin Huang 	if (buf_out && recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE) {
2986dd8b682SAviad Krawczyk 		memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);
2996dd8b682SAviad Krawczyk 		*out_size = recv_msg->msg_len;
3006dd8b682SAviad Krawczyk 	}
3016dd8b682SAviad Krawczyk 
3026dd8b682SAviad Krawczyk unlock_sync_msg:
3036dd8b682SAviad Krawczyk 	up(&pf_to_mgmt->sync_msg_lock);
3046dd8b682SAviad Krawczyk 	return err;
3056dd8b682SAviad Krawczyk }
3066dd8b682SAviad Krawczyk 
3076dd8b682SAviad Krawczyk /**
3086dd8b682SAviad Krawczyk  * msg_to_mgmt_async - send message to mgmt without response
3096dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
3106dd8b682SAviad Krawczyk  * @mod: module in the chip that will get the message
3116dd8b682SAviad Krawczyk  * @cmd: command of the message
3126dd8b682SAviad Krawczyk  * @buf_in: the msg data
3136dd8b682SAviad Krawczyk  * @in_size: the msg data length
3146dd8b682SAviad Krawczyk  * @direction: the direction of the original message
3156dd8b682SAviad Krawczyk  * @resp_msg_id: msg id to response for
3166dd8b682SAviad Krawczyk  *
3176dd8b682SAviad Krawczyk  * Return 0 - Success, negative - Failure
3186dd8b682SAviad Krawczyk  **/
msg_to_mgmt_async(struct hinic_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,u8 cmd,u8 * buf_in,u16 in_size,enum mgmt_direction_type direction,u16 resp_msg_id)3196dd8b682SAviad Krawczyk static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt,
3206dd8b682SAviad Krawczyk 			     enum hinic_mod_type mod, u8 cmd,
3216dd8b682SAviad Krawczyk 			     u8 *buf_in, u16 in_size,
3226dd8b682SAviad Krawczyk 			     enum mgmt_direction_type direction,
3236dd8b682SAviad Krawczyk 			     u16 resp_msg_id)
3246dd8b682SAviad Krawczyk {
3256dd8b682SAviad Krawczyk 	int err;
3266dd8b682SAviad Krawczyk 
3276dd8b682SAviad Krawczyk 	/* Lock the sync_msg_buf */
3286dd8b682SAviad Krawczyk 	down(&pf_to_mgmt->sync_msg_lock);
3296dd8b682SAviad Krawczyk 
3306dd8b682SAviad Krawczyk 	err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
3316dd8b682SAviad Krawczyk 			       MSG_NO_ACK, direction, resp_msg_id);
3326dd8b682SAviad Krawczyk 
3336dd8b682SAviad Krawczyk 	up(&pf_to_mgmt->sync_msg_lock);
3346dd8b682SAviad Krawczyk 	return err;
3356dd8b682SAviad Krawczyk }
3366dd8b682SAviad Krawczyk 
337a5564e7eSAviad Krawczyk /**
338a5564e7eSAviad Krawczyk  * hinic_msg_to_mgmt - send message to mgmt
339a5564e7eSAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
340a5564e7eSAviad Krawczyk  * @mod: module in the chip that will get the message
341a5564e7eSAviad Krawczyk  * @cmd: command of the message
342a5564e7eSAviad Krawczyk  * @buf_in: the msg data
343a5564e7eSAviad Krawczyk  * @in_size: the msg data length
344a5564e7eSAviad Krawczyk  * @buf_out: response
345a5564e7eSAviad Krawczyk  * @out_size: returned response length
346a5564e7eSAviad Krawczyk  * @sync: sync msg or async msg
347a5564e7eSAviad Krawczyk  *
348a5564e7eSAviad Krawczyk  * Return 0 - Success, negative - Failure
349a5564e7eSAviad Krawczyk  **/
hinic_msg_to_mgmt(struct hinic_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size,enum hinic_mgmt_msg_type sync)350a5564e7eSAviad Krawczyk int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
351a5564e7eSAviad Krawczyk 		      enum hinic_mod_type mod, u8 cmd,
352a5564e7eSAviad Krawczyk 		      void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
353a5564e7eSAviad Krawczyk 		      enum hinic_mgmt_msg_type sync)
354a5564e7eSAviad Krawczyk {
3556dd8b682SAviad Krawczyk 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
3566dd8b682SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
357e8a1b0efSLuo bin 	u32 timeout = 0;
3586dd8b682SAviad Krawczyk 
3596dd8b682SAviad Krawczyk 	if (sync != HINIC_MGMT_MSG_SYNC) {
3606dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "Invalid MGMT msg type\n");
361a5564e7eSAviad Krawczyk 		return -EINVAL;
362a5564e7eSAviad Krawczyk 	}
363a5564e7eSAviad Krawczyk 
3646dd8b682SAviad Krawczyk 	if (!MSG_SZ_IS_VALID(in_size)) {
3656dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");
3666dd8b682SAviad Krawczyk 		return -EINVAL;
3676dd8b682SAviad Krawczyk 	}
3686dd8b682SAviad Krawczyk 
3694e4269ebSLuo bin 	if (HINIC_IS_VF(hwif)) {
3704e4269ebSLuo bin 		if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
3714e4269ebSLuo bin 			timeout = SET_FUNC_PORT_MBOX_TIMEOUT;
3724e4269ebSLuo bin 
3734e4269ebSLuo bin 		return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,
3744e4269ebSLuo bin 					in_size, buf_out, out_size, timeout);
3754e4269ebSLuo bin 	} else {
376e8a1b0efSLuo bin 		if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
377e8a1b0efSLuo bin 			timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
3780c97ee5fSLuo bin 		else if (cmd == HINIC_PORT_CMD_UPDATE_FW)
3790c97ee5fSLuo bin 			timeout = UPDATE_FW_MGMT_TIMEOUT;
380e8a1b0efSLuo bin 
3816dd8b682SAviad Krawczyk 		return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
3826dd8b682SAviad Krawczyk 				buf_out, out_size, MGMT_DIRECT_SEND,
383e8a1b0efSLuo bin 				MSG_NOT_RESP, timeout);
3846dd8b682SAviad Krawczyk 	}
3854e4269ebSLuo bin }
3866dd8b682SAviad Krawczyk 
recv_mgmt_msg_work_handler(struct work_struct * work)3876dbb8901SLuo bin static void recv_mgmt_msg_work_handler(struct work_struct *work)
3886dbb8901SLuo bin {
3896dbb8901SLuo bin 	struct hinic_mgmt_msg_handle_work *mgmt_work =
3906dbb8901SLuo bin 		container_of(work, struct hinic_mgmt_msg_handle_work, work);
3916dbb8901SLuo bin 	struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;
3926dbb8901SLuo bin 	struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
3936dbb8901SLuo bin 	u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;
3946dbb8901SLuo bin 	struct hinic_mgmt_cb *mgmt_cb;
3956dbb8901SLuo bin 	unsigned long cb_state;
3966dbb8901SLuo bin 	u16 out_size = 0;
3976dbb8901SLuo bin 
3986dbb8901SLuo bin 	memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
3996dbb8901SLuo bin 
4006dbb8901SLuo bin 	if (mgmt_work->mod >= HINIC_MOD_MAX) {
4016dbb8901SLuo bin 		dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
4026dbb8901SLuo bin 			mgmt_work->mod);
4036dbb8901SLuo bin 		kfree(mgmt_work->msg);
4046dbb8901SLuo bin 		kfree(mgmt_work);
4056dbb8901SLuo bin 		return;
4066dbb8901SLuo bin 	}
4076dbb8901SLuo bin 
4086dbb8901SLuo bin 	mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
4096dbb8901SLuo bin 
4106dbb8901SLuo bin 	cb_state = cmpxchg(&mgmt_cb->state,
4116dbb8901SLuo bin 			   HINIC_MGMT_CB_ENABLED,
4126dbb8901SLuo bin 			   HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
4136dbb8901SLuo bin 
414c8ad5df6SGuangbin Huang 	if (cb_state == HINIC_MGMT_CB_ENABLED && mgmt_cb->cb)
4156dbb8901SLuo bin 		mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,
4166dbb8901SLuo bin 			    mgmt_work->msg, mgmt_work->msg_len,
4176dbb8901SLuo bin 			    buf_out, &out_size);
4186dbb8901SLuo bin 	else
4196dbb8901SLuo bin 		dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
4206dbb8901SLuo bin 			mgmt_work->mod, mgmt_work->cmd);
4216dbb8901SLuo bin 
4226dbb8901SLuo bin 	mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
4236dbb8901SLuo bin 
4246dbb8901SLuo bin 	if (!mgmt_work->async_mgmt_to_pf)
4256dbb8901SLuo bin 		/* MGMT sent sync msg, send the response */
4266dbb8901SLuo bin 		msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,
4276dbb8901SLuo bin 				  buf_out, out_size, MGMT_RESP,
4286dbb8901SLuo bin 				  mgmt_work->msg_id);
4296dbb8901SLuo bin 
4306dbb8901SLuo bin 	kfree(mgmt_work->msg);
4316dbb8901SLuo bin 	kfree(mgmt_work);
4326dbb8901SLuo bin }
4336dbb8901SLuo bin 
4346dd8b682SAviad Krawczyk /**
4356dd8b682SAviad Krawczyk  * mgmt_recv_msg_handler - handler for message from mgmt cpu
4366dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
4376dd8b682SAviad Krawczyk  * @recv_msg: received message details
4386dd8b682SAviad Krawczyk  **/
mgmt_recv_msg_handler(struct hinic_pf_to_mgmt * pf_to_mgmt,struct hinic_recv_msg * recv_msg)4396dd8b682SAviad Krawczyk static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
4406dd8b682SAviad Krawczyk 				  struct hinic_recv_msg *recv_msg)
4416dd8b682SAviad Krawczyk {
4426dbb8901SLuo bin 	struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
4436dd8b682SAviad Krawczyk 
4446dbb8901SLuo bin 	mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
445c199fdb8SDaode Huang 	if (!mgmt_work)
446c4d06d2dSAviad Krawczyk 		return;
447c4d06d2dSAviad Krawczyk 
4486dbb8901SLuo bin 	if (recv_msg->msg_len) {
4496dbb8901SLuo bin 		mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
4506dbb8901SLuo bin 		if (!mgmt_work->msg) {
4516dbb8901SLuo bin 			kfree(mgmt_work);
4526dbb8901SLuo bin 			return;
4536dbb8901SLuo bin 		}
4546dbb8901SLuo bin 	}
455c4d06d2dSAviad Krawczyk 
4566dbb8901SLuo bin 	mgmt_work->pf_to_mgmt = pf_to_mgmt;
4576dbb8901SLuo bin 	mgmt_work->msg_len = recv_msg->msg_len;
4586dbb8901SLuo bin 	memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
4596dbb8901SLuo bin 	mgmt_work->msg_id = recv_msg->msg_id;
4606dbb8901SLuo bin 	mgmt_work->mod = recv_msg->mod;
4616dbb8901SLuo bin 	mgmt_work->cmd = recv_msg->cmd;
4626dbb8901SLuo bin 	mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
463c4d06d2dSAviad Krawczyk 
4646dbb8901SLuo bin 	INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
4656dbb8901SLuo bin 	queue_work(pf_to_mgmt->workq, &mgmt_work->work);
4666dd8b682SAviad Krawczyk }
4676dd8b682SAviad Krawczyk 
4686dd8b682SAviad Krawczyk /**
4696dd8b682SAviad Krawczyk  * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
4706dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
4716dd8b682SAviad Krawczyk  * @recv_msg: received message details
4726dd8b682SAviad Krawczyk  **/
mgmt_resp_msg_handler(struct hinic_pf_to_mgmt * pf_to_mgmt,struct hinic_recv_msg * recv_msg)4736dd8b682SAviad Krawczyk static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
4746dd8b682SAviad Krawczyk 				  struct hinic_recv_msg *recv_msg)
4756dd8b682SAviad Krawczyk {
4766dd8b682SAviad Krawczyk 	wmb();  /* verify writing all, before reading */
4776dd8b682SAviad Krawczyk 
4786dd8b682SAviad Krawczyk 	complete(&recv_msg->recv_done);
4796dd8b682SAviad Krawczyk }
4806dd8b682SAviad Krawczyk 
4816dd8b682SAviad Krawczyk /**
4826dd8b682SAviad Krawczyk  * recv_mgmt_msg_handler - handler for a message from mgmt cpu
4836dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
4846dd8b682SAviad Krawczyk  * @header: the header of the message
4856dd8b682SAviad Krawczyk  * @recv_msg: received message details
4866dd8b682SAviad Krawczyk  **/
recv_mgmt_msg_handler(struct hinic_pf_to_mgmt * pf_to_mgmt,u64 * header,struct hinic_recv_msg * recv_msg)4876dd8b682SAviad Krawczyk static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
4886dd8b682SAviad Krawczyk 				  u64 *header, struct hinic_recv_msg *recv_msg)
4896dd8b682SAviad Krawczyk {
4906dd8b682SAviad Krawczyk 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
4916dd8b682SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
4926dd8b682SAviad Krawczyk 	int seq_id, seg_len;
4936dd8b682SAviad Krawczyk 	u8 *msg_body;
4946dd8b682SAviad Krawczyk 
4956dd8b682SAviad Krawczyk 	seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
4966dd8b682SAviad Krawczyk 	seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
4976dd8b682SAviad Krawczyk 
4986dd8b682SAviad Krawczyk 	if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
4996dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "recv big mgmt msg\n");
5006dd8b682SAviad Krawczyk 		return;
5016dd8b682SAviad Krawczyk 	}
5026dd8b682SAviad Krawczyk 
5036dd8b682SAviad Krawczyk 	msg_body = (u8 *)header + sizeof(*header);
5046dd8b682SAviad Krawczyk 	memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
5056dd8b682SAviad Krawczyk 
5066dd8b682SAviad Krawczyk 	if (!HINIC_MSG_HEADER_GET(*header, LAST))
5076dd8b682SAviad Krawczyk 		return;
5086dd8b682SAviad Krawczyk 
5096dd8b682SAviad Krawczyk 	recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
5106dd8b682SAviad Krawczyk 	recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
5116dd8b682SAviad Krawczyk 	recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
5126dd8b682SAviad Krawczyk 							  ASYNC_MGMT_TO_PF);
5136dd8b682SAviad Krawczyk 	recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
5146dd8b682SAviad Krawczyk 	recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
5156dd8b682SAviad Krawczyk 
5166dd8b682SAviad Krawczyk 	if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
5176dd8b682SAviad Krawczyk 		mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
5186dd8b682SAviad Krawczyk 	else
5196dd8b682SAviad Krawczyk 		mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
5206dd8b682SAviad Krawczyk }
5216dd8b682SAviad Krawczyk 
522a5564e7eSAviad Krawczyk /**
523a5564e7eSAviad Krawczyk  * mgmt_msg_aeqe_handler - handler for a mgmt message event
524a5564e7eSAviad Krawczyk  * @handle: PF to MGMT channel
525a5564e7eSAviad Krawczyk  * @data: the header of the message
526a5564e7eSAviad Krawczyk  * @size: unused
527a5564e7eSAviad Krawczyk  **/
mgmt_msg_aeqe_handler(void * handle,void * data,u8 size)528a5564e7eSAviad Krawczyk static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
529a5564e7eSAviad Krawczyk {
5306dd8b682SAviad Krawczyk 	struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
5316dd8b682SAviad Krawczyk 	struct hinic_recv_msg *recv_msg;
5326dd8b682SAviad Krawczyk 	u64 *header = (u64 *)data;
5336dd8b682SAviad Krawczyk 
5346dd8b682SAviad Krawczyk 	recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
5356dd8b682SAviad Krawczyk 		   MGMT_DIRECT_SEND ?
5366dd8b682SAviad Krawczyk 		   &pf_to_mgmt->recv_msg_from_mgmt :
5376dd8b682SAviad Krawczyk 		   &pf_to_mgmt->recv_resp_msg_from_mgmt;
5386dd8b682SAviad Krawczyk 
5396dd8b682SAviad Krawczyk 	recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
5406dd8b682SAviad Krawczyk }
5416dd8b682SAviad Krawczyk 
5426dd8b682SAviad Krawczyk /**
5436dd8b682SAviad Krawczyk  * alloc_recv_msg - allocate receive message memory
5446dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
5456dd8b682SAviad Krawczyk  * @recv_msg: pointer that will hold the allocated data
5466dd8b682SAviad Krawczyk  *
5476dd8b682SAviad Krawczyk  * Return 0 - Success, negative - Failure
5486dd8b682SAviad Krawczyk  **/
alloc_recv_msg(struct hinic_pf_to_mgmt * pf_to_mgmt,struct hinic_recv_msg * recv_msg)5496dd8b682SAviad Krawczyk static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
5506dd8b682SAviad Krawczyk 			  struct hinic_recv_msg *recv_msg)
5516dd8b682SAviad Krawczyk {
5526dd8b682SAviad Krawczyk 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
5536dd8b682SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
5546dd8b682SAviad Krawczyk 
5556dd8b682SAviad Krawczyk 	recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
5566dd8b682SAviad Krawczyk 				     GFP_KERNEL);
5576dd8b682SAviad Krawczyk 	if (!recv_msg->msg)
5586dd8b682SAviad Krawczyk 		return -ENOMEM;
5596dd8b682SAviad Krawczyk 
5606dd8b682SAviad Krawczyk 	recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
5616dd8b682SAviad Krawczyk 					 GFP_KERNEL);
5626dd8b682SAviad Krawczyk 	if (!recv_msg->buf_out)
5636dd8b682SAviad Krawczyk 		return -ENOMEM;
5646dd8b682SAviad Krawczyk 
5656dd8b682SAviad Krawczyk 	return 0;
5666dd8b682SAviad Krawczyk }
5676dd8b682SAviad Krawczyk 
5686dd8b682SAviad Krawczyk /**
5696dd8b682SAviad Krawczyk  * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
5706dd8b682SAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
5716dd8b682SAviad Krawczyk  *
5726dd8b682SAviad Krawczyk  * Return 0 - Success, negative - Failure
5736dd8b682SAviad Krawczyk  **/
alloc_msg_buf(struct hinic_pf_to_mgmt * pf_to_mgmt)5746dd8b682SAviad Krawczyk static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
5756dd8b682SAviad Krawczyk {
5766dd8b682SAviad Krawczyk 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
5776dd8b682SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
5786dd8b682SAviad Krawczyk 	int err;
5796dd8b682SAviad Krawczyk 
5806dd8b682SAviad Krawczyk 	err = alloc_recv_msg(pf_to_mgmt,
5816dd8b682SAviad Krawczyk 			     &pf_to_mgmt->recv_msg_from_mgmt);
5826dd8b682SAviad Krawczyk 	if (err) {
5836dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "Failed to allocate recv msg\n");
5846dd8b682SAviad Krawczyk 		return err;
5856dd8b682SAviad Krawczyk 	}
5866dd8b682SAviad Krawczyk 
5876dd8b682SAviad Krawczyk 	err = alloc_recv_msg(pf_to_mgmt,
5886dd8b682SAviad Krawczyk 			     &pf_to_mgmt->recv_resp_msg_from_mgmt);
5896dd8b682SAviad Krawczyk 	if (err) {
5906dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
5916dd8b682SAviad Krawczyk 		return err;
5926dd8b682SAviad Krawczyk 	}
5936dd8b682SAviad Krawczyk 
5946dd8b682SAviad Krawczyk 	pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
5956dd8b682SAviad Krawczyk 						MAX_PF_MGMT_BUF_SIZE,
5966dd8b682SAviad Krawczyk 						GFP_KERNEL);
5976dd8b682SAviad Krawczyk 	if (!pf_to_mgmt->sync_msg_buf)
5986dd8b682SAviad Krawczyk 		return -ENOMEM;
5996dd8b682SAviad Krawczyk 
6006dbb8901SLuo bin 	pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
6016dbb8901SLuo bin 						MAX_PF_MGMT_BUF_SIZE,
6026dbb8901SLuo bin 						GFP_KERNEL);
6036dbb8901SLuo bin 	if (!pf_to_mgmt->mgmt_ack_buf)
6046dbb8901SLuo bin 		return -ENOMEM;
6056dbb8901SLuo bin 
6066dd8b682SAviad Krawczyk 	return 0;
607a5564e7eSAviad Krawczyk }
608a5564e7eSAviad Krawczyk 
609a5564e7eSAviad Krawczyk /**
610a5564e7eSAviad Krawczyk  * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
611a5564e7eSAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
612a5564e7eSAviad Krawczyk  * @hwif: HW interface the PF to MGMT will use for accessing HW
613a5564e7eSAviad Krawczyk  *
614a5564e7eSAviad Krawczyk  * Return 0 - Success, negative - Failure
615a5564e7eSAviad Krawczyk  **/
hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt * pf_to_mgmt,struct hinic_hwif * hwif)616a5564e7eSAviad Krawczyk int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
617a5564e7eSAviad Krawczyk 			  struct hinic_hwif *hwif)
618a5564e7eSAviad Krawczyk {
619a5564e7eSAviad Krawczyk 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
620a5564e7eSAviad Krawczyk 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
621eabf0fadSAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
622eabf0fadSAviad Krawczyk 	int err;
623a5564e7eSAviad Krawczyk 
624a5564e7eSAviad Krawczyk 	pf_to_mgmt->hwif = hwif;
6257dd29ee1SLuo bin 	pf_to_mgmt->hwdev = hwdev;
6267dd29ee1SLuo bin 
6277dd29ee1SLuo bin 	if (HINIC_IS_VF(hwif))
6287dd29ee1SLuo bin 		return 0;
629a5564e7eSAviad Krawczyk 
630c15850c7SLuo bin 	err = hinic_health_reporters_create(hwdev->devlink_dev);
631c15850c7SLuo bin 	if (err)
632c15850c7SLuo bin 		return err;
633c15850c7SLuo bin 
6346dd8b682SAviad Krawczyk 	sema_init(&pf_to_mgmt->sync_msg_lock, 1);
6356dbb8901SLuo bin 	pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
6366dbb8901SLuo bin 	if (!pf_to_mgmt->workq) {
6376dbb8901SLuo bin 		dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
638c15850c7SLuo bin 		hinic_health_reporters_destroy(hwdev->devlink_dev);
6396dbb8901SLuo bin 		return -ENOMEM;
6406dbb8901SLuo bin 	}
6416dd8b682SAviad Krawczyk 	pf_to_mgmt->sync_msg_id = 0;
6426dd8b682SAviad Krawczyk 
6436dd8b682SAviad Krawczyk 	err = alloc_msg_buf(pf_to_mgmt);
6446dd8b682SAviad Krawczyk 	if (err) {
6456dd8b682SAviad Krawczyk 		dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
646cf31d1efSZheng Bin 		destroy_workqueue(pf_to_mgmt->workq);
647c15850c7SLuo bin 		hinic_health_reporters_destroy(hwdev->devlink_dev);
6486dd8b682SAviad Krawczyk 		return err;
6496dd8b682SAviad Krawczyk 	}
6506dd8b682SAviad Krawczyk 
651eabf0fadSAviad Krawczyk 	err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
652eabf0fadSAviad Krawczyk 	if (err) {
653eabf0fadSAviad Krawczyk 		dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
654cf31d1efSZheng Bin 		destroy_workqueue(pf_to_mgmt->workq);
655c15850c7SLuo bin 		hinic_health_reporters_destroy(hwdev->devlink_dev);
656eabf0fadSAviad Krawczyk 		return err;
657eabf0fadSAviad Krawczyk 	}
658eabf0fadSAviad Krawczyk 
659a5564e7eSAviad Krawczyk 	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
660a5564e7eSAviad Krawczyk 				 pf_to_mgmt,
661a5564e7eSAviad Krawczyk 				 mgmt_msg_aeqe_handler);
662a5564e7eSAviad Krawczyk 	return 0;
663a5564e7eSAviad Krawczyk }
664a5564e7eSAviad Krawczyk 
665a5564e7eSAviad Krawczyk /**
666a5564e7eSAviad Krawczyk  * hinic_pf_to_mgmt_free - free PF to MGMT channel
667a5564e7eSAviad Krawczyk  * @pf_to_mgmt: PF to MGMT channel
668a5564e7eSAviad Krawczyk  **/
hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt * pf_to_mgmt)669a5564e7eSAviad Krawczyk void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
670a5564e7eSAviad Krawczyk {
671a5564e7eSAviad Krawczyk 	struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
672a5564e7eSAviad Krawczyk 	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
673a5564e7eSAviad Krawczyk 
6747dd29ee1SLuo bin 	if (HINIC_IS_VF(hwdev->hwif))
6757dd29ee1SLuo bin 		return;
6767dd29ee1SLuo bin 
677a5564e7eSAviad Krawczyk 	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
678eabf0fadSAviad Krawczyk 	hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
6796dbb8901SLuo bin 	destroy_workqueue(pf_to_mgmt->workq);
680c15850c7SLuo bin 	hinic_health_reporters_destroy(hwdev->devlink_dev);
681a5564e7eSAviad Krawczyk }
682