hinic: add mailbox function support
virtual function and physical function can communicate with each other through mailbox channel supported by hw Signed-off-by: Luo bin <luobin9@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c90af587a9
commit
a425b6e1c6
@ -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_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_common.o hinic_ethtool.o
|
||||
hinic_common.o hinic_ethtool.o hinic_hw_mbox.o
|
||||
|
@ -10,7 +10,7 @@
|
||||
/* HW interface registers */
|
||||
#define HINIC_CSR_FUNC_ATTR0_ADDR 0x0
|
||||
#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_ATTR5_ADDR 0x14
|
||||
|
||||
|
@ -676,10 +676,23 @@ static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC,
|
||||
pfhwdev, nic_mgmt_msg_handler);
|
||||
err = hinic_func_to_func_init(hwdev);
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -693,7 +706,13 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "hinic_hw_mgmt.h"
|
||||
#include "hinic_hw_qp.h"
|
||||
#include "hinic_hw_io.h"
|
||||
#include "hinic_hw_mbox.h"
|
||||
|
||||
#define HINIC_MAX_QPS 32
|
||||
|
||||
@ -225,6 +226,7 @@ struct hinic_hwdev {
|
||||
|
||||
struct hinic_aeqs aeqs;
|
||||
struct hinic_func_to_io func_to_io;
|
||||
struct hinic_mbox_func_to_func *func_to_func;
|
||||
|
||||
struct hinic_cap nic_cap;
|
||||
};
|
||||
|
@ -143,8 +143,9 @@ enum hinic_eq_type {
|
||||
};
|
||||
|
||||
enum hinic_aeq_type {
|
||||
HINIC_MBX_FROM_FUNC = 1,
|
||||
HINIC_MSG_FROM_MGMT_CPU = 2,
|
||||
|
||||
HINIC_MBX_SEND_RSLT = 5,
|
||||
HINIC_MAX_AEQ_EVENTS,
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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_SET(action, PF_ACTION);
|
||||
|
||||
@ -203,7 +207,8 @@ static int hwif_ready(struct hinic_hwif *hwif)
|
||||
* @attr0: the first 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.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)
|
||||
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_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)
|
||||
**/
|
||||
static void read_hwif_attr(struct hinic_hwif *hwif)
|
||||
{
|
||||
u32 addr, attr0, attr1;
|
||||
u32 addr, attr0, attr1, attr2;
|
||||
|
||||
addr = HINIC_CSR_FUNC_ATTR0_ADDR;
|
||||
attr0 = hinic_hwif_read_reg(hwif, addr);
|
||||
@ -230,7 +237,10 @@ static void read_hwif_attr(struct hinic_hwif *hwif)
|
||||
addr = HINIC_CSR_FUNC_ATTR1_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)
|
||||
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
|
||||
* @hwif: the HW interface of a pci function device
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define HINIC_FA0_FUNC_IDX_SHIFT 0
|
||||
#define HINIC_FA0_PF_IDX_SHIFT 10
|
||||
#define HINIC_FA0_PCI_INTF_IDX_SHIFT 14
|
||||
#define HINIC_FA0_VF_IN_PF_SHIFT 16
|
||||
/* reserved members - off 16 */
|
||||
#define HINIC_FA0_FUNC_TYPE_SHIFT 24
|
||||
|
||||
@ -42,6 +43,7 @@
|
||||
#define HINIC_FA0_PF_IDX_MASK 0xF
|
||||
#define HINIC_FA0_PCI_INTF_IDX_MASK 0x3
|
||||
#define HINIC_FA0_FUNC_TYPE_MASK 0x1
|
||||
#define HINIC_FA0_VF_IN_PF_MASK 0xFF
|
||||
|
||||
#define HINIC_FA0_GET(val, member) \
|
||||
(((val) >> HINIC_FA0_##member##_SHIFT) & HINIC_FA0_##member##_MASK)
|
||||
@ -64,6 +66,12 @@
|
||||
#define HINIC_FA1_GET(val, member) \
|
||||
(((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_DB_STATE_SHIFT 1
|
||||
|
||||
@ -140,6 +148,7 @@
|
||||
#define HINIC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx)
|
||||
|
||||
#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_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF)
|
||||
|
||||
@ -173,6 +182,7 @@ enum hinic_pcie_tph {
|
||||
|
||||
enum hinic_func_type {
|
||||
HINIC_PF = 0,
|
||||
HINIC_VF = 1,
|
||||
HINIC_PPF = 2,
|
||||
};
|
||||
|
||||
@ -223,6 +233,8 @@ struct hinic_func_attr {
|
||||
u8 num_ceqs;
|
||||
|
||||
u8 num_dma_attr;
|
||||
|
||||
u16 global_vf_id_of_pf;
|
||||
};
|
||||
|
||||
struct hinic_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,
|
||||
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);
|
||||
|
||||
void hinic_free_hwif(struct hinic_hwif *hwif);
|
||||
|
1213
drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
Normal file
1213
drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
Normal file
File diff suppressed because it is too large
Load Diff
154
drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.h
Normal file
154
drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* 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 {
|
||||
};
|
||||
|
||||
enum hinic_comm_cmd {
|
||||
HINIC_COMM_CMD_START_FLR = 0x1,
|
||||
HINIC_COMM_CMD_IO_STATUS_GET = 0x3,
|
||||
|
||||
HINIC_COMM_CMD_CMDQ_CTXT_SET = 0x10,
|
||||
|
Loading…
x
Reference in New Issue
Block a user