Commit a425b6e1 authored by Luo bin's avatar Luo bin Committed by David S. Miller

hinic: add mailbox function support

virtual function and physical function can communicate with each
other through mailbox channel supported by hw
Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c90af587
...@@ -4,4 +4,4 @@ obj-$(CONFIG_HINIC) += hinic.o ...@@ -4,4 +4,4 @@ obj-$(CONFIG_HINIC) += hinic.o
hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \
hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \ hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \
hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \ hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \
hinic_common.o hinic_ethtool.o hinic_common.o hinic_ethtool.o hinic_hw_mbox.o
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
/* HW interface registers */ /* HW interface registers */
#define HINIC_CSR_FUNC_ATTR0_ADDR 0x0 #define HINIC_CSR_FUNC_ATTR0_ADDR 0x0
#define HINIC_CSR_FUNC_ATTR1_ADDR 0x4 #define HINIC_CSR_FUNC_ATTR1_ADDR 0x4
#define HINIC_CSR_FUNC_ATTR2_ADDR 0x8
#define HINIC_CSR_FUNC_ATTR4_ADDR 0x10 #define HINIC_CSR_FUNC_ATTR4_ADDR 0x10
#define HINIC_CSR_FUNC_ATTR5_ADDR 0x14 #define HINIC_CSR_FUNC_ATTR5_ADDR 0x14
......
...@@ -676,10 +676,23 @@ static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev) ...@@ -676,10 +676,23 @@ static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
return err; return err;
} }
hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, err = hinic_func_to_func_init(hwdev);
pfhwdev, nic_mgmt_msg_handler); if (err) {
dev_err(&hwif->pdev->dev, "Failed to init mailbox\n");
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
return err;
}
if (!HINIC_IS_VF(hwif))
hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
HINIC_MOD_L2NIC, pfhwdev,
nic_mgmt_msg_handler);
else
hinic_register_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC,
nic_mgmt_msg_handler);
hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE); hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE);
return 0; return 0;
} }
...@@ -693,7 +706,13 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev) ...@@ -693,7 +706,13 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT); hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT);
hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC); if (!HINIC_IS_VF(hwdev->hwif))
hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
HINIC_MOD_L2NIC);
else
hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC);
hinic_func_to_func_free(hwdev);
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt); hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "hinic_hw_mgmt.h" #include "hinic_hw_mgmt.h"
#include "hinic_hw_qp.h" #include "hinic_hw_qp.h"
#include "hinic_hw_io.h" #include "hinic_hw_io.h"
#include "hinic_hw_mbox.h"
#define HINIC_MAX_QPS 32 #define HINIC_MAX_QPS 32
...@@ -225,6 +226,7 @@ struct hinic_hwdev { ...@@ -225,6 +226,7 @@ struct hinic_hwdev {
struct hinic_aeqs aeqs; struct hinic_aeqs aeqs;
struct hinic_func_to_io func_to_io; struct hinic_func_to_io func_to_io;
struct hinic_mbox_func_to_func *func_to_func;
struct hinic_cap nic_cap; struct hinic_cap nic_cap;
}; };
......
...@@ -143,8 +143,9 @@ enum hinic_eq_type { ...@@ -143,8 +143,9 @@ enum hinic_eq_type {
}; };
enum hinic_aeq_type { enum hinic_aeq_type {
HINIC_MBX_FROM_FUNC = 1,
HINIC_MSG_FROM_MGMT_CPU = 2, HINIC_MSG_FROM_MGMT_CPU = 2,
HINIC_MBX_SEND_RSLT = 5,
HINIC_MAX_AEQ_EVENTS, HINIC_MAX_AEQ_EVENTS,
}; };
......
...@@ -115,8 +115,12 @@ int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index) ...@@ -115,8 +115,12 @@ int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index)
**/ **/
void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action) void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action)
{ {
u32 attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR); u32 attr5;
if (HINIC_IS_VF(hwif))
return;
attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR);
attr5 = HINIC_FA5_CLEAR(attr5, PF_ACTION); attr5 = HINIC_FA5_CLEAR(attr5, PF_ACTION);
attr5 |= HINIC_FA5_SET(action, PF_ACTION); attr5 |= HINIC_FA5_SET(action, PF_ACTION);
...@@ -203,7 +207,8 @@ static int hwif_ready(struct hinic_hwif *hwif) ...@@ -203,7 +207,8 @@ static int hwif_ready(struct hinic_hwif *hwif)
* @attr0: the first attribute that was read from the hw * @attr0: the first attribute that was read from the hw
* @attr1: the second attribute that was read from the hw * @attr1: the second attribute that was read from the hw
**/ **/
static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1) static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1,
u32 attr2)
{ {
hwif->attr.func_idx = HINIC_FA0_GET(attr0, FUNC_IDX); hwif->attr.func_idx = HINIC_FA0_GET(attr0, FUNC_IDX);
hwif->attr.pf_idx = HINIC_FA0_GET(attr0, PF_IDX); hwif->attr.pf_idx = HINIC_FA0_GET(attr0, PF_IDX);
...@@ -214,6 +219,8 @@ static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1) ...@@ -214,6 +219,8 @@ static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1)
hwif->attr.num_ceqs = BIT(HINIC_FA1_GET(attr1, CEQS_PER_FUNC)); hwif->attr.num_ceqs = BIT(HINIC_FA1_GET(attr1, CEQS_PER_FUNC));
hwif->attr.num_irqs = BIT(HINIC_FA1_GET(attr1, IRQS_PER_FUNC)); hwif->attr.num_irqs = BIT(HINIC_FA1_GET(attr1, IRQS_PER_FUNC));
hwif->attr.num_dma_attr = BIT(HINIC_FA1_GET(attr1, DMA_ATTR_PER_FUNC)); hwif->attr.num_dma_attr = BIT(HINIC_FA1_GET(attr1, DMA_ATTR_PER_FUNC));
hwif->attr.global_vf_id_of_pf = HINIC_FA2_GET(attr2,
GLOBAL_VF_ID_OF_PF);
} }
/** /**
...@@ -222,7 +229,7 @@ static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1) ...@@ -222,7 +229,7 @@ static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1)
**/ **/
static void read_hwif_attr(struct hinic_hwif *hwif) static void read_hwif_attr(struct hinic_hwif *hwif)
{ {
u32 addr, attr0, attr1; u32 addr, attr0, attr1, attr2;
addr = HINIC_CSR_FUNC_ATTR0_ADDR; addr = HINIC_CSR_FUNC_ATTR0_ADDR;
attr0 = hinic_hwif_read_reg(hwif, addr); attr0 = hinic_hwif_read_reg(hwif, addr);
...@@ -230,7 +237,10 @@ static void read_hwif_attr(struct hinic_hwif *hwif) ...@@ -230,7 +237,10 @@ static void read_hwif_attr(struct hinic_hwif *hwif)
addr = HINIC_CSR_FUNC_ATTR1_ADDR; addr = HINIC_CSR_FUNC_ATTR1_ADDR;
attr1 = hinic_hwif_read_reg(hwif, addr); attr1 = hinic_hwif_read_reg(hwif, addr);
set_hwif_attr(hwif, attr0, attr1); addr = HINIC_CSR_FUNC_ATTR2_ADDR;
attr2 = hinic_hwif_read_reg(hwif, addr);
set_hwif_attr(hwif, attr0, attr1, attr2);
} }
/** /**
...@@ -309,6 +319,34 @@ static void dma_attr_init(struct hinic_hwif *hwif) ...@@ -309,6 +319,34 @@ static void dma_attr_init(struct hinic_hwif *hwif)
HINIC_PCIE_SNOOP, HINIC_PCIE_TPH_DISABLE); HINIC_PCIE_SNOOP, HINIC_PCIE_TPH_DISABLE);
} }
u16 hinic_glb_pf_vf_offset(struct hinic_hwif *hwif)
{
if (!hwif)
return 0;
return hwif->attr.global_vf_id_of_pf;
}
u16 hinic_global_func_id_hw(struct hinic_hwif *hwif)
{
u32 addr, attr0;
addr = HINIC_CSR_FUNC_ATTR0_ADDR;
attr0 = hinic_hwif_read_reg(hwif, addr);
return HINIC_FA0_GET(attr0, FUNC_IDX);
}
u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif)
{
u32 addr, attr0;
addr = HINIC_CSR_FUNC_ATTR0_ADDR;
attr0 = hinic_hwif_read_reg(hwif, addr);
return HINIC_FA0_GET(attr0, PF_IDX);
}
/** /**
* hinic_init_hwif - initialize the hw interface * hinic_init_hwif - initialize the hw interface
* @hwif: the HW interface of a pci function device * @hwif: the HW interface of a pci function device
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define HINIC_FA0_FUNC_IDX_SHIFT 0 #define HINIC_FA0_FUNC_IDX_SHIFT 0
#define HINIC_FA0_PF_IDX_SHIFT 10 #define HINIC_FA0_PF_IDX_SHIFT 10
#define HINIC_FA0_PCI_INTF_IDX_SHIFT 14 #define HINIC_FA0_PCI_INTF_IDX_SHIFT 14
#define HINIC_FA0_VF_IN_PF_SHIFT 16
/* reserved members - off 16 */ /* reserved members - off 16 */
#define HINIC_FA0_FUNC_TYPE_SHIFT 24 #define HINIC_FA0_FUNC_TYPE_SHIFT 24
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
#define HINIC_FA0_PF_IDX_MASK 0xF #define HINIC_FA0_PF_IDX_MASK 0xF
#define HINIC_FA0_PCI_INTF_IDX_MASK 0x3 #define HINIC_FA0_PCI_INTF_IDX_MASK 0x3
#define HINIC_FA0_FUNC_TYPE_MASK 0x1 #define HINIC_FA0_FUNC_TYPE_MASK 0x1
#define HINIC_FA0_VF_IN_PF_MASK 0xFF
#define HINIC_FA0_GET(val, member) \ #define HINIC_FA0_GET(val, member) \
(((val) >> HINIC_FA0_##member##_SHIFT) & HINIC_FA0_##member##_MASK) (((val) >> HINIC_FA0_##member##_SHIFT) & HINIC_FA0_##member##_MASK)
...@@ -64,6 +66,12 @@ ...@@ -64,6 +66,12 @@
#define HINIC_FA1_GET(val, member) \ #define HINIC_FA1_GET(val, member) \
(((val) >> HINIC_FA1_##member##_SHIFT) & HINIC_FA1_##member##_MASK) (((val) >> HINIC_FA1_##member##_SHIFT) & HINIC_FA1_##member##_MASK)
#define HINIC_FA2_GLOBAL_VF_ID_OF_PF_SHIFT 16
#define HINIC_FA2_GLOBAL_VF_ID_OF_PF_MASK 0x3FF
#define HINIC_FA2_GET(val, member) \
(((val) >> HINIC_FA2_##member##_SHIFT) & HINIC_FA2_##member##_MASK)
#define HINIC_FA4_OUTBOUND_STATE_SHIFT 0 #define HINIC_FA4_OUTBOUND_STATE_SHIFT 0
#define HINIC_FA4_DB_STATE_SHIFT 1 #define HINIC_FA4_DB_STATE_SHIFT 1
...@@ -140,6 +148,7 @@ ...@@ -140,6 +148,7 @@
#define HINIC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx) #define HINIC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx)
#define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type)
#define HINIC_IS_VF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_VF)
#define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF) #define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF)
#define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF) #define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF)
...@@ -173,6 +182,7 @@ enum hinic_pcie_tph { ...@@ -173,6 +182,7 @@ enum hinic_pcie_tph {
enum hinic_func_type { enum hinic_func_type {
HINIC_PF = 0, HINIC_PF = 0,
HINIC_VF = 1,
HINIC_PPF = 2, HINIC_PPF = 2,
}; };
...@@ -223,6 +233,8 @@ struct hinic_func_attr { ...@@ -223,6 +233,8 @@ struct hinic_func_attr {
u8 num_ceqs; u8 num_ceqs;
u8 num_dma_attr; u8 num_dma_attr;
u16 global_vf_id_of_pf;
}; };
struct hinic_hwif { struct hinic_hwif {
...@@ -271,6 +283,12 @@ enum hinic_db_state hinic_db_state_get(struct hinic_hwif *hwif); ...@@ -271,6 +283,12 @@ enum hinic_db_state hinic_db_state_get(struct hinic_hwif *hwif);
void hinic_db_state_set(struct hinic_hwif *hwif, void hinic_db_state_set(struct hinic_hwif *hwif,
enum hinic_db_state db_state); enum hinic_db_state db_state);
u16 hinic_glb_pf_vf_offset(struct hinic_hwif *hwif);
u16 hinic_global_func_id_hw(struct hinic_hwif *hwif);
u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif);
int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev); int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev);
void hinic_free_hwif(struct hinic_hwif *hwif); void hinic_free_hwif(struct hinic_hwif *hwif);
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*/
#ifndef HINIC_MBOX_H_
#define HINIC_MBOX_H_
#define HINIC_MBOX_PF_SEND_ERR 0x1
#define HINIC_MBOX_PF_BUSY_ACTIVE_FW 0x2
#define HINIC_MBOX_VF_CMD_ERROR 0x3
#define HINIC_MAX_FUNCTIONS 512
#define HINIC_MAX_PF_FUNCS 16
#define HINIC_MBOX_WQ_NAME "hinic_mbox"
#define HINIC_FUNC_CSR_MAILBOX_DATA_OFF 0x80
#define HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF 0x0100
#define HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF 0x0104
#define HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF 0x0108
#define HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF 0x010C
enum hinic_mbox_ack_type {
MBOX_ACK,
MBOX_NO_ACK,
};
struct mbox_msg_info {
u8 msg_id;
u8 status;
};
struct hinic_recv_mbox {
struct completion recv_done;
void *mbox;
u8 cmd;
enum hinic_mod_type mod;
u16 mbox_len;
void *buf_out;
enum hinic_mbox_ack_type ack_type;
struct mbox_msg_info msg_info;
u8 seq_id;
atomic_t msg_cnt;
};
struct hinic_send_mbox {
struct completion send_done;
u8 *data;
u64 *wb_status;
void *wb_vaddr;
dma_addr_t wb_paddr;
};
typedef void (*hinic_vf_mbox_cb)(void *handle, u8 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size);
typedef int (*hinic_pf_mbox_cb)(void *handle, u16 vf_id, u8 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size);
enum mbox_event_state {
EVENT_START = 0,
EVENT_FAIL,
EVENT_TIMEOUT,
EVENT_END,
};
enum hinic_mbox_cb_state {
HINIC_VF_MBOX_CB_REG = 0,
HINIC_VF_MBOX_CB_RUNNING,
HINIC_PF_MBOX_CB_REG,
HINIC_PF_MBOX_CB_RUNNING,
HINIC_PPF_MBOX_CB_REG,
HINIC_PPF_MBOX_CB_RUNNING,
HINIC_PPF_TO_PF_MBOX_CB_REG,
HINIC_PPF_TO_PF_MBOX_CB_RUNNIG,
};
struct hinic_mbox_func_to_func {
struct hinic_hwdev *hwdev;
struct hinic_hwif *hwif;
struct semaphore mbox_send_sem;
struct semaphore msg_send_sem;
struct hinic_send_mbox send_mbox;
struct workqueue_struct *workq;
struct hinic_recv_mbox mbox_resp[HINIC_MAX_FUNCTIONS];
struct hinic_recv_mbox mbox_send[HINIC_MAX_FUNCTIONS];
hinic_vf_mbox_cb vf_mbox_cb[HINIC_MOD_MAX];
hinic_pf_mbox_cb pf_mbox_cb[HINIC_MOD_MAX];
unsigned long pf_mbox_cb_state[HINIC_MOD_MAX];
unsigned long vf_mbox_cb_state[HINIC_MOD_MAX];
u8 send_msg_id;
enum mbox_event_state event_flag;
/* lock for mbox event flag */
spinlock_t mbox_lock;
};
struct hinic_mbox_work {
struct work_struct work;
u16 src_func_idx;
struct hinic_mbox_func_to_func *func_to_func;
struct hinic_recv_mbox *recv_mbox;
};
struct vf_cmd_msg_handle {
u8 cmd;
int (*cmd_msg_handler)(void *hwdev, u16 vf_id,
void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
};
int hinic_register_pf_mbox_cb(struct hinic_hwdev *hwdev,
enum hinic_mod_type mod,
hinic_pf_mbox_cb callback);
int hinic_register_vf_mbox_cb(struct hinic_hwdev *hwdev,
enum hinic_mod_type mod,
hinic_vf_mbox_cb callback);
void hinic_unregister_pf_mbox_cb(struct hinic_hwdev *hwdev,
enum hinic_mod_type mod);
void hinic_unregister_vf_mbox_cb(struct hinic_hwdev *hwdev,
enum hinic_mod_type mod);
void hinic_mbox_func_aeqe_handler(void *handle, void *header, u8 size);
void hinic_mbox_self_aeqe_handler(void *handle, void *header, u8 size);
int hinic_func_to_func_init(struct hinic_hwdev *hwdev);
void hinic_func_to_func_free(struct hinic_hwdev *hwdev);
int hinic_mbox_to_pf(struct hinic_hwdev *hwdev, enum hinic_mod_type mod,
u8 cmd, void *buf_in, u16 in_size, void *buf_out,
u16 *out_size, u32 timeout);
int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
enum hinic_mod_type mod, u16 cmd, u16 dst_func,
void *buf_in, u16 in_size, void *buf_out,
u16 *out_size, u32 timeout);
int hinic_mbox_to_vf(struct hinic_hwdev *hwdev,
enum hinic_mod_type mod, u16 vf_id, u8 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size, u32 timeout);
#endif
...@@ -60,6 +60,7 @@ enum hinic_cfg_cmd { ...@@ -60,6 +60,7 @@ enum hinic_cfg_cmd {
}; };
enum hinic_comm_cmd { enum hinic_comm_cmd {
HINIC_COMM_CMD_START_FLR = 0x1,
HINIC_COMM_CMD_IO_STATUS_GET = 0x3, HINIC_COMM_CMD_IO_STATUS_GET = 0x3,
HINIC_COMM_CMD_CMDQ_CTXT_SET = 0x10, HINIC_COMM_CMD_CMDQ_CTXT_SET = 0x10,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment