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