// SPDX-License-Identifier: GPL-2.0-only /* * Huawei HiNIC PCI Express Linux driver * Copyright(c) 2017 Huawei Technologies Co., Ltd */ #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/pci.h> #include <linux/device.h> #include <linux/semaphore.h> #include <linux/completion.h> #include <linux/slab.h> #include <net/devlink.h> #include <asm/barrier.h> #include "hinic_devlink.h" #include "hinic_hw_if.h" #include "hinic_hw_eqs.h" #include "hinic_hw_api_cmd.h" #include "hinic_hw_mgmt.h" #include "hinic_hw_dev.h" #define SYNC_MSG_ID_MASK … #define SYNC_MSG_ID(pf_to_mgmt) … #define SYNC_MSG_ID_INC(pf_to_mgmt) … #define MSG_SZ_IS_VALID(in_size) … #define MGMT_MSG_LEN_MIN … #define MGMT_MSG_LEN_STEP … #define MGMT_MSG_RSVD_FOR_DEV … #define SEGMENT_LEN … #define MAX_PF_MGMT_BUF_SIZE … /* Data should be SEG LEN size aligned */ #define MAX_MSG_LEN … #define MSG_NOT_RESP … #define MGMT_MSG_TIMEOUT … #define SET_FUNC_PORT_MBOX_TIMEOUT … #define SET_FUNC_PORT_MGMT_TIMEOUT … #define UPDATE_FW_MGMT_TIMEOUT … #define mgmt_to_pfhwdev(pf_mgmt) … enum msg_segment_type { … }; enum mgmt_direction_type { … }; enum msg_ack_type { … }; /** * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module * @pf_to_mgmt: PF to MGMT channel * @mod: module in the chip that this handler will handle its messages * @handle: private data for the callback * @callback: the handler that will handle messages **/ void 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)) { … } /** * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module * @pf_to_mgmt: PF to MGMT channel * @mod: module in the chip that this handler handles its messages **/ void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt, enum hinic_mod_type mod) { … } /** * prepare_header - prepare the header of the message * @pf_to_mgmt: PF to MGMT channel * @msg_len: the length of the message * @mod: module in the chip that will get the message * @ack_type: ask for response * @direction: the direction of the message * @cmd: command of the message * @msg_id: message id * * Return the prepared header value **/ static u64 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) { … } /** * prepare_mgmt_cmd - prepare the mgmt command * @mgmt_cmd: pointer to the command to prepare * @header: pointer of the header for the message * @msg: the data of the message * @msg_len: the length of the message **/ static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, u8 *msg, u16 msg_len) { … } /** * mgmt_msg_len - calculate the total message length * @msg_data_len: the length of the message data * * Return the total message length **/ static u16 mgmt_msg_len(u16 msg_data_len) { … } /** * send_msg_to_mgmt - send message to mgmt by API CMD * @pf_to_mgmt: PF to MGMT channel * @mod: module in the chip that will get the message * @cmd: command of the message * @data: the msg data * @data_len: the msg data length * @ack_type: ask for response * @direction: the direction of the original message * @resp_msg_id: msg id to response for * * Return 0 - Success, negative - Failure **/ static int 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) { … } /** * msg_to_mgmt_sync - send sync message to mgmt * @pf_to_mgmt: PF to MGMT channel * @mod: module in the chip that will get the message * @cmd: command of the message * @buf_in: the msg data * @in_size: the msg data length * @buf_out: response * @out_size: response length * @direction: the direction of the original message * @resp_msg_id: msg id to response for * @timeout: time-out period of waiting for response * * Return 0 - Success, negative - Failure **/ static int 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) { … } /** * msg_to_mgmt_async - send message to mgmt without response * @pf_to_mgmt: PF to MGMT channel * @mod: module in the chip that will get the message * @cmd: command of the message * @buf_in: the msg data * @in_size: the msg data length * @direction: the direction of the original message * @resp_msg_id: msg id to response for * * Return 0 - Success, negative - Failure **/ static int 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) { … } /** * hinic_msg_to_mgmt - send message to mgmt * @pf_to_mgmt: PF to MGMT channel * @mod: module in the chip that will get the message * @cmd: command of the message * @buf_in: the msg data * @in_size: the msg data length * @buf_out: response * @out_size: returned response length * @sync: sync msg or async msg * * Return 0 - Success, negative - Failure **/ int 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) { … } static void recv_mgmt_msg_work_handler(struct work_struct *work) { … } /** * mgmt_recv_msg_handler - handler for message from mgmt cpu * @pf_to_mgmt: PF to MGMT channel * @recv_msg: received message details **/ static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt, struct hinic_recv_msg *recv_msg) { … } /** * mgmt_resp_msg_handler - handler for a response message from mgmt cpu * @pf_to_mgmt: PF to MGMT channel * @recv_msg: received message details **/ static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt, struct hinic_recv_msg *recv_msg) { … } /** * recv_mgmt_msg_handler - handler for a message from mgmt cpu * @pf_to_mgmt: PF to MGMT channel * @header: the header of the message * @recv_msg: received message details **/ static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt, u64 *header, struct hinic_recv_msg *recv_msg) { … } /** * mgmt_msg_aeqe_handler - handler for a mgmt message event * @handle: PF to MGMT channel * @data: the header of the message * @size: unused **/ static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size) { … } /** * alloc_recv_msg - allocate receive message memory * @pf_to_mgmt: PF to MGMT channel * @recv_msg: pointer that will hold the allocated data * * Return 0 - Success, negative - Failure **/ static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt, struct hinic_recv_msg *recv_msg) { … } /** * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel * @pf_to_mgmt: PF to MGMT channel * * Return 0 - Success, negative - Failure **/ static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt) { … } /** * hinic_pf_to_mgmt_init - initialize PF to MGMT channel * @pf_to_mgmt: PF to MGMT channel * @hwif: HW interface the PF to MGMT will use for accessing HW * * Return 0 - Success, negative - Failure **/ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt, struct hinic_hwif *hwif) { … } /** * hinic_pf_to_mgmt_free - free PF to MGMT channel * @pf_to_mgmt: PF to MGMT channel **/ void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt) { … }