From: Xue <xuechaojing(a)huawei.com>
commit f9e0a2f5aeedaea85af5c981b5f3f321a4f6ff27 openEuler-1.0
driver inclusion
category:bugfix
bugzilla:4472
CVE:NA
------------------------------------------------------------------------
Update Hi1822 nic driver from 1.8.2.8 to 2.3.2.0:
Problem repair and reliability enhancement. Due to the
complexity of this content, we do not describe it here. If necessary,
please contact (xue chaojing) Get the release note for
details.
Reviewed-by: Wu Like <wulike1(a)huawei.com>
Signed-off-by: Xue <xuechaojing(a)huawei.com>
Reviewed-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Xin Hao <haoxing990(a)gmail.com>
---
.../net/ethernet/huawei/hinic/hinic_api_cmd.c | 4 +-
drivers/net/ethernet/huawei/hinic/hinic_cfg.c | 129 ++++++-
drivers/net/ethernet/huawei/hinic/hinic_cfg.h | 5 +-
.../net/ethernet/huawei/hinic/hinic_cmdq.c | 54 ++-
.../net/ethernet/huawei/hinic/hinic_ctx_def.h | 11 +-
drivers/net/ethernet/huawei/hinic/hinic_dbg.h | 7 +-
.../ethernet/huawei/hinic/hinic_dbgtool_knl.c | 43 +--
.../ethernet/huawei/hinic/hinic_dbgtool_knl.h | 1 +
drivers/net/ethernet/huawei/hinic/hinic_dcb.c | 279 ++++++++++++++-
drivers/net/ethernet/huawei/hinic/hinic_dcb.h | 15 +
.../net/ethernet/huawei/hinic/hinic_dfx_def.h | 20 +-
drivers/net/ethernet/huawei/hinic/hinic_eqs.c | 92 ++++-
drivers/net/ethernet/huawei/hinic/hinic_eqs.h | 24 +-
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 32 +-
drivers/net/ethernet/huawei/hinic/hinic_hw.h | 20 +-
.../net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 19 +-
.../net/ethernet/huawei/hinic/hinic_hwdev.c | 213 ++++++-----
.../net/ethernet/huawei/hinic/hinic_hwdev.h | 34 +-
.../net/ethernet/huawei/hinic/hinic_hwif.c | 116 ++++++
drivers/net/ethernet/huawei/hinic/hinic_lld.c | 334 ++++++++----------
drivers/net/ethernet/huawei/hinic/hinic_lld.h | 7 +
.../net/ethernet/huawei/hinic/hinic_main.c | 160 +++++++--
.../net/ethernet/huawei/hinic/hinic_mbox.c | 119 ++++---
.../net/ethernet/huawei/hinic/hinic_mbox.h | 10 +-
.../net/ethernet/huawei/hinic/hinic_mgmt.c | 43 ++-
.../net/ethernet/huawei/hinic/hinic_mgmt.h | 8 +-
.../huawei/hinic/hinic_mgmt_interface.h | 9 +-
.../huawei/hinic/hinic_multi_host_mgmt.c | 83 +++--
drivers/net/ethernet/huawei/hinic/hinic_nic.h | 2 +
.../net/ethernet/huawei/hinic/hinic_nic_cfg.c | 319 ++++++++++++++---
.../net/ethernet/huawei/hinic/hinic_nic_cfg.h | 8 +-
.../net/ethernet/huawei/hinic/hinic_nic_dbg.c | 7 +-
.../net/ethernet/huawei/hinic/hinic_nic_dev.h | 16 +-
.../net/ethernet/huawei/hinic/hinic_nic_io.c | 31 +-
.../net/ethernet/huawei/hinic/hinic_nic_io.h | 3 +
.../net/ethernet/huawei/hinic/hinic_nictool.c | 272 +++++++++++++-
.../net/ethernet/huawei/hinic/hinic_nictool.h | 47 ++-
.../ethernet/huawei/hinic/hinic_pci_id_tbl.h | 1 +
.../ethernet/huawei/hinic/hinic_port_cmd.h | 24 +-
.../net/ethernet/huawei/hinic/hinic_qe_def.h | 52 +--
drivers/net/ethernet/huawei/hinic/hinic_rx.c | 12 +-
drivers/net/ethernet/huawei/hinic/hinic_rx.h | 5 +-
.../net/ethernet/huawei/hinic/hinic_sm_lt.h | 2 +-
.../ethernet/huawei/hinic/hinic_sml_counter.c | 4 +-
.../net/ethernet/huawei/hinic/hinic_sriov.c | 13 +-
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 54 ++-
drivers/net/ethernet/huawei/hinic/hinic_tx.h | 10 +-
drivers/net/ethernet/huawei/hinic/hinic_wq.c | 2 +-
.../ethernet/huawei/hinic/ossl_knl_linux.c | 4 +-
.../ethernet/huawei/hinic/ossl_knl_linux.h | 4 +-
50 files changed, 2093 insertions(+), 690 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_api_cmd.c
b/drivers/net/ethernet/huawei/hinic/hinic_api_cmd.c
index de190ba06064..6ead68963cf8 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_api_cmd.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_api_cmd.c
@@ -251,8 +251,8 @@ static void prepare_cell_ctrl(u64 *cell_ctrl, u16 cell_len)
**/
static void prepare_api_cmd(struct hinic_api_cmd_chain *chain,
struct hinic_api_cmd_cell *cell,
- enum hinic_node_id dest,
- void *cmd, u16 cmd_size)
+ enum hinic_node_id dest,
+ const void *cmd, u16 cmd_size)
{
struct hinic_api_cmd_cell_ctxt *cell_ctxt;
u32 priv;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c
b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c
index fbacba16f359..6662119f684b 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c
@@ -34,6 +34,20 @@
#include "hinic_nic_cfg.h"
#include "hinic_mgmt_interface.h"
#include "hinic_multi_host_mgmt.h"
+
+uint g_rdma_mtts_num;
+uint g_rdma_qps_num;
+uint g_rdma_mpts_num;
+uint g_vfs_num;
+module_param(g_rdma_mtts_num, uint, 0444);
+MODULE_PARM_DESC(g_rdma_mtts_num, "number of roce used mtts, use default value when
pass 0");
+module_param(g_rdma_qps_num, uint, 0444);
+MODULE_PARM_DESC(g_rdma_qps_num, "number of roce used qps, use default value when
pass 0");
+module_param(g_rdma_mpts_num, uint, 0444);
+MODULE_PARM_DESC(g_rdma_mpts_num, "number of roce used mpts, use default value when
pass 0");
+module_param(g_vfs_num, uint, 0444);
+MODULE_PARM_DESC(g_vfs_num, "number of used vfs, use default value when pass 0
");
+
uint intr_mode;
uint timer_enable = 1;
@@ -149,6 +163,7 @@ static void parse_pub_res_cap(struct service_cap *cap,
cap->cos_valid_bitmap = dev_cap->valid_cos_bitmap;
cap->er_id = dev_cap->er_id;
cap->port_id = dev_cap->port_id;
+ cap->force_up = dev_cap->force_up;
parse_sf_en_cap(cap, dev_cap, type);
@@ -253,6 +268,7 @@ static void parse_l2nic_res_cap(struct service_cap *cap,
nic_cap->max_rqs = dev_cap->nic_max_rq;
nic_cap->vf_max_sqs = 0;
nic_cap->vf_max_rqs = 0;
+ nic_cap->max_queue_allowed = dev_cap->max_queue_allowed;
}
if (dev_cap->nic_lro_en)
@@ -263,11 +279,12 @@ static void parse_l2nic_res_cap(struct service_cap *cap,
nic_cap->lro_sz = dev_cap->nic_lro_sz;
nic_cap->tso_sz = dev_cap->nic_tso_sz;
- pr_info("L2nic resource capbility, max_sqs=0x%x, max_rqs=0x%x, vf_max_sqs=0x%x,
vf_max_rqs=0x%x\n",
+ pr_info("L2nic resource capbility, max_sqs=0x%x, max_rqs=0x%x, vf_max_sqs=0x%x,
vf_max_rqs=0x%x, max_queue_allowed=0x%x\n",
nic_cap->max_sqs,
nic_cap->max_rqs,
nic_cap->vf_max_sqs,
- nic_cap->vf_max_rqs);
+ nic_cap->vf_max_rqs,
+ nic_cap->max_queue_allowed);
/* Check parameters from firmware */
if (nic_cap->max_sqs > HINIC_CFG_MAX_QP ||
@@ -557,7 +574,9 @@ static int get_cap_from_fw(struct hinic_hwdev *dev, enum func_type
type)
int err;
dev_cap.version = HINIC_CMD_VER_FUNC_ID;
- dev_cap.func_id = hinic_global_func_id(dev);
+ err = hinic_global_func_id_get(dev, &dev_cap.func_id);
+ if (err)
+ return err;
sdk_info(dev->dev_hdl, "Get cap from fw, func_idx: %d\n",
dev_cap.func_id);
@@ -630,6 +649,14 @@ static int get_dev_cap(struct hinic_hwdev *dev)
static void nic_param_fix(struct hinic_hwdev *dev)
{
+ struct nic_service_cap *nic_cap = &dev->cfg_mgmt->svc_cap.nic_cap;
+
+ if ((hinic_func_type(dev) == TYPE_VF) &&
+ nic_cap->max_queue_allowed != 0) {
+ nic_cap->max_rqs = nic_cap->max_queue_allowed;
+ nic_cap->max_sqs = nic_cap->max_queue_allowed;
+ }
+
}
static void rdma_param_fix(struct hinic_hwdev *dev)
@@ -696,7 +723,8 @@ static void rdma_param_fix(struct hinic_hwdev *dev)
* we use original 8bits directly for simpilification
*/
rdma_cap->max_fmr_maps = 255;
- rdma_cap->num_mtts = RDMA_NUM_MTTS;
+ rdma_cap->num_mtts = (g_rdma_mtts_num > 0 ?
+ g_rdma_mtts_num : RDMA_NUM_MTTS);
rdma_cap->log_mtt_seg = LOG_MTT_SEG;
rdma_cap->mtt_entry_sz = MTT_ENTRY_SZ;
rdma_cap->log_rdmarc_seg = LOG_RDMARC_SEG;
@@ -1158,7 +1186,7 @@ int hinic_alloc_ceqs(void *hwdev, enum hinic_service_type type, int
num,
for (i = 0; i < num; i++) {
if (eq->num_ceq_remain == 0) {
sdk_warn(dev->dev_hdl, "Alloc %d ceqs, less than required %d ceqs\n",
- *act_num, num);
+ *act_num, num);
mutex_unlock(&eq->eq_mutex);
return 0;
}
@@ -1322,15 +1350,16 @@ static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd,
void *buf_in,
dev_cap->nic_max_sq = dev_cap_tmp.nic_max_sq + 1;
dev_cap->nic_max_rq = dev_cap_tmp.nic_max_rq + 1;
- sdk_info(dev->dev_hdl, "func_id(%u) fixed qnum %u\n",
- func_id, dev_cap->nic_max_sq);
+ dev_cap->max_queue_allowed = dev_cap_tmp.max_queue_allowed;
+ sdk_info(dev->dev_hdl, "func_id(%u) fixed qnum %u max_queue_allowed %u\n",
+ func_id, dev_cap->nic_max_sq, dev_cap->max_queue_allowed);
return 0;
}
static int cfg_mbx_ppf_proc_msg(void *hwdev, u16 pf_id, u16 vf_id, u8 cmd,
- void *buf_in, u16 in_size, void *buf_out,
- u16 *out_size)
+ void *buf_in, u16 in_size, void *buf_out,
+ u16 *out_size)
{
struct hinic_hwdev *dev = hwdev;
@@ -1343,7 +1372,7 @@ static int cfg_mbx_ppf_proc_msg(void *hwdev, u16 pf_id, u16 vf_id,
u8 cmd,
}
static int cfg_mbx_vf_proc_msg(void *hwdev, u8 cmd, void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size)
+ void *buf_out, u16 *out_size)
{
struct hinic_hwdev *dev = hwdev;
@@ -1734,6 +1763,32 @@ bool hinic_func_for_mgmt(void *hwdev)
return true;
}
+bool hinic_func_for_hwpt(void *hwdev)
+{
+ struct hinic_hwdev *dev = hwdev;
+
+ if (!hwdev)
+ return false;
+
+ if (IS_HWPT_TYPE(dev))
+ return true;
+ else
+ return false;
+}
+
+bool hinic_func_for_pt(void *hwdev)
+{
+ struct hinic_hwdev *dev = hwdev;
+
+ if (!hwdev)
+ return false;
+
+ if (dev->cfg_mgmt->svc_cap.force_up)
+ return true;
+ else
+ return false;
+}
+
int cfg_set_func_sf_en(void *hwdev, u32 enbits, u32 enmask)
{
struct hinic_hwdev *dev = hwdev;
@@ -1750,10 +1805,15 @@ int cfg_set_func_sf_en(void *hwdev, u32 enbits, u32 enmask)
return -ENOMEM;
}
- glb_func_idx = hinic_global_func_id(hwdev);
- func_sf_enbits->function_id = glb_func_idx;
+ err = hinic_global_func_id_get(dev, &glb_func_idx);
+ if (err) {
+ kfree(func_sf_enbits);
+ return err;
+ }
+
func_sf_enbits->stateful_enbits = enbits;
func_sf_enbits->stateful_enmask = enmask;
+ func_sf_enbits->function_id = glb_func_idx;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
HINIC_MISC_SET_FUNC_SF_ENBITS,
@@ -1788,7 +1848,11 @@ int cfg_get_func_sf_en(void *hwdev, u32 *enbits)
return -ENOMEM;
}
- glb_func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(dev, &glb_func_idx);
+ if (err) {
+ kfree(func_sf_enbits);
+ return err;
+ }
func_sf_enbits->function_id = glb_func_idx;
@@ -2056,7 +2120,9 @@ static int hinic_os_dep_init(struct hinic_hwdev *hwdev)
static void hinic_os_dep_deinit(struct hinic_hwdev *hwdev)
{
destroy_work(&hwdev->fault_work);
+
destroy_workqueue(hwdev->workq);
+
down(&hwdev->fault_list_sem);
up(&hwdev->fault_list_sem);
@@ -2068,7 +2134,6 @@ static void hinic_os_dep_deinit(struct hinic_hwdev *hwdev)
void hinic_ppf_hwdev_unreg(void *hwdev)
{
struct hinic_hwdev *dev = hwdev;
-
if (!hwdev)
return;
@@ -2082,7 +2147,6 @@ void hinic_ppf_hwdev_unreg(void *hwdev)
void hinic_ppf_hwdev_reg(void *hwdev, void *ppf_hwdev)
{
struct hinic_hwdev *dev = hwdev;
-
if (!hwdev)
return;
@@ -2149,6 +2213,8 @@ int hinic_init_hwdev(struct hinic_init_para *para)
hwdev->chip_node = para->chip_node;
hwdev->ppf_hwdev = para->ppf_hwdev;
sema_init(&hwdev->ppf_sem, 1);
+ sema_init(&hwdev->func_sem, 1);
+ hwdev->func_ref = 0;
hwdev->chip_fault_stats = vzalloc(HINIC_CHIP_FAULT_SIZE);
if (!hwdev->chip_fault_stats)
@@ -2208,6 +2274,9 @@ int hinic_init_hwdev(struct hinic_init_para *para)
goto init_cap_err;
}
+ if (hwdev->cfg_mgmt->svc_cap.force_up)
+ hwdev->feature_cap |= HINIC_FUNC_FORCE_LINK_UP;
+
err = __vf_func_init(hwdev);
if (err)
goto vf_func_init_err;
@@ -2244,6 +2313,7 @@ int hinic_init_hwdev(struct hinic_init_para *para)
vfree(hwdev->chip_fault_stats);
alloc_chip_fault_stats_err:
+ sema_deinit(&hwdev->func_sem);
sema_deinit(&hwdev->ppf_sem);
kfree(hwdev);
*para->hwdev = NULL;
@@ -2251,6 +2321,33 @@ int hinic_init_hwdev(struct hinic_init_para *para)
return -EFAULT;
}
+/**
+ * hinic_set_vf_dev_cap - Set max queue num for VF
+ * @hwdev: the HW device for VF
+ **/
+int hinic_set_vf_dev_cap(void *hwdev)
+{
+ int err;
+ struct hinic_hwdev *dev;
+ enum func_type type;
+
+ if (!hwdev)
+ return -EFAULT;
+
+ dev = (struct hinic_hwdev *)hwdev;
+ type = HINIC_FUNC_TYPE(dev);
+ if (type != TYPE_VF)
+ return -EPERM;
+
+ err = get_dev_cap(dev);
+ if (err)
+ return err;
+
+ nic_param_fix(dev);
+
+ return 0;
+}
+
void hinic_free_hwdev(void *hwdev)
{
struct hinic_hwdev *dev = hwdev;
@@ -2287,6 +2384,7 @@ void hinic_free_hwdev(void *hwdev)
clear_bit(HINIC_HWDEV_NONE_INITED, &dev->func_state);
hinic_free_hwif(dev);
vfree(dev->chip_fault_stats);
+ sema_deinit(&dev->func_sem);
sema_deinit(&dev->ppf_sem);
kfree(dev);
}
@@ -2337,6 +2435,7 @@ enum hinic_func_mode hinic_get_func_mode(void *hwdev)
return dev->func_mode;
}
+EXPORT_SYMBOL(hinic_get_func_mode);
enum hinic_service_mode hinic_get_service_mode(void *hwdev)
{
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cfg.h
b/drivers/net/ethernet/huawei/hinic/hinic_cfg.h
index 55d038335f3c..8ca07640d4c0 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_cfg.h
@@ -222,6 +222,7 @@ struct service_cap {
u8 er_id; /* PF/VF's ER */
u8 port_id; /* PF/VF's physical port */
u8 max_vf; /* max VF number that PF supported */
+ u8 force_up;
bool sf_en; /* stateful business status */
u8 timer_en; /* 0:disable, 1:enable */
u8 bloomfilter_en; /* 0:disable, 1:enable*/
@@ -363,7 +364,7 @@ struct hinic_dev_cap {
u8 cfg_file_ver;
u8 net_port_mode;
u8 valid_cos_bitmap; /* every bit indicate cos is valid */
- u8 rsvd1;
+ u8 force_up;
u32 pf_num;
u32 pf_id_start;
u32 vf_num;
@@ -386,7 +387,7 @@ struct hinic_dev_cap {
u8 nic_lro_en;
u8 nic_lro_sz;
u8 nic_tso_sz;
- u8 rsvd3;
+ u8 max_queue_allowed;
/* RoCE */
u32 roce_max_qp;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cmdq.c
b/drivers/net/ethernet/huawei/hinic/hinic_cmdq.c
index e9f9f0a392ab..3f52123be4af 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_cmdq.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_cmdq.c
@@ -53,7 +53,7 @@
#define CMDQ_DB_INFO_SRC_TYPE_MASK 0x1FU
#define CMDQ_DB_INFO_SET(val, member) \
- (((val) & CMDQ_DB_INFO_##member##_MASK) \
+ ((val & CMDQ_DB_INFO_##member##_MASK) \
<< CMDQ_DB_INFO_##member##_SHIFT)
#define CMDQ_CTRL_PI_SHIFT 0
@@ -168,7 +168,7 @@
#define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3)
#define CMDQ_DB_ADDR(db_base, pi) \
- (((u8 *)(db_base) + HINIC_DB_OFF) + CMDQ_DB_PI_OFF(pi))
+ (((u8 *)db_base + HINIC_DB_OFF) + CMDQ_DB_PI_OFF(pi))
#define CMDQ_PFN_SHIFT 12
#define CMDQ_PFN(addr) ((addr) >> CMDQ_PFN_SHIFT)
@@ -194,6 +194,9 @@
#define CMDQ_SEND_CMPT_CODE 10
#define CMDQ_COMPLETE_CMPT_CODE 11
+#define HINIC_GET_CMDQ_FREE_WQEBBS(cmdq_wq) \
+ atomic_read(&(cmdq_wq)->delta)
+
enum cmdq_scmd_type {
CMDQ_SET_ARM_CMD = 2,
};
@@ -278,7 +281,7 @@ void hinic_free_cmd_buf(void *hwdev, struct hinic_cmd_buf *cmd_buf)
struct hinic_cmdqs *cmdqs;
if (!hwdev || !cmd_buf) {
- pr_err("Failed to free cmd buf.\n");
+ pr_err("Failed to free cmd buf\n");
return;
}
@@ -337,7 +340,7 @@ static void cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd *wqe,
}
static void cmdq_set_inline_wqe_data(struct hinic_cmdq_inline_wqe *wqe,
- void *buf_in, u32 in_size)
+ const void *buf_in, u32 in_size)
{
struct hinic_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd;
@@ -368,7 +371,7 @@ static void cmdq_set_db(struct hinic_cmdq *cmdq,
writel(db.db_info, CMDQ_DB_ADDR(cmdq->db_base, prod_idx));
}
-static void cmdq_wqe_fill(void *dst, void *src)
+static void cmdq_wqe_fill(void *dst, const void *src)
{
memcpy((u8 *)dst + FIRST_DATA_TO_WRITE_LAST,
(u8 *)src + FIRST_DATA_TO_WRITE_LAST,
@@ -541,8 +544,9 @@ static int hinic_cmdq_sync_timeout_check(struct hinic_cmdq *cmdq,
return 0;
}
-static void __clear_cmd_info(struct hinic_cmdq_cmd_info *cmd_info, int *errcode,
- struct completion *done, u64 *out_param)
+static void __clear_cmd_info(struct hinic_cmdq_cmd_info *cmd_info,
+ const int *errcode, struct completion *done,
+ u64 *out_param)
{
if (cmd_info->errcode == errcode)
cmd_info->errcode = NULL;
@@ -576,10 +580,20 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,
/* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */
spin_lock_bh(&cmdq->cmdq_lock);
- /* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow*/
+ /* in order to save a wqebb for setting arm_bit when
+ * send cmdq commands frequently resulting in cmdq full
+ */
+ if (HINIC_GET_CMDQ_FREE_WQEBBS(wq) < num_wqebbs + 1) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ return -EBUSY;
+ }
+
+ /* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow */
curr_wqe = hinic_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
if (!curr_wqe) {
spin_unlock_bh(&cmdq->cmdq_lock);
+ sdk_err(cmdq->hwdev->dev_hdl, "Can not get avalible wqebb, mod: %u, cmd:
0x%x\n",
+ mod, cmd);
return -EBUSY;
}
@@ -696,10 +710,20 @@ static int cmdq_sync_cmd_detail_resp(struct hinic_cmdq *cmdq,
/* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */
spin_lock_bh(&cmdq->cmdq_lock);
+ /* in order to save a wqebb for setting arm_bit when
+ * send cmdq commands frequently resulting in cmdq full
+ */
+ if (HINIC_GET_CMDQ_FREE_WQEBBS(wq) < num_wqebbs + 1) {
+ spin_unlock_bh(&cmdq->cmdq_lock);
+ return -EBUSY;
+ }
+
/* WQE_SIZE = WQEBB_SIZE, we will get the wq element and not shadow*/
curr_wqe = hinic_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
if (!curr_wqe) {
spin_unlock_bh(&cmdq->cmdq_lock);
+ sdk_err(cmdq->hwdev->dev_hdl, "Can not get avalible wqebb, mod: %u, cmd:
0x%x\n",
+ mod, cmd);
return -EBUSY;
}
@@ -716,6 +740,7 @@ static int cmdq_sync_cmd_detail_resp(struct hinic_cmdq *cmdq,
cmd_info = &cmdq->cmd_infos[curr_prod_idx];
init_completion(&done);
+
cmd_info->done = &done;
cmd_info->errcode = &errcode;
cmd_info->cmpt_code = &cmpt_code;
@@ -856,6 +881,7 @@ static int cmdq_set_arm_bit(struct hinic_cmdq *cmdq, void *buf_in, u16
in_size)
curr_wqe = hinic_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
if (!curr_wqe) {
spin_unlock_bh(&cmdq->cmdq_lock);
+ sdk_err(cmdq->hwdev->dev_hdl, "Can not get avalible wqebb setting
arm\n");
return -EBUSY;
}
@@ -946,9 +972,13 @@ int hinic_cmdq_direct_resp(void *hwdev, enum hinic_ack_type
ack_type,
return err;
}
+ err = hinic_func_own_get(hwdev);
+ if (err)
+ return err;
+
err = cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC_CMDQ_SYNC], ack_type,
mod, cmd, buf_in, out_param, timeout);
-
+ hinic_func_own_free(hwdev);
if (!(((struct hinic_hwdev *)hwdev)->chip_present_flag))
return -ETIMEDOUT;
else
@@ -1109,7 +1139,8 @@ static void cmdq_sync_cmd_handler(struct hinic_cmdq *cmdq,
cmdq_update_cmd_status(cmdq, prod_idx, wqe);
if (cmdq->cmd_infos[prod_idx].cmpt_code) {
- *cmdq->cmd_infos[prod_idx].cmpt_code = CMDQ_COMPLETE_CMPT_CODE;
+ *cmdq->cmd_infos[prod_idx].cmpt_code =
+ CMDQ_COMPLETE_CMPT_CODE;
cmdq->cmd_infos[prod_idx].cmpt_code = NULL;
}
@@ -1267,7 +1298,7 @@ static void cmdq_init_queue_ctxt(struct hinic_cmdq *cmdq,
ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) |
CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN);
- cmdq_ctxt->func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);
+ cmdq_ctxt->func_idx = hinic_global_func_id_hw(hwdev);
cmdq_ctxt->ppf_idx = HINIC_HWIF_PPF_IDX(hwdev->hwif);
cmdq_ctxt->cmdq_id = cmdq->cmdq_type;
}
@@ -1348,6 +1379,7 @@ int hinic_set_cmdq_ctxts(struct hinic_hwdev *hwdev)
cmdq_type = HINIC_CMDQ_SYNC;
for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
cmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;
+ cmdq_ctxt->func_idx = hinic_global_func_id_hw(hwdev);
in_size = sizeof(*cmdq_ctxt);
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
HINIC_MGMT_CMD_CMDQ_CTXT_SET,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ctx_def.h
b/drivers/net/ethernet/huawei/hinic/hinic_ctx_def.h
index 0b61e22501b5..71ccb1f17044 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ctx_def.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ctx_def.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0*/
/******************************************************************************
- *
- * Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
- *
+
+ Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
+
******************************************************************************
File Name : hinic_ctx_def.h
Version : Initial Draft
@@ -33,6 +33,8 @@ extern "C"{
#define HINIC_Q_CTXT_MAX 42
+#define HINIC_RQ_CQ_MAX 128
+
#define MAX_WQE_SIZE(max_sge, wqebb_size) \
(((max_sge) <= 2) ? (wqebb_size) : \
((ALIGN(((max_sge) - 2), 4) / 4 + 1) * (wqebb_size)))
@@ -214,6 +216,7 @@ enum cfg_svc_type_en {
CFG_SVC_OVS_BIT7 = (1 << 7),
CFG_SVC_ACL_BIT8 = (1 << 8),
CFG_SVC_IOE_BIT9 = (1 << 9),
+ CFG_SVC_HWPT_BIT10 = (1 << 10),
CFG_SVC_FT_EN = (CFG_SVC_FCOE_BIT2 | CFG_SVC_TOE_BIT3 |
CFG_SVC_FC_BIT5 | CFG_SVC_IOE_BIT9),
@@ -244,6 +247,8 @@ enum cfg_svc_type_en {
((dev)->cfg_mgmt->svc_cap.chip_svc_type & CFG_SVC_FT_EN)
#define IS_RDMA_TYPE(dev) \
((dev)->cfg_mgmt->svc_cap.chip_svc_type & CFG_SVC_RDMA_EN)
+#define IS_HWPT_TYPE(dev) \
+ ((dev)->cfg_mgmt->svc_cap.chip_svc_type & CFG_SVC_HWPT_BIT10)
#ifdef __cplusplus
#if __cplusplus
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dbg.h
b/drivers/net/ethernet/huawei/hinic/hinic_dbg.h
index bfc6aa4440af..f87bedfc113e 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dbg.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dbg.h
@@ -39,7 +39,7 @@ u64 hinic_dbg_get_rq_cla_addr(void *hwdev, u16 q_id);
int hinic_dbg_get_sq_db_addr(void *hwdev, u16 q_id, u64 **map_addr,
u64 *phy_addr, u32 *pg_idx);
-u16 hinic_dbg_get_global_qpn(void *hwdev);
+u16 hinic_dbg_get_global_qpn(const void *hwdev);
int hinic_dbg_get_sq_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt,
u8 *wqe, u16 *wqe_size);
@@ -79,11 +79,12 @@ int hinic_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val);
int hinic_api_csr_rd64(void *hwdev, u8 dest, u32 addr, u64 *val);
-int hinic_dbg_get_hw_stats(void *hwdev, u8 *hw_stats, u16 *out_size);
+int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size);
u16 hinic_dbg_clear_hw_stats(void *hwdev);
-void hinic_get_chip_fault_stats(void *hwdev, u8 *chip_fault_stats, int offset);
+void hinic_get_chip_fault_stats(const void *hwdev,
+ u8 *chip_fault_stats, int offset);
int hinic_dbg_get_pf_bw_limit(void *hwdev, u32 *pf_bw_limit);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
b/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
index 96fb8db66656..0cf65bfde2de 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
@@ -53,13 +53,9 @@ struct ffm_intr_info {
void *g_card_node_array[MAX_CARD_NUM] = {0};
void *g_card_vir_addr[MAX_CARD_NUM] = {0};
u64 g_card_phy_addr[MAX_CARD_NUM] = {0};
-/* lock for g_card_vir_addr */
+/* lock for g_card_vir_addr */
struct mutex g_addr_lock;
int card_id;
-unsigned long card_id_flag;
-enum hinic_card_id_status {
- HINIC_CARD_ID_USE = BIT(0),
-};
/* dbgtool character device name, class name, dev path*/
#define CHR_DEV_DBGTOOL "dbgtool_chr_dev"
@@ -111,7 +107,7 @@ static ssize_t dbgtool_knl_write(struct file *pfile,
static bool is_valid_phy_addr(u64 offset)
{
- int i = 0;
+ int i;
for (i = 0; i < MAX_CARD_NUM; i++) {
if (offset == g_card_phy_addr[i])
@@ -129,20 +125,17 @@ int hinic_mem_mmap(struct file *filp, struct vm_area_struct *vma)
if (vmsize > (PAGE_SIZE * (1 << DBGTOOL_PAGE_ORDER))) {
pr_err("Map size = %lu is bigger than alloc\n", vmsize);
- clear_bit(HINIC_CARD_ID_USE, &card_id_flag);
return -EAGAIN;
}
if (offset && !is_valid_phy_addr((u64)offset) &&
!hinic_is_valid_bar_addr((u64)offset)) {
- pr_err("offset is invalid\n");
- clear_bit(HINIC_CARD_ID_USE, &card_id_flag);
+ pr_err("offset is invalid");
return -EAGAIN;
}
/* old version of tool set vma->vm_pgoff to 0 */
phy_addr = offset ? offset : g_card_phy_addr[card_id];
- clear_bit(HINIC_CARD_ID_USE, &card_id_flag);
if (!phy_addr) {
pr_err("Card_id = %d physical address is 0\n", card_id);
return -EAGAIN;
@@ -200,9 +193,10 @@ long dbgtool_knl_api_cmd_read(struct dbgtool_param *para,
ack_size = para->param.api_rd.ack_size;
if (para->param.api_rd.ack_size == 0) {
pr_err("Read cmd ack size is 0\n");
- ret = -EINVAL;
+ ret = -ENOMEM;
goto alloc_ack_mem_fail;
}
+
ack = kzalloc((unsigned long long)ack_size, GFP_KERNEL);
if (!ack) {
pr_err("Alloc read ack mem fail\n");
@@ -557,7 +551,7 @@ long dbgtool_knl_unlocked_ioctl(struct file *pfile,
struct dbgtool_param param;
struct dbgtool_k_glb_info *dbgtool_info;
struct card_node *card_info = NULL;
- int i, cnt = 0;
+ int i;
(void)memset(¶m, 0, sizeof(param));
@@ -580,20 +574,7 @@ long dbgtool_knl_unlocked_ioctl(struct file *pfile,
return -EFAULT;
}
- while (cnt < 10) {
- if (!test_and_set_bit(HINIC_CARD_ID_USE, &card_id_flag))
- break;
- usleep_range(500, 1000);
- cnt++;
- }
-
- if (cnt < 10) {
- card_id = i;
- } else {
- pr_err("Card id in using!\n");
- clear_bit(HINIC_CARD_ID_USE, &card_id_flag);
- return -EFAULT;
- }
+ card_id = i;
dbgtool_info = (struct dbgtool_k_glb_info *)card_info->dbgtool_info;
@@ -651,6 +632,7 @@ void ffm_intr_msg_record(void *handle, void *buf_in, u16 in_size,
struct timex txc;
struct rtc_time rctm;
struct card_node *card_info = NULL;
+ bool flag = false;
int i, j;
for (i = 0; i < MAX_CARD_NUM; i++) {
@@ -659,10 +641,14 @@ void ffm_intr_msg_record(void *handle, void *buf_in, u16 in_size,
continue;
for (j = 0; j < MAX_FUNCTION_NUM; j++) {
- if (handle == card_info->func_handle_array[j])
+ if (handle == card_info->func_handle_array[j]) {
+ flag = true;
break;
+ }
}
- break;
+
+ if (flag)
+ break;
}
if (i == MAX_CARD_NUM || !card_info) {
@@ -787,6 +773,7 @@ int dbgtool_knl_init(void *vhwdev, void *chip_node)
pr_err("Failed to get hinic id\n");
goto sscanf_chdev_fail;
}
+
g_card_node_array[id] = chip_info;
chip_info->func_num++;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.h
b/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.h
index 833d3fd60d51..33aaca1eb734 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.h
@@ -118,4 +118,5 @@ int hinic_mem_mmap(struct file *filp, struct vm_area_struct *vma);
void chipif_get_all_pf_dev_info(struct pf_dev_info *dev_info, int card_id,
void **g_func_handle_array);
long dbgtool_knl_free_mem(int id);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dcb.c
b/drivers/net/ethernet/huawei/hinic/hinic_dcb.c
index 0d1bb2a7ed48..8f80a8f240a3 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dcb.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dcb.c
@@ -120,6 +120,8 @@ void hinic_init_ieee_settings(struct hinic_nic_dev *nic_dev)
if (dcb_cfg->tc_cfg[i].pfc_en)
pfc->pfc_en |= (u8)BIT(i);
}
+
+ return;
}
static int hinic_set_up_cos_map(struct hinic_nic_dev *nic_dev,
@@ -330,6 +332,41 @@ int hinic_setup_tc(struct net_device *netdev, u8 tc)
return 0;
}
+u8 hinic_setup_dcb_tool(struct net_device *netdev, u8 *dcb_en, bool wr_flag)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ int err = 0;
+
+ if (wr_flag) {
+ if (nic_dev->max_qps < nic_dev->dcb_cfg.pg_tcs && *dcb_en) {
+ netif_err(nic_dev, drv, netdev,
+ "max_qps:%d is less than %d\n",
+ nic_dev->max_qps, nic_dev->dcb_cfg.pg_tcs);
+ return 1;
+ }
+ if (*dcb_en)
+ set_bit(HINIC_DCB_ENABLE, &nic_dev->flags);
+ else
+ clear_bit(HINIC_DCB_ENABLE, &nic_dev->flags);
+ /*hinic_setup_tc need get the nic_mutex lock again */
+ mutex_unlock(&nic_dev->nic_mutex);
+ /* kill the rtnl assert warning */
+ rtnl_lock();
+ err = hinic_setup_tc(netdev,
+ *dcb_en ? nic_dev->dcb_cfg.pg_tcs : 0);
+ rtnl_unlock();
+ mutex_lock(&nic_dev->nic_mutex);
+
+ if (!err)
+ netif_info(nic_dev, drv, netdev, "%s DCB\n",
+ *dcb_en ? "Enable" : "Disable");
+ } else {
+ *dcb_en = (u8)test_bit(HINIC_DCB_ENABLE, &nic_dev->flags);
+ }
+
+ return !!err;
+}
+
static u8 hinic_dcbnl_get_state(struct net_device *netdev)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
@@ -349,6 +386,13 @@ static u8 hinic_dcbnl_set_state(struct net_device *netdev, u8 state)
if (state == curr_state)
return 0;
+ if (nic_dev->max_qps < nic_dev->dcb_cfg.pg_tcs && state) {
+ netif_err(nic_dev, drv, netdev,
+ "max_qps:%d is less than %d\n",
+ nic_dev->max_qps, nic_dev->dcb_cfg.pg_tcs);
+ return 1;
+ }
+
err = hinic_setup_tc(netdev, state ? nic_dev->dcb_cfg.pg_tcs : 0);
if (!err)
netif_info(nic_dev, drv, netdev, "%s DCB\n",
@@ -370,6 +414,58 @@ static void hinic_dcbnl_get_perm_hw_addr(struct net_device *netdev,
nicif_err(nic_dev, drv, netdev, "Failed to get default mac\n");
}
+void hinic_dcbnl_set_ets_tc_tool(struct net_device *netdev, u8 tc[], bool flag)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_tc_cfg *cfg = nic_dev->tmp_dcb_cfg.tc_cfg;
+ struct hinic_tc_cfg *tc_conf = nic_dev->dcb_cfg.tc_cfg;
+ u8 i, tc_tmp, j;
+
+ if (flag) {
+ /*need to clear first */
+ for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
+ cfg[i].path[HINIC_DCB_CFG_TX].up_map = 0;
+ cfg[i].path[HINIC_DCB_CFG_RX].up_map = 0;
+ }
+ for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
+ tc_tmp = tc[i];
+ cfg[tc_tmp].path[HINIC_DCB_CFG_TX].up_map |= (u8)BIT(i);
+ cfg[tc_tmp].path[HINIC_DCB_CFG_RX].up_map |= (u8)BIT(i);
+ cfg[tc_tmp].path[HINIC_DCB_CFG_TX].pg_id = (u8)tc_tmp;
+ cfg[tc_tmp].path[HINIC_DCB_CFG_RX].pg_id = (u8)tc_tmp;
+ }
+ } else {
+ for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
+ for (j = 0; j < HINIC_DCB_TC_MAX; j++) {
+ if (tc_conf[i].path[HINIC_DCB_CFG_TX].up_map &
+ (u8)BIT(j)) {
+ tc[j] = i;
+ }
+ }
+ }
+ }
+}
+
+void hinic_dcbnl_set_ets_pecent_tool(struct net_device *netdev,
+ u8 percent[], bool flag)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ int i;
+
+ if (flag) {
+ for (i = 0; i < HINIC_DCB_COS_MAX; i++) {
+ nic_dev->tmp_dcb_cfg.bw_pct[HINIC_DCB_CFG_TX][i] =
+ percent[i];
+ nic_dev->tmp_dcb_cfg.bw_pct[HINIC_DCB_CFG_RX][i] =
+ percent[i];
+ }
+ } else {
+ for (i = 0; i < HINIC_DCB_COS_MAX; i++)
+ percent[i] =
+ nic_dev->dcb_cfg.bw_pct[HINIC_DCB_CFG_TX][i];
+ }
+}
+
static void hinic_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
u8 prio, u8 pg_id, u8 bw_pct,
u8 up_map)
@@ -460,6 +556,69 @@ static void hinic_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev,
int bwg_id,
*bw_pct = nic_dev->dcb_cfg.bw_pct[1][bwg_id];
}
+void hinic_dcbnl_set_pfc_cfg_tool(struct net_device *netdev, u8 setting)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ u8 i;
+
+ for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
+ nic_dev->tmp_dcb_cfg.tc_cfg[i].pfc_en = !!(setting & BIT(i));
+ if (nic_dev->tmp_dcb_cfg.tc_cfg[i].pfc_en !=
+ nic_dev->dcb_cfg.tc_cfg[i].pfc_en) {
+ nic_dev->tmp_dcb_cfg.pfc_state = true;
+ }
+ }
+}
+
+void hinic_dcbnl_set_ets_strict_tool(struct net_device *netdev,
+ u8 *setting, bool flag)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_tc_cfg *cfg = nic_dev->tmp_dcb_cfg.tc_cfg;
+ struct hinic_tc_cfg *conf = nic_dev->dcb_cfg.tc_cfg;
+ u8 i;
+
+ if (flag) {
+ for (i = 0; i < HINIC_DCB_COS_MAX; i++) {
+ cfg[i].path[HINIC_DCB_CFG_TX].prio_type =
+ !!(*setting & BIT(i)) ? 2 : 0;
+ cfg[i].path[HINIC_DCB_CFG_RX].prio_type =
+ !!(*setting & BIT(i)) ? 2 : 0;
+ }
+ } else {
+ for (i = 0; i < HINIC_DCB_COS_MAX; i++) {
+ *setting = *setting |
+ (u8)((u32)(!!(conf[i].path[0].prio_type)) << i);
+ }
+ }
+}
+
+void hinic_dcbnl_set_pfc_en_tool(struct net_device *netdev,
+ u8 *value, bool flag)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+
+ if (flag)
+ nic_dev->tmp_dcb_cfg.pfc_state = !!(*value);
+ else
+ *value = !!nic_dev->tmp_dcb_cfg.pfc_state;
+}
+
+void hinic_dcbnl_set_ets_en_tool(struct net_device *netdev,
+ u8 *value, bool flag)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+
+ if (flag) {
+ if (*value)
+ set_bit(HINIC_ETS_ENABLE, &nic_dev->flags);
+ else
+ clear_bit(HINIC_ETS_ENABLE, &nic_dev->flags);
+ } else {
+ *value = (u8)test_bit(HINIC_ETS_ENABLE, &nic_dev->flags);
+ }
+}
+
static void hinic_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
u8 setting)
{
@@ -471,6 +630,24 @@ static void hinic_dcbnl_set_pfc_cfg(struct net_device *netdev, int
prio,
nic_dev->tmp_dcb_cfg.pfc_state = true;
}
+void hinic_dcbnl_get_pfc_cfg_tool(struct net_device *netdev, u8 *setting)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ u8 i;
+
+ for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
+ *setting = *setting |
+ (u8)((u32)(nic_dev->dcb_cfg.tc_cfg[i].pfc_en) << i);
+ }
+}
+
+void hinic_dcbnl_get_tc_num_tool(struct net_device *netdev, u8 *tc_num)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+
+ *tc_num = nic_dev->max_cos;
+}
+
static void hinic_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
u8 *setting)
{
@@ -598,7 +775,7 @@ static u8 hinic_sync_dcb_cfg(struct hinic_nic_dev *nic_dev)
static void hinic_dcb_get_pfc_map(struct hinic_nic_dev *nic_dev,
struct hinic_dcb_config *dcb_cfg, u8 *pfc_map)
{
- int i, up;
+ u8 i, up;
u8 pfc_en = 0, outof_range_pfc = 0;
for (i = 0; i < dcb_cfg->pfc_tcs; i++) {
@@ -624,7 +801,7 @@ static void hinic_dcb_get_pfc_map(struct hinic_nic_dev *nic_dev,
static bool is_cos_in_use(u8 cos, u8 up_valid_bitmap, u8 *up_cos)
{
- int i;
+ u32 i;
for (i = 0; i < HINIC_DCB_UP_MAX; i++) {
if (!(up_valid_bitmap & BIT(i)))
@@ -869,6 +1046,52 @@ static int __set_hw_ets(struct hinic_nic_dev *nic_dev)
return 0;
}
+u8 hinic_dcbnl_set_ets_tool(struct net_device *netdev)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ u8 state = DCB_HW_CFG_CHG;
+ int err;
+
+ nic_dev->dcb_changes |= hinic_sync_dcb_cfg(nic_dev);
+ if (!nic_dev->dcb_changes)
+ return DCB_HW_CFG_CHG;
+
+ err = hinic_stop_port_traffic_flow(nic_dev);
+ if (err)
+ return DCB_HW_CFG_ERR;
+ /* wait all traffic flow stopped */
+ if (netdev->reg_state == NETREG_REGISTERED)
+ msleep(HINIC_WAIT_PORT_IO_STOP);
+
+ if (nic_dev->dcb_changes & DCB_CFG_CHG_UP_COS) {
+ err = __set_hw_cos_up_map(nic_dev);
+ if (err) {
+ hinic_info(nic_dev, drv,
+ "Set cos_up map to hardware failed\n");
+ state = DCB_HW_CFG_ERR;
+ goto out;
+ }
+
+ nic_dev->dcb_changes &= (~DCB_CFG_CHG_UP_COS);
+ }
+
+ if (nic_dev->dcb_changes & (DCB_CFG_CHG_PG_TX | DCB_CFG_CHG_PG_RX)) {
+ err = __set_hw_ets(nic_dev);
+ if (err) {
+ state = DCB_HW_CFG_ERR;
+ goto out;
+ }
+
+ nic_dev->dcb_changes &=
+ (~(DCB_CFG_CHG_PG_TX | DCB_CFG_CHG_PG_RX));
+ }
+
+out:
+ hinic_start_port_traffic_flow(nic_dev);
+
+ return state;
+}
+
static int hinic_dcbnl_set_df_ieee_cfg(struct net_device *netdev)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
@@ -910,7 +1133,44 @@ static int hinic_dcbnl_set_df_ieee_cfg(struct net_device *netdev)
hinic_start_port_traffic_flow(nic_dev);
- return (err1 | err2) ? -EINVAL : 0;
+ return (err1 || err2) ? -EINVAL : 0;
+}
+
+u8 hinic_dcbnl_set_pfc_tool(struct net_device *netdev)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_dcb_config *dcb_cfg = &nic_dev->dcb_cfg;
+ u8 state = DCB_HW_CFG_CHG;
+ int err;
+
+ nic_dev->dcb_changes |= hinic_sync_dcb_cfg(nic_dev);
+ if (!nic_dev->dcb_changes)
+ return DCB_HW_CFG_CHG;
+
+ if (nic_dev->dcb_changes & DCB_CFG_CHG_PFC) {
+ u8 pfc_map = 0;
+
+ hinic_dcb_get_pfc_map(nic_dev, dcb_cfg, &pfc_map);
+ err = hinic_dcb_set_pfc(nic_dev->hwdev, dcb_cfg->pfc_state,
+ pfc_map);
+ if (err) {
+ hinic_info(nic_dev, drv, "Failed to %s PFC\n",
+ dcb_cfg->pfc_state ? "enable" : "disable");
+ state = DCB_HW_CFG_ERR;
+ goto out;
+ }
+
+ if (dcb_cfg->pfc_state)
+ hinic_info(nic_dev, drv, "Set PFC: 0x%x to hw done\n",
+ pfc_map);
+ else
+ hinic_info(nic_dev, drv, "Disable PFC, enable tx/rx pause\n");
+
+ nic_dev->dcb_changes &= (~DCB_CFG_CHG_PFC);
+ }
+out:
+
+ return state;
}
u8 hinic_dcbnl_set_all(struct net_device *netdev)
@@ -986,7 +1246,7 @@ u8 hinic_dcbnl_set_all(struct net_device *netdev)
}
static int hinic_dcbnl_ieee_get_ets(struct net_device *netdev,
- struct ieee_ets *ets)
+ struct ieee_ets *ets)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
struct ieee_ets *my_ets = &nic_dev->hinic_ieee_ets;
@@ -1001,7 +1261,7 @@ static int hinic_dcbnl_ieee_get_ets(struct net_device *netdev,
}
static int hinic_dcbnl_ieee_set_ets(struct net_device *netdev,
- struct ieee_ets *ets)
+ struct ieee_ets *ets)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
struct hinic_dcb_config *dcb_cfg = &nic_dev->dcb_cfg;
@@ -1067,7 +1327,7 @@ static int hinic_dcbnl_ieee_set_ets(struct net_device *netdev,
}
static int hinic_dcbnl_ieee_get_pfc(struct net_device *netdev,
- struct ieee_pfc *pfc)
+ struct ieee_pfc *pfc)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
struct ieee_pfc *my_pfc = &nic_dev->hinic_ieee_pfc;
@@ -1079,7 +1339,7 @@ static int hinic_dcbnl_ieee_get_pfc(struct net_device *netdev,
}
static int hinic_dcbnl_ieee_set_pfc(struct net_device *netdev,
- struct ieee_pfc *pfc)
+ struct ieee_pfc *pfc)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
struct hinic_dcb_config *dcb_cfg = &nic_dev->dcb_cfg;
@@ -1206,7 +1466,6 @@ static u8 hinic_dcbnl_setdcbx(struct net_device *netdev, u8 mode)
if (nic_dev->dcbx_cap == mode)
return 0;
-
nic_dev->dcbx_cap = mode;
if (mode & DCB_CAP_DCBX_VER_CEE) {
@@ -1224,7 +1483,9 @@ static u8 hinic_dcbnl_setdcbx(struct net_device *netdev, u8 mode)
return 1;
}
}
+
hinic_dcbnl_set_df_ieee_cfg(netdev);
+ hinic_force_port_relink(nic_dev->hwdev);
} else {
err = hinic_setup_tc(netdev, 0);
if (err) {
@@ -1309,7 +1570,7 @@ void hinic_configure_dcb(struct net_device *netdev)
static bool __is_cos_up_map_change(struct hinic_nic_dev *nic_dev, u8 *cos_up)
{
- int cos, up;
+ u8 cos, up;
for (cos = 0; cos < nic_dev->max_cos; cos++) {
up = cos_up[cos];
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dcb.h
b/drivers/net/ethernet/huawei/hinic/hinic_dcb.h
index 0d6c0251d8da..056b722734c3 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dcb.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dcb.h
@@ -48,5 +48,20 @@ int hinic_get_num_cos(struct hinic_nic_dev *nic_dev, u8 *num_cos);
int hinic_get_cos_up_map(struct hinic_nic_dev *nic_dev,
u8 *num_cos, u8 *cos_up);
+u8 hinic_setup_dcb_tool(struct net_device *netdev, u8 *dcb_en, bool wr_flag);
+void hinic_dcbnl_set_pfc_en_tool(struct net_device *netdev,
+ u8 *value, bool flag);
+void hinic_dcbnl_set_pfc_cfg_tool(struct net_device *netdev, u8 setting);
+void hinic_dcbnl_get_pfc_cfg_tool(struct net_device *netdev, u8 *setting);
+u8 hinic_dcbnl_set_pfc_tool(struct net_device *netdev);
+void hinic_dcbnl_get_tc_num_tool(struct net_device *netdev, u8 *tc_num);
+void hinic_dcbnl_set_ets_tc_tool(struct net_device *netdev, u8 tc[], bool flag);
+void hinic_dcbnl_set_ets_pecent_tool(struct net_device *netdev,
+ u8 percent[], bool flag);
+void hinic_dcbnl_set_ets_en_tool(struct net_device *netdev,
+ u8 *value, bool flag);
+void hinic_dcbnl_set_ets_strict_tool(struct net_device *netdev,
+ u8 *setting, bool flag);
+u8 hinic_dcbnl_set_ets_tool(struct net_device *netdev);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h
b/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h
index ff993528ffaf..cb5fe472eb20 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0*/
/******************************************************************************
- *
- * Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
- *
+
+ Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
+
******************************************************************************
File Name : hinic_dfx_def.h
Version : Initial Draft
@@ -95,6 +95,14 @@ enum driver_cmd_type {
GET_NIC_STATS_STRING,
GET_NIC_STATS_INFO,
GET_PF_ID,
+ SET_DCB_CFG,
+ SET_PFC_PRIORITY,
+ GET_PFC_INFO,
+ SET_PFC_CONTROL,
+ SET_ETS,
+ GET_ETS_INFO,
+ GET_SUPPORT_UP,
+ GET_SUPPORT_TC,
RSS_CFG = 0x40,
RSS_INDIR,
@@ -121,9 +129,9 @@ enum api_chain_cmd_type {
};
enum sm_cmd_type {
-SM_CTR_RD32 = 1,
-SM_CTR_RD64_PAIR,
-SM_CTR_RD64
+ SM_CTR_RD32 = 1,
+ SM_CTR_RD64_PAIR,
+ SM_CTR_RD64
};
enum hinic_show_set {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_eqs.c
b/drivers/net/ethernet/huawei/hinic/hinic_eqs.c
index 3d6dbc700746..80650f8de8da 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_eqs.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_eqs.c
@@ -10,6 +10,7 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
@@ -35,15 +36,23 @@
#define HINIC_EQS_WQ_NAME "hinic_eqs"
#define AEQ_CTRL_0_INTR_IDX_SHIFT 0
+#define AEQ_CTRL_0_FUNC_BUSY_SHIFT 10
#define AEQ_CTRL_0_DMA_ATTR_SHIFT 12
#define AEQ_CTRL_0_PCI_INTF_IDX_SHIFT 20
+#define AEQ_CTRL_0_QPS_NUM_SHIFT 22
#define AEQ_CTRL_0_INTR_MODE_SHIFT 31
#define AEQ_CTRL_0_INTR_IDX_MASK 0x3FFU
+#define AEQ_CTRL_0_FUNC_BUSY_MASK 0x1U
#define AEQ_CTRL_0_DMA_ATTR_MASK 0x3FU
#define AEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3U
+#define AEQ_CTRL_0_QPS_NUM_MASK 0xFFU
#define AEQ_CTRL_0_INTR_MODE_MASK 0x1U
+#define AEQ_CTRL_0_GET(val, member) \
+ (((val) >> AEQ_CTRL_0_##member##_SHIFT) & \
+ AEQ_CTRL_0_##member##_MASK)
+
#define AEQ_CTRL_0_SET(val, member) \
(((val) & AEQ_CTRL_0_##member##_MASK) << \
AEQ_CTRL_0_##member##_SHIFT)
@@ -53,13 +62,19 @@
<< AEQ_CTRL_0_##member##_SHIFT)))
#define AEQ_CTRL_1_LEN_SHIFT 0
+#define AEQ_CTRL_1_FUNC_OWN_SHIFT 21
#define AEQ_CTRL_1_ELEM_SIZE_SHIFT 24
#define AEQ_CTRL_1_PAGE_SIZE_SHIFT 28
#define AEQ_CTRL_1_LEN_MASK 0x1FFFFFU
+#define AEQ_CTRL_1_FUNC_OWN_MASK 0x1U
#define AEQ_CTRL_1_ELEM_SIZE_MASK 0x3U
#define AEQ_CTRL_1_PAGE_SIZE_MASK 0xFU
+#define AEQ_CTRL_1_GET(val, member) \
+ (((val) >> AEQ_CTRL_1_##member##_SHIFT) & \
+ AEQ_CTRL_1_##member##_MASK)
+
#define AEQ_CTRL_1_SET(val, member) \
(((val) & AEQ_CTRL_1_##member##_MASK) << \
AEQ_CTRL_1_##member##_SHIFT)
@@ -213,6 +228,66 @@ MODULE_PARM_DESC(g_num_ceqe_in_tasklet,
static irqreturn_t aeq_interrupt(int irq, void *data);
static irqreturn_t ceq_interrupt(int irq, void *data);
+
+void hinic_qps_num_set(struct hinic_hwdev *hwdev, u32 num_qps)
+{
+ struct hinic_hwif *hwif = hwdev->hwif;
+ u32 addr, val, ctrl;
+
+ addr = HINIC_CSR_AEQ_CTRL_0_ADDR(0);
+ val = hinic_hwif_read_reg(hwif, addr);
+ val = AEQ_CTRL_0_CLEAR(val, QPS_NUM);
+ ctrl = AEQ_CTRL_0_SET(num_qps, QPS_NUM);
+ val |= ctrl;
+ hinic_hwif_write_reg(hwif, addr, val);
+}
+
+u32 hinic_func_busy_state_get(struct hinic_hwdev *hwdev)
+{
+ struct hinic_hwif *hwif = hwdev->hwif;
+ u32 addr, val;
+
+ addr = HINIC_CSR_AEQ_CTRL_0_ADDR(0);
+ val = hinic_hwif_read_reg(hwif, addr);
+ return AEQ_CTRL_0_GET(val, FUNC_BUSY);
+}
+
+void hinic_func_busy_state_set(struct hinic_hwdev *hwdev, u32 cfg)
+{
+ struct hinic_hwif *hwif = hwdev->hwif;
+ u32 addr, val, ctrl;
+
+ addr = HINIC_CSR_AEQ_CTRL_0_ADDR(0);
+ val = hinic_hwif_read_reg(hwif, addr);
+ val = AEQ_CTRL_0_CLEAR(val, FUNC_BUSY);
+ ctrl = AEQ_CTRL_0_SET(cfg, FUNC_BUSY);
+ val |= ctrl;
+ hinic_hwif_write_reg(hwif, addr, val);
+}
+
+u32 hinic_func_own_bit_get(struct hinic_hwdev *hwdev)
+{
+ struct hinic_hwif *hwif = hwdev->hwif;
+ u32 addr, val;
+
+ addr = HINIC_CSR_AEQ_CTRL_1_ADDR(0);
+ val = hinic_hwif_read_reg(hwif, addr);
+ return AEQ_CTRL_1_GET(val, FUNC_OWN);
+}
+
+void hinic_func_own_bit_set(struct hinic_hwdev *hwdev, u32 cfg)
+{
+ struct hinic_hwif *hwif = hwdev->hwif;
+ u32 addr, val, ctrl;
+
+ addr = HINIC_CSR_AEQ_CTRL_1_ADDR(0);
+ val = hinic_hwif_read_reg(hwif, addr);
+ val = AEQ_CTRL_1_CLEAR(val, FUNC_OWN);
+ ctrl = AEQ_CTRL_1_SET(cfg, FUNC_OWN);
+ val |= ctrl;
+ hinic_hwif_write_reg(hwif, addr, val);
+}
+
static void ceq_tasklet(ulong eq_tasklet);
static u8 eq_cons_idx_checksum_set(u32 val)
@@ -463,7 +538,7 @@ static bool aeq_irq_handler(struct hinic_eq *eq)
&aeqs->aeq_sw_cb_state[sw_event]);
if (aeqs->aeq_swe_cb[sw_event] &&
test_bit(HINIC_AEQ_SW_CB_REG,
- &aeqs->aeq_sw_cb_state[sw_event])) {
+ &aeqs->aeq_sw_cb_state[sw_event])) {
lev = aeqs->aeq_swe_cb[sw_event](aeqs->hwdev,
ucode_event,
aeqe_data);
@@ -479,7 +554,7 @@ static bool aeq_irq_handler(struct hinic_eq *eq)
&aeqs->aeq_hw_cb_state[event]);
if (aeqs->aeq_hwe_cb[event] &&
test_bit(HINIC_AEQ_HW_CB_REG,
- &aeqs->aeq_hw_cb_state[event]))
+ &aeqs->aeq_hw_cb_state[event]))
aeqs->aeq_hwe_cb[event](aeqs->hwdev,
aeqe_pos->aeqe_data, size);
clear_bit(HINIC_AEQ_HW_CB_RUNNING,
@@ -709,7 +784,10 @@ static int set_ceq_ctrl_reg(struct hinic_hwdev *hwdev, u16 q_id,
u16 out_size = sizeof(ceq_ctrl);
int err;
- ceq_ctrl.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &ceq_ctrl.func_id);
+ if (err)
+ return err;
+
ceq_ctrl.q_id = q_id;
ceq_ctrl.ctrl0 = ctrl0;
ceq_ctrl.ctrl1 = ctrl1;
@@ -751,6 +829,11 @@ static int set_eq_ctrls(struct hinic_eq *eq)
AEQ_CTRL_0_CLEAR(val, PCI_INTF_IDX) &
AEQ_CTRL_0_CLEAR(val, INTR_MODE);
+ if (HINIC_IS_VF(eq->hwdev)) {
+ val = AEQ_CTRL_0_CLEAR(val, FUNC_BUSY) &
+ AEQ_CTRL_1_CLEAR(val, FUNC_OWN);
+ }
+
ctrl0 = AEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) |
AEQ_CTRL_0_SET(AEQ_DMA_ATTR_DEFAULT, DMA_ATTR) |
AEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) |
@@ -955,7 +1038,6 @@ static void free_eq_pages(struct hinic_eq *eq)
kfree(eq->virt_addr);
kfree(eq->dma_addr);
}
-
static inline u32 get_page_size(struct hinic_eq *eq)
{
u32 total_size;
@@ -979,7 +1061,6 @@ static inline u32 get_page_size(struct hinic_eq *eq)
return EQ_MIN_PAGE_SIZE << n;
}
-
/**
* init_eq - initialize eq
* @eq: the event queue
@@ -1091,6 +1172,7 @@ static void remove_eq(struct hinic_eq *eq)
hinic_set_msix_state(eq->hwdev, entry->msix_entry_idx,
HINIC_MSIX_DISABLE);
synchronize_irq(entry->irq_id);
+
free_irq(entry->irq_id, eq);
if (eq->type == HINIC_AEQ) {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_eqs.h
b/drivers/net/ethernet/huawei/hinic/hinic_eqs.h
index 102dd189bb93..5813c4b3e67c 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_eqs.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_eqs.h
@@ -14,11 +14,13 @@
*/
#ifndef HINIC_EQS_H
+#include <linux/interrupt.h>
+
#define HINIC_EQS_H
#define HINIC_EQ_PAGE_SIZE 0x00001000
-#define HINIC_MAX_AEQS 4
+#define HINIC_MAX_AEQS 3
#define HINIC_MAX_CEQS 32
#define HINIC_EQ_MAX_PAGES 8
@@ -65,7 +67,6 @@ struct hinic_eq_work {
struct hinic_ceq_tasklet_data {
void *data;
};
-
struct hinic_eq {
struct hinic_hwdev *hwdev;
u16 q_id;
@@ -113,7 +114,6 @@ struct hinic_aeqs {
struct hinic_hwdev *hwdev;
hinic_aeq_hwe_cb aeq_hwe_cb[HINIC_MAX_AEQ_EVENTS];
-
hinic_aeq_swe_cb aeq_swe_cb[HINIC_MAX_AEQ_SW_EVENTS];
unsigned long aeq_hw_cb_state[HINIC_MAX_AEQ_EVENTS];
unsigned long aeq_sw_cb_state[HINIC_MAX_AEQ_SW_EVENTS];
@@ -140,6 +140,24 @@ struct hinic_ceqs {
u16 num_ceqs;
};
+enum hinic_msg_pipe_state {
+ PIPE_STATE_IDLE,
+ PIPE_STATE_BUSY,
+ PIPE_STATE_SUSPEND,
+};
+
+#define PIPE_CYCLE_MAX 10000
+
+u32 hinic_func_busy_state_get(struct hinic_hwdev *hwdev);
+
+void hinic_func_busy_state_set(struct hinic_hwdev *hwdev, u32 cfg);
+
+u32 hinic_func_own_bit_get(struct hinic_hwdev *hwdev);
+
+void hinic_func_own_bit_set(struct hinic_hwdev *hwdev, u32 cfg);
+
+void hinic_qps_num_set(struct hinic_hwdev *hwdev, u32 num_qps);
+
int hinic_aeqs_init(struct hinic_hwdev *hwdev, u16 num_aeqs,
struct irq_info *msix_entries);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index 76443f8a596d..e563d8aea676 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -140,7 +140,7 @@ static struct hinic_stats hinic_tx_queue_stats_extern[] = {
HINIC_TXQ_STAT(alloc_cpy_frag_err),
HINIC_TXQ_STAT(map_cpy_frag_err),
HINIC_TXQ_STAT(map_frag_err),
-}; /*lint -restore*/
+};/*lint -restore*/
#define HINIC_FUNC_STAT(_stat_item) { \
.name = #_stat_item, \
@@ -677,9 +677,9 @@ static int hinic_get_settings(struct net_device *netdev,
}
#ifdef ETHTOOL_GLINKSETTINGS
+#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
static int hinic_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings
- *link_settings)
+ struct ethtool_link_ksettings *link_settings)
{
struct cmd_link_settings settings = {0};
struct ethtool_link_settings *base = &link_settings->base;
@@ -707,6 +707,7 @@ static int hinic_get_link_ksettings(struct net_device *netdev,
return 0;
}
#endif
+#endif
static int hinic_is_speed_legal(struct hinic_nic_dev *nic_dev, u32 speed)
{
@@ -852,15 +853,16 @@ static int hinic_set_settings(struct net_device *netdev,
}
#ifdef ETHTOOL_GLINKSETTINGS
+#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
static int hinic_set_link_ksettings(struct net_device *netdev,
- const struct ethtool_link_ksettings
- *link_settings)
+ const struct ethtool_link_ksettings *link_settings)
{
/* Only support to set autoneg and speed */
return set_link_settings(netdev, link_settings->base.autoneg,
link_settings->base.speed);
}
#endif
+#endif
static void hinic_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
@@ -1374,27 +1376,27 @@ static int is_coalesce_legal(struct net_device *netdev,
#define CHECK_COALESCE_ALIGN(coal, item, unit) \
do { \
- if ((coal)->item % (unit)) \
+ if (coal->item % (unit)) \
nicif_warn(nic_dev, drv, netdev, \
"%s in %d units, change to %d\n", \
- #item, (unit), ALIGN_DOWN((coal)->item, unit));\
+ #item, (unit), ALIGN_DOWN(coal->item, unit));\
} while (0)
#define CHECK_COALESCE_CHANGED(coal, item, unit, ori_val, obj_str) \
do { \
- if (((coal)->item / (unit)) != (ori_val)) \
+ if ((coal->item / (unit)) != (ori_val)) \
nicif_info(nic_dev, drv, netdev, \
"Change %s from %d to %d %s\n", \
#item, (ori_val) * (unit), \
- ALIGN_DOWN((coal)->item, unit), (obj_str)); \
+ ALIGN_DOWN(coal->item, unit), (obj_str)); \
} while (0)
#define CHECK_PKT_RATE_CHANGED(coal, item, ori_val, obj_str) \
do { \
- if ((coal)->item != (ori_val)) \
+ if (coal->item != (ori_val)) \
nicif_info(nic_dev, drv, netdev, \
"Change %s from %llu to %u %s\n", \
- #item, (ori_val), (coal)->item, (obj_str)); \
+ #item, (ori_val), coal->item, (obj_str)); \
} while (0)
static int __hinic_set_coalesce(struct net_device *netdev,
@@ -1865,7 +1867,7 @@ static int hinic_run_lp_test(struct hinic_nic_dev *nic_dev, u32
test_time)
/* mark index for every pkt */
skb->data[LP_PKT_LEN - 1] = j;
- if (hinic_xmit_frame(skb, netdev)) {
+ if (hinic_lb_xmit_frame(skb, netdev)) {
dev_kfree_skb_any(skb);
dev_kfree_skb_any(skb_tmp);
nicif_err(nic_dev, drv, netdev,
@@ -2228,7 +2230,7 @@ static int __set_rss_rxfh(struct net_device *netdev,
/* We request double spaces for the hash key,
* the second one holds the key of Big Edian
* format.
- */
+ */
nic_dev->rss_hkey_user =
kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
@@ -2448,8 +2450,10 @@ static int hinic_set_rxfh_indir(struct net_device *netdev, const
u32 *indir)
static const struct ethtool_ops hinic_ethtool_ops = {
#ifdef ETHTOOL_GLINKSETTINGS
+#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
.get_link_ksettings = hinic_get_link_ksettings,
.set_link_ksettings = hinic_set_link_ksettings,
+#endif
#endif
.get_settings = hinic_get_settings,
.set_settings = hinic_set_settings,
@@ -2521,7 +2525,9 @@ static const struct ethtool_ops_ext hinic_ethtool_ops_ext = {
static const struct ethtool_ops hinicvf_ethtool_ops = {
#ifdef ETHTOOL_GLINKSETTINGS
+#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
.get_link_ksettings = hinic_get_link_ksettings,
+#endif
#else
.get_settings = hinic_get_settings,
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw.h
b/drivers/net/ethernet/huawei/hinic/hinic_hw.h
index 9850a8ed6e22..69b069ba0cd3 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw.h
@@ -84,8 +84,8 @@ int hinic_msg_to_mgmt_async(void *hwdev, enum hinic_mod_type mod, u8
cmd,
void *buf_in, u16 in_size);
int hinic_mbox_to_vf(void *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);
+ u16 vf_id, u8 cmd, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size, u32 timeout);
int hinic_api_cmd_write_nack(void *hwdev, u8 dest,
void *cmd, u16 size);
@@ -375,11 +375,13 @@ enum hinic_func_cap {
* allocation or dev_err print the parameter
*/
int hinic_init_hwdev(struct hinic_init_para *para);
+int hinic_set_vf_dev_cap(void *hwdev);
void hinic_free_hwdev(void *hwdev);
void hinic_shutdown_hwdev(void *hwdev);
void hinic_ppf_hwdev_unreg(void *hwdev);
void hinic_ppf_hwdev_reg(void *hwdev, void *ppf_hwdev);
+
bool hinic_is_hwdev_mod_inited(void *hwdev, enum hinic_hwdev_init_state state);
enum hinic_func_mode hinic_get_func_mode(void *hwdev);
u64 hinic_get_func_feature_cap(void *hwdev);
@@ -390,7 +392,6 @@ enum hinic_service_mode {
HINIC_WORK_MODE_NIC,
HINIC_WORK_MODE_INVALID = 0xFF,
};
-
enum hinic_service_mode hinic_get_service_mode(void *hwdev);
int hinic_slq_init(void *dev, int num_wqs);
@@ -616,6 +617,7 @@ enum hinic_event_type {
HINIC_EVENT_PORT_MODULE_EVENT = 7,
HINIC_EVENT_MCTP_GET_HOST_INFO,
HINIC_EVENT_MULTI_HOST_MGMT,
+ HINIC_EVENT_INIT_MIGRATE_PF,
};
struct hinic_event_info {
@@ -726,14 +728,16 @@ struct hinic_hw_pf_infos {
int hinic_get_hw_pf_infos(void *hwdev, struct hinic_hw_pf_infos *infos);
int hinic_set_ip_check(void *hwdev, bool ip_check_ctl);
int hinic_mbox_to_host_sync(void *hwdev, enum hinic_mod_type mod,
- u8 cmd, void *buf_in, u16 in_size, void *buf_out,
- u16 *out_size, u32 timeout);
+ u8 cmd, void *buf_in, u16 in_size, void *buf_out,
+ u16 *out_size, u32 timeout);
int hinic_mbox_ppf_to_vf(void *hwdev,
- enum hinic_mod_type mod, u16 func_id, u8 cmd,
- void *buf_in, u16 in_size, void *buf_out,
- u16 *out_size, u32 timeout);
+ enum hinic_mod_type mod, u16 func_id, u8 cmd, void *buf_in,
+ u16 in_size, void *buf_out, u16 *out_size, u32 timeout);
int hinic_get_card_present_state(void *hwdev, bool *card_present_state);
+
+void hinic_migrate_report(void *dev);
int hinic_set_vxlan_udp_dport(void *hwdev, u32 udp_port);
+bool is_multi_vm_slave(void *hwdev);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
index d4bb6fab3462..f2143c05526e 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
@@ -1,5 +1,5 @@
-/*
- * Huawei HiNIC PCI Express Linux driver
+/* SPDX-License-Identifier: GPL-2.0*/
+/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,6 +27,9 @@ enum hinic_service_type {
SERVICE_T_IWARP,
SERVICE_T_FC,
SERVICE_T_FCOE,
+ SERVICE_T_MIGRATE,
+ SERVICE_T_PT,
+ SERVICE_T_HWPT,
SERVICE_T_MAX,
/* Only used for interruption resource management,
@@ -68,6 +71,8 @@ struct nic_service_cap {
bool lro_en; /* LRO feature enable bit*/
u8 lro_sz; /* LRO context space: n*16B */
u8 tso_sz; /* TSO context space: n*16B */
+
+ u16 max_queue_allowed;
};
struct dev_roce_svc_own_cap {
@@ -520,7 +525,6 @@ struct hinic_micro_log_info {
int (*init)(void *hwdev);
void (*deinit)(void *hwdev);
};
-
int hinic_register_micro_log(struct hinic_micro_log_info *micro_log_info);
void hinic_unregister_micro_log(struct hinic_micro_log_info *micro_log_info);
@@ -544,5 +548,12 @@ struct hinic_func_nic_state {
int hinic_set_func_nic_state(void *hwdev, struct hinic_func_nic_state *state);
int hinic_get_func_nic_enable(void *hwdev, u16 glb_func_idx, bool *en);
bool hinic_get_master_host_mbox_enable(void *hwdev);
-
+bool hinic_get_slave_host_enable(void *hwdev, u8 host_id);
+int hinic_func_own_get(void *hwdev);
+void hinic_func_own_free(void *hwdev);
+int hinic_global_func_id_get(void *hwdev, u16 *func_id);
+u16 hinic_pf_id_of_vf_hw(void *hwdev);
+u16 hinic_global_func_id_hw(void *hwdev);
+bool hinic_func_for_pt(void *hwdev);
+bool hinic_func_for_hwpt(void *hwdev);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c
b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c
index 86e6da167bb2..26939981877c 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c
@@ -10,6 +10,7 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
@@ -514,30 +515,6 @@ static void hinic_set_mgmt_channel_status(void *handle, bool state);
static inline void __set_heartbeat_ehd_detect_delay(struct hinic_hwdev *hwdev,
u32 delay_ms);
-#define HINIC_MGMT_STATUS_ERR_OK 0 /* Ok */
-#define HINIC_MGMT_STATUS_ERR_PARAM 1 /* Invalid parameter */
-#define HINIC_MGMT_STATUS_ERR_FAILED 2 /* Operation failed */
-#define HINIC_MGMT_STATUS_ERR_PORT 3 /* Invalid port */
-#define HINIC_MGMT_STATUS_ERR_TIMEOUT 4 /* Operation time out */
-#define HINIC_MGMT_STATUS_ERR_NOMATCH 5 /* Version not match */
-#define HINIC_MGMT_STATUS_ERR_EXIST 6 /* Entry exists */
-#define HINIC_MGMT_STATUS_ERR_NOMEM 7 /* Out of memory */
-#define HINIC_MGMT_STATUS_ERR_INIT 8 /* Feature not initialized */
-#define HINIC_MGMT_STATUS_ERR_FAULT 9 /* Invalid address */
-#define HINIC_MGMT_STATUS_ERR_PERM 10 /* Operation not permitted */
-#define HINIC_MGMT_STATUS_ERR_EMPTY 11 /* Table empty */
-#define HINIC_MGMT_STATUS_ERR_FULL 12 /* Table full */
-#define HINIC_MGMT_STATUS_ERR_NOT_FOUND 13 /* Not found */
-#define HINIC_MGMT_STATUS_ERR_BUSY 14 /* Device or resource busy */
-#define HINIC_MGMT_STATUS_ERR_RESOURCE 15 /* No resources for operation */
-#define HINIC_MGMT_STATUS_ERR_CONFIG 16 /* Invalid configuration */
-#define HINIC_MGMT_STATUS_ERR_UNAVAIL 17 /* Feature unavailable */
-#define HINIC_MGMT_STATUS_ERR_CRC 18 /* CRC check failed */
-#define HINIC_MGMT_STATUS_ERR_NXIO 19 /* No such device or address */
-#define HINIC_MGMT_STATUS_ERR_ROLLBACK 20 /* Chip rollback fail */
-#define HINIC_MGMT_STATUS_ERR_LEN 32 /* Length too short or too long */
-#define HINIC_MGMT_STATUS_ERR_UNSUPPORT 0xFF/* Feature not supported*/
-
#define HINIC_QUEUE_MIN_DEPTH 6
#define HINIC_QUEUE_MAX_DEPTH 12
#define HINIC_MAX_RX_BUFFER_SIZE 15
@@ -692,7 +669,7 @@ static void __print_status_info(struct hinic_hwdev *dev,
if (HINIC_IS_VF(dev) && (cmd == HINIC_PORT_CMD_SET_MAC || cmd ==
HINIC_PORT_CMD_DEL_MAC || cmd ==
HINIC_PORT_CMD_UPDATE_MAC) &&
- mgmt_status_log[index].status == HINIC_PF_SET_VF_ALREADY)
+ (mgmt_status_log[index].status == HINIC_PF_SET_VF_ALREADY))
return;
nic_err(dev->dev_hdl, "Mgmt process mod(0x%x) cmd(0x%x) fail: %s",
@@ -719,8 +696,8 @@ static bool hinic_status_need_special_handle(enum hinic_mod_type mod,
return false;
}
-void hinic_print_status_info(void *hwdev, enum hinic_mod_type mod, u8 cmd,
- void *buf_out)
+static void hinic_print_status_info(void *hwdev, enum hinic_mod_type mod,
+ u8 cmd, const void *buf_out)
{
struct hinic_hwdev *dev = hwdev;
int i, size;
@@ -773,9 +750,15 @@ void hinic_set_chip_absent(void *hwdev)
int hinic_get_chip_present_flag(void *hwdev)
{
- int flag = ((struct hinic_hwdev *)hwdev)->chip_present_flag;
+ int flag;
+
+ if (!hwdev)
+ return -EINVAL;
+ flag = ((struct hinic_hwdev *)hwdev)->chip_present_flag;
return flag;
}
+EXPORT_SYMBOL(hinic_get_chip_present_flag);
+
static void hinic_set_fast_recycle_status(void *hwdev)
{
@@ -843,8 +826,7 @@ static int __func_send_mbox(struct hinic_hwdev *hwdev, enum
hinic_mod_type mod,
out_size, timeout);
else if (NEED_MBOX_FORWARD(hwdev))
err = hinic_mbox_to_host_sync(hwdev, mod, cmd, buf_in,
- in_size, buf_out, out_size,
- timeout);
+ in_size, buf_out, out_size, timeout);
else
err = -EFAULT;
@@ -1060,8 +1042,8 @@ int hinic_mbox_to_vf(void *hwdev,
EXPORT_SYMBOL(hinic_mbox_to_vf);
int hinic_clp_to_mgmt(void *hwdev, enum hinic_mod_type mod, u8 cmd,
- void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size)
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
{
struct hinic_hwdev *dev = hwdev;
@@ -1080,7 +1062,7 @@ int hinic_clp_to_mgmt(void *hwdev, enum hinic_mod_type mod, u8 cmd,
return -EPERM;
err = hinic_pf_clp_to_mgmt(dev, mod, cmd, buf_in,
- in_size, buf_out, out_size);
+ in_size, buf_out, out_size);
return err;
}
@@ -1162,7 +1144,9 @@ int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr
*attr)
if (!hwdev || !attr)
return -EINVAL;
- cons_idx_attr.func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &cons_idx_attr.func_idx);
+ if (err)
+ return err;
cons_idx_attr.dma_attr_off = attr->dma_attr_off;
cons_idx_attr.pending_limit = attr->pending_limit;
@@ -1199,7 +1183,10 @@ static int hinic_set_cmdq_depth(struct hinic_hwdev *hwdev, u16
cmdq_depth)
u16 out_size = sizeof(root_ctxt);
int err;
- root_ctxt.func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &root_ctxt.func_idx);
+ if (err)
+ return err;
+
root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
root_ctxt.set_cmdq_depth = 1;
@@ -1244,7 +1231,10 @@ int hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth,
int rx_buf_sz)
if (!hwdev)
return -EINVAL;
- root_ctxt.func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &root_ctxt.func_idx);
+ if (err)
+ return err;
+
root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
root_ctxt.set_cmdq_depth = 0;
@@ -1280,7 +1270,10 @@ int hinic_clean_root_ctxt(void *hwdev)
if (!hwdev)
return -EINVAL;
- root_ctxt.func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &root_ctxt.func_idx);
+ if (err)
+ return err;
+
root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
@@ -1368,7 +1361,10 @@ static int hinic_vf_rx_tx_flush(struct hinic_hwdev *hwdev)
if (err)
sdk_warn(hwdev->dev_hdl, "Cmdq is still working, please check CMDQ timeout
value is reasonable\n");
- clr_res.func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);
+ err = hinic_global_func_id_get(hwdev, &clr_res.func_idx);
+ if (err)
+ return err;
+
clr_res.ppf_idx = HINIC_HWIF_PPF_IDX(hwdev->hwif);
err = hinic_mbox_to_pf_no_ack(hwdev, HINIC_MOD_COMM,
HINIC_MGMT_CMD_START_FLR, &clr_res,
@@ -1434,6 +1430,7 @@ static int hinic_vf_rx_tx_flush_in_pf(struct hinic_hwdev *hwdev, u16
vf_id)
ret = -EFAULT;
}
+ /* wait ucode stop I/O */
msleep(100);
/* notice up begine vf flush */
@@ -1462,11 +1459,11 @@ static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
struct hinic_hwif *hwif = hwdev->hwif;
struct hinic_clear_doorbell clear_db = {0};
struct hinic_clear_resource clr_res = {0};
- u16 out_size;
+ u16 out_size, func_id;
int err;
int ret = 0;
- /* wait ucode stop I/O */
+ /* wait ucode stop I/O */
msleep(100);
err = wait_cmdq_stop(hwdev);
@@ -1478,7 +1475,8 @@ static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
hinic_disable_doorbell(hwif);
out_size = sizeof(clear_db);
- clear_db.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+ func_id = hinic_global_func_id_hw(hwdev);
+ clear_db.func_idx = func_id;
clear_db.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
@@ -1495,7 +1493,7 @@ static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
hinic_set_pf_status(hwif, HINIC_PF_STATUS_FLR_START_FLAG);
- clr_res.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+ clr_res.func_idx = func_id;
clr_res.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
err = hinic_msg_to_mgmt_no_ack(hwdev, HINIC_MOD_COMM,
@@ -1551,7 +1549,10 @@ int hinic_get_interrupt_cfg(void *hwdev,
if (!hwdev || !interrupt_info)
return -EINVAL;
- msix_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &msix_cfg.func_id);
+ if (err)
+ return err;
+
msix_cfg.msix_index = interrupt_info->msix_index;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
@@ -1586,15 +1587,17 @@ int hinic_set_interrupt_cfg(void *hwdev,
if (!hwdev)
return -EINVAL;
- msix_cfg.func_id = hinic_global_func_id(hwdev);
- msix_cfg.msix_index = (u16)interrupt_info.msix_index;
-
temp_info.msix_index = interrupt_info.msix_index;
err = hinic_get_interrupt_cfg(hwdev, &temp_info);
if (err)
return -EINVAL;
+ err = hinic_global_func_id_get(hwdev, &msix_cfg.func_id);
+ if (err)
+ return err;
+
+ msix_cfg.msix_index = (u16)interrupt_info.msix_index;
msix_cfg.lli_credit_cnt = temp_info.lli_credit_limit;
msix_cfg.lli_tmier_cnt = temp_info.lli_timer_cfg;
msix_cfg.pending_cnt = temp_info.pending_limt;
@@ -1747,7 +1750,9 @@ static int set_vf_dma_attr_entry(struct hinic_hwdev *hwdev, u8
entry_idx,
u16 out_size = sizeof(attr);
int err;
- attr.func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &attr.func_idx);
+ if (err)
+ return err;
attr.func_dma_entry_num = hinic_dma_attr_entry_num(hwdev);
attr.entry_idx = entry_idx;
@@ -1799,12 +1804,14 @@ static int dma_attr_table_init(struct hinic_hwdev *hwdev)
static int resources_state_set(struct hinic_hwdev *hwdev,
enum hinic_res_state state)
{
- struct hinic_hwif *hwif = hwdev->hwif;
struct hinic_cmd_set_res_state res_state = {0};
u16 out_size = sizeof(res_state);
int err;
- res_state.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+ err = hinic_global_func_id_get(hwdev, &res_state.func_idx);
+ if (err)
+ return err;
+
res_state.state = state;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
@@ -2141,7 +2148,6 @@ static void hinic_comm_pf_to_mgmt_free(struct hinic_hwdev *hwdev)
hinic_pf_to_mgmt_free(hwdev);
}
-
static int hinic_comm_clp_to_mgmt_init(struct hinic_hwdev *hwdev)
{
int err;
@@ -2225,8 +2231,8 @@ static int hinic_sync_mgmt_func_state(struct hinic_hwdev *hwdev)
if (HINIC_FUNC_TYPE(hwdev) == TYPE_PPF) {
/* heartbeat synchronize must be after set pf active status */
hinic_comm_recv_mgmt_self_cmd_reg(hwdev,
- HINIC_MGMT_HEARTBEAT_EVENT,
- mgmt_heartbeat_event_handler);
+ HINIC_MGMT_CMD_HEARTBEAT_EVENT,
+ mgmt_heartbeat_event_handler);
}
return 0;
@@ -2244,7 +2250,7 @@ static void hinic_unsync_mgmt_func_state(struct hinic_hwdev *hwdev)
hwdev->heartbeat_ehd.en = false;
if (HINIC_FUNC_TYPE(hwdev) == TYPE_PPF) {
hinic_comm_recv_up_self_cmd_unreg(hwdev,
- HINIC_MGMT_HEARTBEAT_EVENT);
+ HINIC_MGMT_CMD_HEARTBEAT_EVENT);
}
resources_state_set(hwdev, HINIC_RES_CLEAN);
@@ -2253,7 +2259,6 @@ static void hinic_unsync_mgmt_func_state(struct hinic_hwdev *hwdev)
int hinic_l2nic_reset_base(struct hinic_hwdev *hwdev, u16 reset_flag)
{
struct hinic_l2nic_reset l2nic_reset = {0};
- struct hinic_hwif *hwif = hwdev->hwif;
u16 out_size = sizeof(l2nic_reset);
int err = 0;
@@ -2264,7 +2269,11 @@ int hinic_l2nic_reset_base(struct hinic_hwdev *hwdev, u16
reset_flag)
msleep(100);
sdk_info(hwdev->dev_hdl, "L2nic reset flag 0x%x\n", reset_flag);
- l2nic_reset.func_id = HINIC_HWIF_GLOBAL_IDX(hwif);
+
+ err = hinic_global_func_id_get(hwdev, &l2nic_reset.func_id);
+ if (err)
+ return err;
+
l2nic_reset.reset_flag = reset_flag;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
HINIC_MGMT_CMD_L2NIC_RESET, &l2nic_reset,
@@ -2337,6 +2346,7 @@ static int __init_eqs_msix_attr(struct hinic_hwdev *hwdev)
int hinic_init_comm_ch(struct hinic_hwdev *hwdev)
{
int err;
+ u16 func_id;
if (IS_BMGW_SLAVE_HOST(hwdev) &&
(!hinic_get_master_host_mbox_enable(hwdev))) {
@@ -2405,8 +2415,12 @@ int hinic_init_comm_ch(struct hinic_hwdev *hwdev)
/* set default wq page_size */
hwdev->wq_page_size = HINIC_DEFAULT_WQ_PAGE_SIZE;
- err = hinic_set_wq_page_size(hwdev, hinic_global_func_id(hwdev),
- hwdev->wq_page_size);
+
+ err = hinic_global_func_id_get(hwdev, &func_id);
+ if (err)
+ goto get_func_id_err;
+
+ err = hinic_set_wq_page_size(hwdev, func_id, hwdev->wq_page_size);
if (err) {
sdk_err(hwdev->dev_hdl, "Failed to set wq page size\n");
goto init_wq_pg_size_err;
@@ -2445,9 +2459,9 @@ int hinic_init_comm_ch(struct hinic_hwdev *hwdev)
cmdq_init_err:
if (HINIC_FUNC_TYPE(hwdev) != TYPE_VF)
- hinic_set_wq_page_size(hwdev, hinic_global_func_id(hwdev),
- HINIC_HW_WQ_PAGE_SIZE);
+ hinic_set_wq_page_size(hwdev, func_id, HINIC_HW_WQ_PAGE_SIZE);
init_wq_pg_size_err:
+get_func_id_err:
init_eqs_msix_err:
hinic_comm_ceqs_free(hwdev);
@@ -2473,6 +2487,8 @@ int hinic_init_comm_ch(struct hinic_hwdev *hwdev)
static void __uninit_comm_module(struct hinic_hwdev *hwdev,
enum hinic_hwdev_init_state init_state)
{
+ u16 func_id;
+
switch (init_state) {
case HINIC_HWDEV_COMM_CH_INITED:
hinic_aeq_unregister_swe_cb(hwdev,
@@ -2485,10 +2501,12 @@ static void __uninit_comm_module(struct hinic_hwdev *hwdev,
* will return error in pf, pf will set all vf's page
* size to 4K when disable sriov
*/
- if (HINIC_FUNC_TYPE(hwdev) != TYPE_VF)
- hinic_set_wq_page_size(hwdev,
- hinic_global_func_id(hwdev),
+ if (HINIC_FUNC_TYPE(hwdev) != TYPE_VF) {
+ func_id = hinic_global_func_id_hw(hwdev);
+ hinic_set_wq_page_size(hwdev, func_id,
HINIC_HW_WQ_PAGE_SIZE);
+ }
+
hinic_comm_ceqs_free(hwdev);
if (IS_MULTI_HOST(hwdev))
@@ -2641,7 +2659,10 @@ int hinic_func_tmr_bitmap_set(void *hwdev, bool en)
if (!hwdev)
return -EINVAL;
- bitmap_op.func_idx = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &bitmap_op.func_idx);
+ if (err)
+ return err;
+
bitmap_op.ppf_idx = hinic_ppf_idx(hwdev);
if (en)
bitmap_op.op_id = FUNC_TMR_BITMAP_ENABLE;
@@ -2916,8 +2937,8 @@ int mqm_eqm_set_cfg_2_hw(struct hinic_hwdev *hwdev, u32 valid)
u16 out_size = sizeof(info_eqm_cfg);
int err;
+ info_eqm_cfg.ppf_id = hinic_global_func_id_hw(hwdev);
info_eqm_cfg.page_size = hwdev->mqm_att.page_size;
- info_eqm_cfg.ppf_id = hwdev->hwif->attr.func_global_idx;
info_eqm_cfg.valid = valid;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
@@ -2974,9 +2995,9 @@ int mqm_eqm_set_page_2_hw(struct hinic_hwdev *hwdev)
info->start_idx = start_idx;
out_size = send_buf_size;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
- HINIC_MGMT_MQM_SRCH_GPA_SET,
- info, (u16)send_buf_size,
- info, &out_size, 0);
+ HINIC_MGMT_CMD_MQM_SRCH_GPA_SET,
+ info, (u16)send_buf_size, info,
+ &out_size, 0);
if (err || !out_size || info->status) {
sdk_err(hwdev->dev_hdl, "Set mqm srch gpa fail, err: %d, status: 0x%x,
out_size: 0x%x\n",
err, info->status, out_size);
@@ -2997,7 +3018,7 @@ int mqm_eqm_set_page_2_hw(struct hinic_hwdev *hwdev)
info->start_idx = start_idx;
out_size = send_buf_size;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
- HINIC_MGMT_MQM_SRCH_GPA_SET,
+ HINIC_MGMT_CMD_MQM_SRCH_GPA_SET,
info, (u16)send_buf_size,
info, &out_size, 0);
if (err || !out_size || info->status) {
@@ -3259,7 +3280,7 @@ static struct hinic_event_convert __event_convert[] = {
},
{
.mod = HINIC_MOD_COMM,
- .cmd = HINIC_MGMT_HEARTBEAT_EVENT,
+ .cmd = HINIC_MGMT_CMD_HEARTBEAT_EVENT,
.event = HINIC_EVENT_MGMT_HEARTBEAT_EHD,
},
};
@@ -3281,7 +3302,7 @@ static enum hinic_event_cmd __get_event_type(u8 mod, u8 cmd)
bool hinic_mgmt_event_ack_first(u8 mod, u8 cmd)
{
if ((mod == HINIC_MOD_COMM && cmd == HINIC_MGMT_CMD_GET_HOST_INFO) ||
- (mod == HINIC_MOD_COMM && cmd == HINIC_MGMT_HEARTBEAT_EVENT))
+ (mod == HINIC_MOD_COMM && cmd == HINIC_MGMT_CMD_HEARTBEAT_EVENT))
return false;
if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC ||
@@ -3392,7 +3413,7 @@ static void fault_report_show(struct hinic_hwdev *hwdev,
}
static void hinic_refresh_history_fault(struct hinic_hwdev *hwdev,
- struct hinic_fault_recover_info *info)
+ struct hinic_fault_recover_info *info)
{
if (!hwdev->history_fault_flag) {
hwdev->history_fault_flag = true;
@@ -3405,6 +3426,20 @@ static void hinic_refresh_history_fault(struct hinic_hwdev *hwdev,
}
}
+void hinic_migrate_report(void *dev)
+{
+ struct hinic_hwdev *hwdev = (struct hinic_hwdev *)dev;
+ struct hinic_event_info event_info = {0};
+
+ if (!dev)
+ return;
+
+ event_info.type = HINIC_EVENT_INIT_MIGRATE_PF;
+ if (hwdev->event_callback)
+ hwdev->event_callback(hwdev->event_pri_handle, &event_info);
+}
+EXPORT_SYMBOL(hinic_migrate_report);
+
static void fault_event_handler(struct hinic_hwdev *hwdev, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size)
{
@@ -4198,7 +4233,6 @@ static int vf_nic_event_handler(void *hwdev, u8 cmd, void *buf_in,
{
enum hinic_event_cmd type = __get_event_type(HINIC_MOD_L2NIC, cmd);
-
if (type == HINIC_EVENT_MAX_TYPE) {
sdk_warn(((struct hinic_hwdev *)hwdev)->dev_hdl,
"Unsupport L2NIC event: cmd %d\n", cmd);
@@ -4216,7 +4250,6 @@ static int vf_comm_event_handler(void *hwdev, u8 cmd, void *buf_in,
{
enum hinic_event_cmd type = __get_event_type(HINIC_MOD_COMM, cmd);
-
if (type == HINIC_EVENT_MAX_TYPE) {
sdk_warn(((struct hinic_hwdev *)hwdev)->dev_hdl,
"Unsupport COMM event: cmd %d\n", cmd);
@@ -4235,7 +4268,6 @@ static void pf_nic_event_handler(void *hwdev, void *pri_handle, u8
cmd,
void *buf_out, u16 *out_size)
{
enum hinic_event_cmd type = __get_event_type(HINIC_MOD_L2NIC, cmd);
-
if (type == HINIC_EVENT_MAX_TYPE) {
sdk_warn(((struct hinic_hwdev *)hwdev)->dev_hdl,
"Unsupport L2NIC event: cmd %d\n", cmd);
@@ -4251,7 +4283,6 @@ static void pf_hilink_event_handler(void *hwdev, void *pri_handle,
u8 cmd,
void *buf_out, u16 *out_size)
{
enum hinic_event_cmd type = __get_event_type(HINIC_MOD_HILINK, cmd);
-
if (type == HINIC_EVENT_MAX_TYPE) {
sdk_warn(((struct hinic_hwdev *)hwdev)->dev_hdl,
"Unsupport HILINK event: cmd %d\n", cmd);
@@ -4265,7 +4296,7 @@ static void pf_hilink_event_handler(void *hwdev, void *pri_handle,
u8 cmd,
/* pf fault report event */
void pf_fault_event_handler(void *hwdev,
void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size)
+ void *buf_out, u16 *out_size)
{
_event_handler(hwdev, HINIC_EVENT_MGMT_FAULT, buf_in,
in_size, buf_out, out_size);
@@ -4286,7 +4317,7 @@ void mgmt_fmw_act_event_handler(void *hwdev, void *buf_in, u16
in_size,
}
void mgmt_pcie_dfx_event_handler(void *hwdev, void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size)
+ void *buf_out, u16 *out_size)
{
_event_handler(hwdev, HINIC_EVENT_MGMT_PCIE_DFX, buf_in,
in_size, buf_out, out_size);
@@ -4398,7 +4429,7 @@ static u8 hinic_get_heartbeat_status(struct hinic_hwdev *hwdev)
sdk_err(hwdev->dev_hdl, "Detect pcie is link down\n");
hinic_set_chip_absent(hwdev);
hinic_force_complete_all(hwdev);
- /* should notify chiperr to pangea
+ /* :should notify chiperr to pangea
* when detecting pcie link down
*/
return 1;
@@ -4538,7 +4569,10 @@ int hinic_enable_fast_recycle(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &fast_recycled_mode.func_id);
+ if (err)
+ return err;
+
fast_recycled_mode.fast_recycled_mode = enable ? 1 : 0;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
@@ -4792,6 +4826,7 @@ int hinic_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit)
struct hinic_hwdev *dev = hwdev;
struct hinic_bios_cfg_cmd cfg = {0};
u16 out_size = sizeof(cfg);
+ u16 func_id;
int err;
if (!hwdev || !pf_bw_limit)
@@ -4801,8 +4836,12 @@ int hinic_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit)
!FUNC_SUPPORT_RATE_LIMIT(hwdev))
return 0;
+ err = hinic_global_func_id_get(hwdev, &func_id);
+ if (err)
+ return err;
+
cfg.func_valid = 1;
- cfg.func_idx = (u8)hinic_global_func_id(hwdev);
+ cfg.func_idx = (u8)func_id;
cfg.op_code = HINIC_BIOS_CFG_GET | HINIC_BIOS_CFG_PF_BW_LIMIT;
@@ -4895,7 +4934,7 @@ int hinic_read_reg(void *hwdev, u32 reg_addr, u32 *val)
}
static void hinic_exec_recover_cb(struct hinic_hwdev *hwdev,
- struct hinic_fault_recover_info *info)
+ struct hinic_fault_recover_info *info)
{
sdk_info(hwdev->dev_hdl, "Enter hinic_exec_recover_cb\n");
@@ -5043,8 +5082,8 @@ int hinic_set_ip_check(void *hwdev, bool ip_check_ctl)
for (i = 0; i <= HINIC_IPSU_CHANNEL_NUM; i++) {
ret = hinic_api_csr_rd32(hwdev, HINIC_NODE_ID_IPSU,
- (HINIC_IPSU_CHANNEL0_ADDR +
- i * HINIC_IPSU_CHANNEL_OFFSET), &val);
+ (HINIC_IPSU_CHANNEL0_ADDR +
+ i * HINIC_IPSU_CHANNEL_OFFSET), &val);
if (ret)
return ret;
@@ -5056,8 +5095,8 @@ int hinic_set_ip_check(void *hwdev, bool ip_check_ctl)
val = cpu_to_be32(val);
ret = hinic_api_csr_wr32(hwdev, HINIC_NODE_ID_IPSU,
- (HINIC_IPSU_CHANNEL0_ADDR +
- i * HINIC_IPSU_CHANNEL_OFFSET), val);
+ (HINIC_IPSU_CHANNEL0_ADDR +
+ i * HINIC_IPSU_CHANNEL_OFFSET), val);
if (ret)
return ret;
}
@@ -5103,7 +5142,7 @@ int hinic_set_vxlan_udp_dport(void *hwdev, u32 udp_port)
return 0;
ret = hinic_api_csr_rd32(hwdev, HINIC_NODE_ID_IPSU,
- HINIC_IPSURX_VXLAN_DPORT_ADDR, &val);
+ HINIC_IPSURX_VXLAN_DPORT_ADDR, &val);
if (ret)
return ret;
@@ -5116,7 +5155,7 @@ int hinic_set_vxlan_udp_dport(void *hwdev, u32 udp_port)
udp_port = cpu_to_be32(udp_port);
ret = hinic_api_csr_wr32(hwdev, HINIC_NODE_ID_IPSU,
- HINIC_IPSURX_VXLAN_DPORT_ADDR, udp_port);
+ HINIC_IPSURX_VXLAN_DPORT_ADDR, udp_port);
if (ret)
return ret;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h
b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h
index e0d76b192080..eebd74b85f94 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h
@@ -24,6 +24,30 @@
#define HINIC_MSG_TO_MGMT_MAX_LEN 2016
+#define HINIC_MGMT_STATUS_ERR_OK 0 /* Ok */
+#define HINIC_MGMT_STATUS_ERR_PARAM 1 /* Invalid parameter */
+#define HINIC_MGMT_STATUS_ERR_FAILED 2 /* Operation failed */
+#define HINIC_MGMT_STATUS_ERR_PORT 3 /* Invalid port */
+#define HINIC_MGMT_STATUS_ERR_TIMEOUT 4 /* Operation time out */
+#define HINIC_MGMT_STATUS_ERR_NOMATCH 5 /* Version not match */
+#define HINIC_MGMT_STATUS_ERR_EXIST 6 /* Entry exists */
+#define HINIC_MGMT_STATUS_ERR_NOMEM 7 /* Out of memory */
+#define HINIC_MGMT_STATUS_ERR_INIT 8 /* Feature not initialized */
+#define HINIC_MGMT_STATUS_ERR_FAULT 9 /* Invalid address */
+#define HINIC_MGMT_STATUS_ERR_PERM 10 /* Operation not permitted */
+#define HINIC_MGMT_STATUS_ERR_EMPTY 11 /* Table empty */
+#define HINIC_MGMT_STATUS_ERR_FULL 12 /* Table full */
+#define HINIC_MGMT_STATUS_ERR_NOT_FOUND 13 /* Not found */
+#define HINIC_MGMT_STATUS_ERR_BUSY 14 /* Device or resource busy */
+#define HINIC_MGMT_STATUS_ERR_RESOURCE 15 /* No resources for operation */
+#define HINIC_MGMT_STATUS_ERR_CONFIG 16 /* Invalid configuration */
+#define HINIC_MGMT_STATUS_ERR_UNAVAIL 17 /* Feature unavailable */
+#define HINIC_MGMT_STATUS_ERR_CRC 18 /* CRC check failed */
+#define HINIC_MGMT_STATUS_ERR_NXIO 19 /* No such device or address */
+#define HINIC_MGMT_STATUS_ERR_ROLLBACK 20 /* Chip rollback fail */
+#define HINIC_MGMT_STATUS_ERR_LEN 32 /* Length too short or too long */
+#define HINIC_MGMT_STATUS_ERR_UNSUPPORT 0xFF/* Feature not supported*/
+
struct cfg_mgmt_info;
struct rdma_comp_resource;
@@ -193,7 +217,8 @@ struct hinic_heartbeat_enhanced {
HINIC_FUNC_SUPP_DFX_REG | \
HINIC_FUNC_SRIOV_EN_DFLT | \
HINIC_FUNC_SUPP_RX_MODE | \
- HINIC_FUNC_SUPP_CHANGE_MAC)
+ HINIC_FUNC_SUPP_CHANGE_MAC | \
+ HINIC_FUNC_OFFLOAD_OVS_UNSUPP)
#define MULTI_HOST_CHIP_MODE_SHIFT 0
#define MULTI_HOST_MASTER_MBX_STS_SHIFT 0x4
@@ -294,6 +319,8 @@ struct hinic_hwdev {
struct semaphore ppf_sem;
void *ppf_hwdev;
+ struct semaphore func_sem;
+ int func_ref;
struct hinic_board_info board_info;
#define MGMT_VERSION_MAX_LEN 32
u8 mgmt_ver[MGMT_VERSION_MAX_LEN];
@@ -347,8 +374,8 @@ int hinic_pf_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8
cmd,
void *buf_out, u16 *out_size, u32 timeout);
int hinic_pf_send_clp_cmd(void *hwdev, enum hinic_mod_type mod, u8 cmd,
- void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size);
+ void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
int hinic_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit);
@@ -379,4 +406,5 @@ int hinic_get_sdi_mode(struct hinic_hwdev *hwdev, u16 *cur_mode);
void mgmt_heartbeat_event_handler(void *hwdev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwif.c
b/drivers/net/ethernet/huawei/hinic/hinic_hwif.c
index fad2d6d9459d..260c61d19242 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hwif.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hwif.c
@@ -10,6 +10,7 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt
@@ -26,6 +27,7 @@
#include "hinic_csr.h"
#include "hinic_hwif.h"
+#include "hinic_eqs.h"
#define WAIT_HWIF_READY_TIMEOUT 10000
@@ -671,6 +673,108 @@ u16 hinic_global_func_id(void *hwdev)
}
EXPORT_SYMBOL(hinic_global_func_id);
+/*get function id from register,used by sriov hot migration process*/
+u16 hinic_global_func_id_hw(void *hwdev)
+{
+ u32 addr, attr0;
+ struct hinic_hwdev *dev;
+
+ dev = (struct hinic_hwdev *)hwdev;
+ addr = HINIC_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hinic_hwif_read_reg(dev->hwif, addr);
+
+ return HINIC_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+}
+
+static int func_busy_state_check(struct hinic_hwdev *hwdev)
+{
+ u32 func_state;
+ int cycle;
+
+ /*set BUSY before src vm suspend and clear it before dst vm resume*/
+ cycle = PIPE_CYCLE_MAX;
+ func_state = hinic_func_busy_state_get(hwdev);
+ while (func_state && cycle) {
+ msleep(20);
+ cycle--;
+ if (!cycle) {
+ sdk_err(hwdev->dev_hdl, "busy_state suspend timeout");
+ return -ETIMEDOUT;
+ }
+
+ func_state = hinic_func_busy_state_get(hwdev);
+ }
+
+ return 0;
+}
+
+int hinic_func_own_get(void *hwdev)
+{
+ struct hinic_hwdev *dev = (struct hinic_hwdev *)hwdev;
+ u32 func_state;
+ int err;
+
+ if (!HINIC_IS_VF(dev))
+ return 0;
+
+restart:
+ down(&dev->func_sem);
+
+ dev->func_ref++;
+ hinic_func_own_bit_set(dev, 1);
+
+ func_state = hinic_func_busy_state_get(hwdev);
+ if (func_state) {
+ dev->func_ref--;
+ if (dev->func_ref == 0)
+ hinic_func_own_bit_set(dev, 0);
+
+ up(&dev->func_sem);
+ err = func_busy_state_check(dev);
+ if (err)
+ return err;
+ goto restart;
+ }
+
+ up(&dev->func_sem);
+ return 0;
+}
+
+void hinic_func_own_free(void *hwdev)
+{
+ struct hinic_hwdev *dev = (struct hinic_hwdev *)hwdev;
+
+ if (!HINIC_IS_VF(dev))
+ return;
+
+ down(&dev->func_sem);
+ dev->func_ref--;
+ if (dev->func_ref == 0)
+ hinic_func_own_bit_set(dev, 0);
+
+ up(&dev->func_sem);
+}
+
+/*get function id, used by sriov hot migratition process.*/
+int hinic_global_func_id_get(void *hwdev, u16 *func_id)
+{
+ struct hinic_hwdev *dev = (struct hinic_hwdev *)hwdev;
+ int err;
+
+ /*only vf get func_id from chip reg for sriov migrate*/
+ if (!HINIC_IS_VF(dev)) {
+ *func_id = hinic_global_func_id(hwdev);
+ return 0;
+ }
+
+ err = func_busy_state_check(dev);
+ if (err)
+ return err;
+
+ *func_id = hinic_global_func_id_hw(dev);
+ return 0;
+}
+
u16 hinic_intr_num(void *hwdev)
{
struct hinic_hwif *hwif;
@@ -697,6 +801,18 @@ u8 hinic_pf_id_of_vf(void *hwdev)
}
EXPORT_SYMBOL(hinic_pf_id_of_vf);
+u16 hinic_pf_id_of_vf_hw(void *hwdev)
+{
+ u32 addr, attr0;
+ struct hinic_hwdev *dev;
+
+ dev = (struct hinic_hwdev *)hwdev;
+ addr = HINIC_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hinic_hwif_read_reg(dev->hwif, addr);
+
+ return HINIC_AF0_GET(attr0, P2P_IDX);
+}
+
u8 hinic_pcie_itf_id(void *hwdev)
{
struct hinic_hwif *hwif;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c
b/drivers/net/ethernet/huawei/hinic/hinic_lld.c
index 4260ed404c65..f653694dfbd6 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c
@@ -134,7 +134,6 @@ struct hinic_pcidev {
bool nic_cur_enable;
bool nic_des_enable;
};
-
#define HINIC_EVENT_PROCESS_TIMEOUT 10000
#define FIND_BIT(num, n) (((num) & (1UL << (n))) ? 1 : 0)
@@ -146,7 +145,7 @@ static u64 card_bit_map;
LIST_HEAD(g_hinic_chip_list);
struct hinic_uld_info g_uld_info[SERVICE_T_MAX] = { {0} };
static const char *s_uld_name[SERVICE_T_MAX] = {
- "nic", "ovs", "roce", "toe", "iwarp",
"fc", "fcoe", };
+ "nic", "ovs", "roce", "toe", "iwarp",
"fc", "fcoe", "migrate"};
enum hinic_lld_status {
HINIC_NODE_CHANGE = BIT(0),
@@ -276,7 +275,6 @@ static int attach_uld(struct hinic_pcidev *dev, enum
hinic_service_type type,
{
void *uld_dev = NULL;
int err;
-
mutex_lock(&dev->pdev_mutex);
if (dev->init_state < HINIC_INIT_STATE_HWDEV_INITED) {
@@ -702,12 +700,6 @@ struct mctp_hdr {
u8 spc_field;
};
-struct mctp_drv_info {
- struct mctp_hdr hdr; /* spc_field: driver is valid, alway 0 */
- u8 drv_name[32];
- u8 drv_ver[MAX_VER_SPLIT_NUM];
-};
-
struct mctp_bdf_info {
struct mctp_hdr hdr; /* spc_field: pf index */
u8 rsvd;
@@ -716,37 +708,13 @@ struct mctp_bdf_info {
u8 function;
};
-struct ipaddr_info {
- u8 ip[16];
- u8 prefix; /* netmask */
- u8 rsvd[3];
-};
-
-#define MCTP_HOST_MAX_IP_ADDR 8
-#define MCTP_IP_TYPE_V4 0U
-#define MCTP_IP_TYPE_V6 1U
-
-struct mctp_ipaddrs_info {
- struct mctp_hdr hdr; /* spc_field: pf index */
- u16 ip_cnt;
- u8 ip_type_bitmap;
- u8 rsvd;
-
- struct ipaddr_info ip[MCTP_HOST_MAX_IP_ADDR];
-};
-
enum mctp_resp_code {
/* COMMAND_COMPLETED = 0, */
- COMMAND_FAILED = 1,
+ /* COMMAND_FAILED = 1, */
/* COMMAND_UNAVALILABLE = 2, */
COMMAND_UNSUPPORTED = 3,
};
-enum mctp_reason_code {
- /* OEM_CMD_HEAD_INFO_INVALID = 0x8002, */
- OEM_GET_INFO_FAILED = 0x8003,
-};
-
static void __mctp_set_hdr(struct mctp_hdr *hdr,
struct hinic_mctp_host_info *mctp_info)
{
@@ -760,29 +728,6 @@ static void __mctp_set_hdr(struct mctp_hdr *hdr,
hdr->reason_code = cpu_to_be16(hdr->reason_code);
}
-static void __mctp_get_drv_info(struct hinic_pcidev *pci_adapter,
- struct hinic_mctp_host_info *mctp_info)
-{
- struct mctp_drv_info *drv_info = mctp_info->data;
- char ver_split[MAX_VER_SPLIT_NUM][MAX_VER_FIELD_LEN] = { {0} };
- int split_num = 0, split;
- u8 ver_i[MAX_VER_SPLIT_NUM] = {0};
- int drv_name_len;
-
- __version_split(HINIC_DRV_VERSION, &split_num, ver_split);
- for (split = 0; split < split_num; split++)
- ver_i[split] = (u8)local_atoi(ver_split[split]);
-
- drv_name_len = (int)strlen(HINIC_DRV_NAME);
- memcpy(drv_info->drv_name, HINIC_DRV_NAME, drv_name_len);
- memcpy(drv_info->drv_ver, ver_i, sizeof(drv_info->drv_ver));
-
- memset(&drv_info->hdr, 0, sizeof(drv_info->hdr));
- __mctp_set_hdr(&drv_info->hdr, mctp_info);
-
- mctp_info->data_len = sizeof(*drv_info);
-}
-
static void __mctp_get_bdf(struct hinic_pcidev *pci_adapter,
struct hinic_mctp_host_info *mctp_info)
{
@@ -795,100 +740,12 @@ static void __mctp_get_bdf(struct hinic_pcidev *pci_adapter,
memset(&bdf_info->hdr, 0, sizeof(bdf_info->hdr));
__mctp_set_hdr(&bdf_info->hdr, mctp_info);
- bdf_info->hdr.spc_field = (u8)hinic_global_func_id(pci_adapter->hwdev);
+ bdf_info->hdr.spc_field =
+ (u8)hinic_global_func_id_hw(pci_adapter->hwdev);
mctp_info->data_len = sizeof(*bdf_info);
}
-static void __copy_ipv6(u32 *dst, __be32 *src)
-{
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst = *src;
-}
-
-static void __mctp_get_ipaddr(struct hinic_pcidev *pci_adapter,
- struct hinic_mctp_host_info *mctp_info)
-{
- struct mctp_ipaddrs_info *ip_info = mctp_info->data;
- struct ipaddr_info *ip;
- struct hinic_nic_dev *nic_dev;
- struct net_device *netdev;
- struct in_device *in_dev;
- struct inet6_dev *in6_dev;
- struct inet6_ifaddr *ifp;
-#ifdef HAVE_INET6_IFADDR_LIST
- struct inet6_ifaddr *tmp;
-#endif
- u16 ip_cnt = 0;
- bool got_lock = true;
-
- memset(&ip_info->hdr, 0, sizeof(ip_info->hdr));
-
- nic_dev = pci_adapter->uld_dev[SERVICE_T_NIC];
- if (!hinic_support_nic(pci_adapter->hwdev, NULL) || !nic_dev) {
- ip_info->hdr.resp_code = COMMAND_FAILED;
- ip_info->hdr.reason_code = OEM_GET_INFO_FAILED;
- goto out;
- }
-
- netdev = nic_dev->netdev;
-
- if (!rtnl_trylock())
- got_lock = false;
-
- in_dev = in_dev_get(netdev);
- if (in_dev) {
- for_ifa(in_dev) {
- if (ip_cnt < MCTP_HOST_MAX_IP_ADDR) {
- ip = &ip_info->ip[ip_cnt];
- *((u32 *)(ip->ip)) = ifa->ifa_address;
- ip->prefix = ifa->ifa_prefixlen;
- ip_info->ip_type_bitmap |=
- (u8)(MCTP_IP_TYPE_V4 << ip_cnt);
- }
-
- ip_cnt++;
- } endfor_ifa(in_dev);
- in_dev_put(in_dev);
- }
-
- if (got_lock)
- rtnl_unlock();
-
- in6_dev = __in6_dev_get(netdev);
- if (!in6_dev)
- goto out;
-
- read_lock_bh(&in6_dev->lock);
-
-#ifdef HAVE_INET6_IFADDR_LIST
- list_for_each_entry_safe(ifp, tmp, &in6_dev->addr_list, if_list) {
-#else
- for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) {
-#endif
- if (ip_cnt < MCTP_HOST_MAX_IP_ADDR) {
- ip = &ip_info->ip[ip_cnt];
- __copy_ipv6((u32 *)(ip->ip), ifp->addr.in6_u.u6_addr32);
- ip->prefix = (u8)ifp->prefix_len;
- ip_info->ip_type_bitmap |=
- (u8)(MCTP_IP_TYPE_V6 << ip_cnt);
- }
-
- ip_cnt++;
- }
-
- read_unlock_bh(&in6_dev->lock);
-
-out:
- ip_info->ip_cnt = cpu_to_be16(ip_cnt);
- __mctp_set_hdr(&ip_info->hdr, mctp_info);
- ip_info->hdr.spc_field = (u8)hinic_global_func_id(pci_adapter->hwdev);
-
- mctp_info->data_len = sizeof(*ip_info);
-}
-
#define MCTP_MAJOR_CMD_PUBLIC 0x0
#define MCTP_MAJOR_CMD_NIC 0x1
@@ -907,14 +764,6 @@ static void __mctp_get_host_info(struct hinic_pcidev *dev,
__mctp_get_bdf(dev, mctp_info);
break;
- case (MCTP_MAJOR_CMD_PUBLIC << 8 | MCTP_PUBLIC_SUB_CMD_DRV):
- __mctp_get_drv_info(dev, mctp_info);
- break;
-
- case (MCTP_MAJOR_CMD_NIC << 8 | MCTP_NIC_SUB_CMD_IP):
- __mctp_get_ipaddr(dev, mctp_info);
- break;
-
default:
hdr = mctp_info->data;
hdr->reason_code = COMMAND_UNSUPPORTED;
@@ -924,7 +773,8 @@ static void __mctp_get_host_info(struct hinic_pcidev *dev,
}
}
-static bool __is_pcidev_match_chip_name(char *ifname, struct hinic_pcidev *dev,
+static bool __is_pcidev_match_chip_name(const char *ifname,
+ struct hinic_pcidev *dev,
struct card_node *chip_node,
enum func_type type)
{
@@ -1004,7 +854,8 @@ static struct hinic_pcidev *hinic_get_pcidev_by_chip_name(char
*ifname)
return NULL;
}
-static bool __is_pcidev_match_dev_name(char *ifname, struct hinic_pcidev *dev,
+static bool __is_pcidev_match_dev_name(const char *ifname,
+ struct hinic_pcidev *dev,
enum hinic_service_type type)
{
struct hinic_nic_dev *nic_dev;
@@ -1099,7 +950,7 @@ int hinic_get_chip_name_by_hwdev(void *hwdev, char *ifname)
}
EXPORT_SYMBOL(hinic_get_chip_name_by_hwdev);
-static struct card_node *hinic_get_chip_node_by_hwdev(void *hwdev)
+static struct card_node *hinic_get_chip_node_by_hwdev(const void *hwdev)
{
struct card_node *chip_node = NULL;
struct card_node *node_tmp = NULL;
@@ -1408,6 +1259,12 @@ void hinic_get_card_info(void *hwdev, void *bufin)
if (hinic_func_for_mgmt(fun_hwdev))
strlcpy(info->pf[i].name, "FOR_MGMT", IFNAMSIZ);
+ if (hinic_func_for_pt(fun_hwdev))
+ info->pf[i].pf_type |= (u32)BIT(SERVICE_T_PT);
+
+ if (hinic_func_for_hwpt(fun_hwdev))
+ info->pf[i].pf_type |= (u32)BIT(SERVICE_T_HWPT);
+
strlcpy(info->pf[i].bus_info, pci_name(dev->pcidev),
sizeof(info->pf[i].bus_info));
info->pf_num++;
@@ -1416,7 +1273,7 @@ void hinic_get_card_info(void *hwdev, void *bufin)
lld_dev_put();
}
-int hinic_get_card_func_info_by_card_name(char *chip_name,
+int hinic_get_card_func_info_by_card_name(const char *chip_name,
struct hinic_card_func_info
*card_func)
{
@@ -1767,16 +1624,20 @@ struct pci_device_id *hinic_get_pci_device_id(struct pci_dev
*pdev)
return &adapter->id;
}
+EXPORT_SYMBOL(hinic_get_pci_device_id);
static int __set_nic_func_state(struct hinic_pcidev *pci_adapter)
{
struct pci_dev *pdev = pci_adapter->pcidev;
+ u16 func_id;
int err;
bool enable_nic;
- err = hinic_get_func_nic_enable(pci_adapter->hwdev,
- hinic_global_func_id
- (pci_adapter->hwdev),
+ err = hinic_global_func_id_get(pci_adapter->hwdev, &func_id);
+ if (err)
+ return err;
+
+ err = hinic_get_func_nic_enable(pci_adapter->hwdev, func_id,
&enable_nic);
if (err) {
sdk_err(&pdev->dev, "Failed to get nic state\n");
@@ -1800,6 +1661,88 @@ static int __set_nic_func_state(struct hinic_pcidev *pci_adapter)
return 0;
}
+int hinic_ovs_set_vf_nic_state(struct hinic_lld_dev *lld_dev, u16 vf_func_id,
+ bool en)
+{
+ struct hinic_pcidev *dev, *des_dev;
+ struct hinic_nic_dev *uld_dev;
+ int err = -EFAULT;
+
+ if (!lld_dev)
+ return -EINVAL;
+
+ dev = pci_get_drvdata(lld_dev->pdev);
+
+ if (!dev)
+ return -EFAULT;
+ /* find func_idx pci_adapter and disable or enable nic */
+ lld_dev_hold();
+ list_for_each_entry(des_dev, &dev->chip_node->func_list, node) {
+ if (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag))
+ continue;
+
+ if (des_dev->init_state <
+ HINIC_INIT_STATE_DBGTOOL_INITED &&
+ !test_bit(HINIC_FUNC_PRB_ERR,
+ &des_dev->flag))
+ continue;
+
+ if (hinic_global_func_id(des_dev->hwdev) != vf_func_id)
+ continue;
+
+ if (des_dev->init_state <
+ HINIC_INIT_STATE_DBGTOOL_INITED) {
+ break;
+ }
+
+ sdk_info(&dev->pcidev->dev, "Receive event: %s vf%d nic\n",
+ en ? "enable" : "disable", vf_func_id);
+
+ err = 0;
+ if (en) {
+ if (des_dev->uld_dev[SERVICE_T_NIC]) {
+ sdk_err(&des_dev->pcidev->dev,
+ "%s driver has attached to pcie device, cannot set VF max_queue_num\n",
+ s_uld_name[SERVICE_T_NIC]);
+ } else {
+ err = hinic_set_vf_dev_cap(des_dev->hwdev);
+
+ if (err) {
+ sdk_err(&des_dev->pcidev->dev,
+ "%s driver Set VF max_queue_num failed, err=%d.\n",
+ s_uld_name[SERVICE_T_NIC], err);
+
+ break;
+ }
+ }
+
+ err = attach_uld(des_dev, SERVICE_T_NIC,
+ &g_uld_info[SERVICE_T_NIC]);
+ if (err) {
+ sdk_err(&des_dev->pcidev->dev, "Failed to initialize NIC\n");
+ break;
+ }
+
+ uld_dev = (struct hinic_nic_dev *)
+ (des_dev->uld_dev[SERVICE_T_NIC]);
+ uld_dev->in_vm = true;
+ uld_dev->is_vm_slave =
+ is_multi_vm_slave(uld_dev->hwdev);
+ if (des_dev->init_state < HINIC_INIT_STATE_NIC_INITED)
+ des_dev->init_state =
+ HINIC_INIT_STATE_NIC_INITED;
+ } else {
+ detach_uld(des_dev, SERVICE_T_NIC);
+ }
+
+ break;
+ }
+ lld_dev_put();
+
+ return err;
+}
+EXPORT_SYMBOL(hinic_ovs_set_vf_nic_state);
+
static void slave_host_mgmt_work(struct work_struct *work)
{
struct hinic_pcidev *pci_adapter =
@@ -1834,7 +1777,7 @@ static void __multi_host_mgmt(struct hinic_pcidev *dev,
&des_dev->flag))
continue;
- if (hinic_global_func_id(des_dev->hwdev) !=
+ if (hinic_global_func_id_hw(des_dev->hwdev) !=
nic_state->func_idx)
continue;
@@ -1843,7 +1786,6 @@ static void __multi_host_mgmt(struct hinic_pcidev *dev,
nic_state->status =
test_bit(HINIC_FUNC_PRB_ERR,
&des_dev->flag) ? 1 : 0;
-
break;
}
@@ -1923,7 +1865,7 @@ static int mapping_bar(struct pci_dev *pdev, struct hinic_pcidev
*pci_adapter)
dwqe_addr = pci_adapter->db_base_phy + HINIC_DB_DWQE_SIZE;
- /* arm do not support call ioremap_wc() */
+ /* arm do not support call ioremap_wc(), refer to */
pci_adapter->dwqe_mapping = __ioremap(dwqe_addr, HINIC_DB_DWQE_SIZE,
__pgprot(PROT_DEVICE_nGnRnE));
if (!pci_adapter->dwqe_mapping) {
@@ -2031,14 +1973,15 @@ static int alloc_chip_node(struct hinic_pcidev *pci_adapter)
static void free_chip_node(struct hinic_pcidev *pci_adapter)
{
struct card_node *chip_node = pci_adapter->chip_node;
- int id, err;
+ u32 id;
+ int err;
if (list_empty(&chip_node->func_list)) {
list_del(&chip_node->node);
sdk_info(&pci_adapter->pcidev->dev,
"Delete chip %s from global list succeed\n",
chip_node->chip_name);
- err = sscanf(chip_node->chip_name, HINIC_CHIP_NAME "%d", &id);
+ err = sscanf(chip_node->chip_name, HINIC_CHIP_NAME "%u", &id);
if (err < 0)
sdk_err(&pci_adapter->pcidev->dev, "Failed to get hinic id\n");
@@ -2081,19 +2024,16 @@ static bool hinic_get_vf_load_state(struct pci_dev *pdev)
return disable_vf_load;
}
-static void hinic_set_vf_load_state(struct hinic_pcidev *pci_adapter)
+static void hinic_set_vf_load_state(struct hinic_pcidev *pci_adapter,
+ bool vf_load_state)
{
struct card_node *chip_node;
- bool vf_load_state;
u16 func_id;
if (hinic_func_type(pci_adapter->hwdev) == TYPE_VF)
return;
- vf_load_state = hinic_support_ovs(pci_adapter->hwdev, NULL) ?
- true : disable_vf_load;
-
- func_id = hinic_global_func_id(pci_adapter->hwdev);
+ func_id = hinic_global_func_id_hw(pci_adapter->hwdev);
chip_node = pci_adapter->chip_node;
chip_node->disable_vf_load[func_id] = vf_load_state;
@@ -2104,6 +2044,27 @@ static void hinic_set_vf_load_state(struct hinic_pcidev
*pci_adapter)
(vf_load_state ? "disable" : "enable"));
}
+int hinic_ovs_set_vf_load_state(struct pci_dev *pdev)
+{
+ struct hinic_pcidev *pci_adapter;
+
+ if (!pdev) {
+ pr_err("pdev is null.\n");
+ return -EINVAL;
+ }
+
+ pci_adapter = pci_get_drvdata(pdev);
+ if (!pci_adapter) {
+ pr_err("pci_adapter is null.\n");
+ return -EFAULT;
+ }
+
+ hinic_set_vf_load_state(pci_adapter, disable_vf_load);
+
+ return 0;
+}
+EXPORT_SYMBOL(hinic_ovs_set_vf_load_state);
+
static int hinic_config_deft_mrss(struct pci_dev *pdev)
{
return 0;
@@ -2276,6 +2237,7 @@ static int hinic_func_init(struct pci_dev *pdev,
struct hinic_pcidev *pci_adapter)
{
struct hinic_init_para init_para;
+ bool vf_load_state;
int err;
init_para.adapter_hdl = pci_adapter;
@@ -2318,7 +2280,10 @@ static int hinic_func_init(struct pci_dev *pdev,
hinic_notify_ppf_reg(pci_adapter);
pci_adapter->init_state = HINIC_INIT_STATE_HWDEV_INITED;
- hinic_set_vf_load_state(pci_adapter);
+ vf_load_state = hinic_support_ovs(pci_adapter->hwdev, NULL) ?
+ true : disable_vf_load;
+
+ hinic_set_vf_load_state(pci_adapter, vf_load_state);
pci_adapter->lld_dev.pdev = pdev;
pci_adapter->lld_dev.hwdev = pci_adapter->hwdev;
@@ -2416,9 +2381,9 @@ static void hinic_func_deinit(struct pci_dev *pdev)
hinic_notify_ppf_unreg(pci_adapter);
if (pci_adapter->init_state >= HINIC_INIT_STATE_HW_IF_INITED) {
- /* Remove the current node from node-list first,
- * then it's safe to free hwdev
- */
+ /* Remove the current node from node-list first,
+ * then it's safe to free hwdev
+ */
lld_lock_chip_node();
list_del(&pci_adapter->node);
lld_unlock_chip_node();
@@ -2502,11 +2467,12 @@ static void hinic_remove(struct pci_dev *pdev)
case HINIC_INIT_STATE_HW_IF_INITED:
case HINIC_INIT_STATE_PCI_INITED:
set_bit(HINIC_FUNC_IN_REMOVE, &pci_adapter->flag);
- wait_tool_unused();
lld_lock_chip_node();
cancel_work_sync(&pci_adapter->slave_nic_work);
lld_unlock_chip_node();
+ wait_tool_unused();
+
if (pci_adapter->init_state >= HINIC_INIT_STATE_HW_IF_INITED)
hinic_func_deinit(pdev);
@@ -2570,11 +2536,12 @@ static void slave_host_init_delay_work(struct work_struct *work)
if (err)
set_bit(HINIC_FUNC_PRB_ERR, &pci_adapter->flag);
return;
+ } else {
+ queue_delayed_work(pci_adapter->slave_nic_init_workq,
+ &pci_adapter->slave_nic_init_dwork,
+ HINIC_SLAVE_NIC_DELAY_TIME);
+ return;
}
-
- queue_delayed_work(pci_adapter->slave_nic_init_workq,
- &pci_adapter->slave_nic_init_dwork,
- HINIC_SLAVE_NIC_DELAY_TIME);
}
static int hinic_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -2677,6 +2644,8 @@ static const struct pci_device_id hinic_pci_table[] = {
{PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_1822_KR_100GE), HINIC_BOARD_100GE},
{PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_1822_KR_25GE), HINIC_BOARD_25GE},
{PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_1822_MULTI_HOST), HINIC_BOARD_25GE},
+ {PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_1822_100GE), HINIC_BOARD_100GE},
+ {PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_1822_DUAL_25GE), HINIC_BOARD_25GE},
{0, 0}
};
@@ -2775,6 +2744,7 @@ static void __exit hinic_lld_exit(void)
pci_unregister_driver(&hinic_driver);
hinic_unregister_uld(SERVICE_T_NIC);
+
}
module_init(hinic_lld_init);
module_exit(hinic_lld_exit);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.h
b/drivers/net/ethernet/huawei/hinic/hinic_lld.h
index deaeb95d5345..844fb5f236d6 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_lld.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.h
@@ -109,6 +109,11 @@ void hinic_detach_roce(struct hinic_lld_dev *lld_dev);
int hinic_disable_nic_rss(struct hinic_lld_dev *lld_dev);
int hinic_enable_nic_rss(struct hinic_lld_dev *lld_dev);
+int hinic_ovs_set_vf_nic_state(struct hinic_lld_dev *lld_dev,
+ u16 vf_func_id, bool en);
+
+int hinic_ovs_set_vf_load_state(struct pci_dev *pdev);
+
int hinic_get_self_test_result(char *ifname, u32 *result);
enum hinic_init_state hinic_get_init_state_by_ifname(char *ifname);
enum hinic_init_state hinic_get_init_state(struct pci_dev *pdev);
@@ -117,5 +122,7 @@ extern struct hinic_uld_info g_uld_info[SERVICE_T_MAX];
struct pci_device_id *hinic_get_pci_device_id(struct pci_dev *pdev);
bool hinic_is_in_host(void);
+
bool hinic_is_valid_bar_addr(u64 offset);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c
b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 9fd3411b6c7d..a2238b97ccef 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -105,8 +105,23 @@ static unsigned char lro_en_status = HINIC_LRO_STATUS_UNSET;
module_param(lro_en_status, byte, 0444);
MODULE_PARM_DESC(lro_en_status, "lro enable status. 0 - disable, 1 - enable, other -
unset. (default unset)");
+static unsigned char qp_pending_limit_low = HINIC_RX_PENDING_LIMIT_LOW;
+module_param(qp_pending_limit_low, byte, 0444);
+MODULE_PARM_DESC(qp_pending_limit_low, "MSI-X adaptive low coalesce pending limit,
range is 0 - 255");
-static unsigned int enable_bp;/*lint !e728*/
+static unsigned char qp_coalesc_timer_low = HINIC_RX_COAL_TIME_LOW;
+module_param(qp_coalesc_timer_low, byte, 0444);
+MODULE_PARM_DESC(qp_coalesc_timer_low, "MSI-X adaptive low coalesce time, range is 0
- 255");
+
+static unsigned char qp_pending_limit_high = HINIC_RX_PENDING_LIMIT_HIGH;
+module_param(qp_pending_limit_high, byte, 0444);
+MODULE_PARM_DESC(qp_pending_limit_high, "MSI-X adaptive high coalesce pending limit,
range is 0 - 255");
+
+static unsigned char qp_coalesc_timer_high = HINIC_RX_COAL_TIME_HIGH;
+module_param(qp_coalesc_timer_high, byte, 0444);
+MODULE_PARM_DESC(qp_coalesc_timer_high, "MSI-X adaptive high coalesce time, range is
0 - 255");
+
+static unsigned int enable_bp;
static unsigned int bp_lower_thd = HINIC_RX_BP_LOWER_THD;
static unsigned int bp_upper_thd = HINIC_RX_BP_UPPER_THD;
@@ -445,6 +460,8 @@ int hinic_poll(struct napi_struct *napi, int budget)
HINIC_MSIX_ENABLE);
else if (!nic_dev->in_vm)
enable_irq(irq_cfg->irq_id);
+ } else {
+ hinic_rx_poll(irq_cfg->rxq, HINIC_RX_BUFFER_WRITE);
}
return max(tx_pkts, rx_pkts);
@@ -572,6 +589,12 @@ static void __calc_coal_para(struct hinic_nic_dev *nic_dev,
struct hinic_intr_coal_info *q_coal, u64 rate,
u8 *coalesc_timer_cfg, u8 *pending_limt)
{
+ if (nic_dev->is_vm_slave && nic_dev->in_vm) {
+ *coalesc_timer_cfg = HINIC_MULTI_VM_LATENCY;
+ *pending_limt = HINIC_MULTI_VM_PENDING_LIMIT;
+ return;
+ }
+
if (rate < q_coal->pkt_rate_low) {
*coalesc_timer_cfg = q_coal->rx_usecs_low;
*pending_limt = q_coal->rx_pending_limt_low;
@@ -609,6 +632,7 @@ static void hinic_auto_moderation_work(struct work_struct *work)
nic_dev->last_moder_jiffies);
u64 rx_packets, rx_bytes, rx_pkt_diff, rate, avg_pkt_size;
+ u64 tx_packets, tx_bytes, tx_pkt_diff, tx_rate;
u8 coalesc_timer_cfg, pending_limt;
u16 qid;
@@ -624,6 +648,8 @@ static void hinic_auto_moderation_work(struct work_struct *work)
for (qid = 0; qid < nic_dev->num_qps; qid++) {
rx_packets = nic_dev->rxqs[qid].rxq_stats.packets;
rx_bytes = nic_dev->rxqs[qid].rxq_stats.bytes;
+ tx_packets = nic_dev->txqs[qid].txq_stats.packets;
+ tx_bytes = nic_dev->txqs[qid].txq_stats.bytes;
q_coal = &nic_dev->intr_coalesce[qid];
rx_pkt_diff =
@@ -634,14 +660,24 @@ static void hinic_auto_moderation_work(struct work_struct *work)
rx_pkt_diff : 0;
rate = rx_pkt_diff * HZ / period;
+ tx_pkt_diff =
+ tx_packets - nic_dev->txqs[qid].last_moder_packets;
+ tx_rate = tx_pkt_diff * HZ / period;
if ((rate > HINIC_RX_RATE_THRESH &&
- avg_pkt_size > HINIC_AVG_PKT_SMALL) || nic_dev->in_vm) {
+ avg_pkt_size > HINIC_AVG_PKT_SMALL) ||
+ (nic_dev->in_vm && (rate > HINIC_RX_RATE_THRESH ||
+ (nic_dev->is_vm_slave &&
+ tx_rate > HINIC_TX_RATE_THRESH)))) {
__calc_coal_para(nic_dev, q_coal, rate,
&coalesc_timer_cfg, &pending_limt);
} else {
- coalesc_timer_cfg = HINIC_LOWEST_LATENCY;
- pending_limt = q_coal->rx_pending_limt_low;
+ coalesc_timer_cfg =
+ (nic_dev->is_vm_slave && nic_dev->in_vm) ?
+ 0 : HINIC_LOWEST_LATENCY;
+ pending_limt =
+ (nic_dev->is_vm_slave && nic_dev->in_vm) ?
+ 0 : q_coal->rx_pending_limt_low;
}
set_interrupt_moder(nic_dev, qid, coalesc_timer_cfg,
@@ -649,6 +685,8 @@ static void hinic_auto_moderation_work(struct work_struct *work)
nic_dev->rxqs[qid].last_moder_packets = rx_packets;
nic_dev->rxqs[qid].last_moder_bytes = rx_bytes;
+ nic_dev->txqs[qid].last_moder_packets = tx_packets;
+ nic_dev->txqs[qid].last_moder_bytes = tx_bytes;
}
nic_dev->last_moder_jiffies = jiffies;
@@ -1039,8 +1077,8 @@ static u16 select_queue_by_toeplitz(struct net_device *dev,
#if defined(HAVE_NDO_SELECT_QUEUE_ACCEL_FALLBACK)
#if defined(HAVE_NDO_SELECT_QUEUE_SB_DEV)
static u16 hinic_select_queue(struct net_device *netdev, struct sk_buff *skb,
- struct net_device *sb_dev,
- select_queue_fallback_t fallback)
+ struct net_device *sb_dev,
+ select_queue_fallback_t fallback)
#else
static u16 hinic_select_queue(struct net_device *netdev, struct sk_buff *skb,
__always_unused void *accel,
@@ -1084,7 +1122,7 @@ static u16 hinic_select_queue(struct net_device *netdev, struct
sk_buff *skb)
#ifdef HAVE_NDO_GET_STATS64
#ifdef HAVE_VOID_NDO_GET_STATS64
static void hinic_get_stats64(struct net_device *netdev,
- struct rtnl_link_stats64 *stats)
+ struct rtnl_link_stats64 *stats)
#else
static struct rtnl_link_stats64
*hinic_get_stats64(struct net_device *netdev,
@@ -1191,6 +1229,7 @@ static int hinic_set_mac_addr(struct net_device *netdev, void
*addr)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
struct sockaddr *saddr = addr;
+ u16 func_id;
int err;
if (!FUNC_SUPPORT_CHANGE_MAC(nic_dev->hwdev)) {
@@ -1209,8 +1248,12 @@ static int hinic_set_mac_addr(struct net_device *netdev, void
*addr)
return 0;
}
+ err = hinic_global_func_id_get(nic_dev->hwdev, &func_id);
+ if (err)
+ return err;
+
err = hinic_update_mac(nic_dev->hwdev, netdev->dev_addr, saddr->sa_data,
- 0, hinic_global_func_id(nic_dev->hwdev));
+ 0, func_id);
if (err)
return err;
@@ -1233,13 +1276,17 @@ hinic_vlan_rx_add_vid(struct net_device *netdev,
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
unsigned long *vlan_bitmap = nic_dev->vlan_bitmap;
- u16 func_id = hinic_global_func_id(nic_dev->hwdev);
+ u16 func_id;
u32 col, line;
int err;
col = VID_COL(nic_dev, vid);
line = VID_LINE(nic_dev, vid);
+ err = hinic_global_func_id_get(nic_dev->hwdev, &func_id);
+ if (err)
+ goto end;
+
err = hinic_add_vlan(nic_dev->hwdev, vid, func_id);
if (err) {
nicif_err(nic_dev, drv, netdev, "Failed to add vlan%d\n", vid);
@@ -1261,12 +1308,16 @@ hinic_vlan_rx_kill_vid(struct net_device *netdev,
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
unsigned long *vlan_bitmap = nic_dev->vlan_bitmap;
- u16 func_id = hinic_global_func_id(nic_dev->hwdev);
+ u16 func_id;
int err, col, line;
col = VID_COL(nic_dev, vid);
line = VID_LINE(nic_dev, vid);
+ err = hinic_global_func_id_get(nic_dev->hwdev, &func_id);
+ if (err)
+ goto end;
+
err = hinic_del_vlan(nic_dev->hwdev, vid, func_id);
if (err) {
nicif_err(nic_dev, drv, netdev, "Failed to delete vlan\n");
@@ -1409,7 +1460,7 @@ static int hinic_set_default_hw_feature(struct hinic_nic_dev
*nic_dev)
if (set_link_status_follow < HINIC_LINK_FOLLOW_STATUS_MAX &&
FUNC_SUPPORT_PORT_SETTING(nic_dev->hwdev)) {
err = hinic_set_link_status_follow(nic_dev->hwdev,
- set_link_status_follow);
+ set_link_status_follow);
if (err == HINIC_MGMT_CMD_UNSUPPORTED)
nic_warn(&nic_dev->pdev->dev,
"Current version of firmware don't support to set link status follow port
status\n");
@@ -1481,21 +1532,33 @@ static void hinic_netpoll(struct net_device *netdev)
static int hinic_uc_sync(struct net_device *netdev, u8 *addr)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ u16 func_id;
+ int err;
- return hinic_set_mac(nic_dev->hwdev, addr, 0,
- hinic_global_func_id(nic_dev->hwdev));
+ err = hinic_global_func_id_get(nic_dev->hwdev, &func_id);
+ if (err)
+ return err;
+
+ err = hinic_set_mac(nic_dev->hwdev, addr, 0, func_id);
+ return err;
}
static int hinic_uc_unsync(struct net_device *netdev, u8 *addr)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ u16 func_id;
+ int err;
/* The addr is in use */
if (ether_addr_equal(addr, netdev->dev_addr))
return 0;
- return hinic_del_mac(nic_dev->hwdev, addr, 0,
- hinic_global_func_id(nic_dev->hwdev));
+ err = hinic_global_func_id_get(nic_dev->hwdev, &func_id);
+ if (err)
+ return err;
+
+ err = hinic_del_mac(nic_dev->hwdev, addr, 0, func_id);
+ return err;
}
static void hinic_clean_mac_list_filter(struct hinic_nic_dev *nic_dev)
@@ -2164,14 +2227,14 @@ static void netdev_feature_init(struct net_device *netdev)
}
#define MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, out_qps) { \
- if ((num_qps) > (nic_dev)->max_qps) \
+ if ((num_qps) > nic_dev->max_qps) \
nic_warn(&nic_dev->pdev->dev, \
"Module Parameter %s value %d is out of range, "\
"Maximum value for the device: %d, using %d\n",\
- #num_qps, num_qps, (nic_dev)->max_qps, \
- (nic_dev)->max_qps); \
- if (!(num_qps) || (num_qps) > (nic_dev)->max_qps) \
- out_qps = (nic_dev)->max_qps; \
+ #num_qps, num_qps, nic_dev->max_qps, \
+ nic_dev->max_qps); \
+ if (!(num_qps) || (num_qps) > nic_dev->max_qps) \
+ out_qps = nic_dev->max_qps; \
else \
out_qps = num_qps; \
}
@@ -2197,8 +2260,12 @@ static void hinic_try_to_enable_rss(struct hinic_nic_dev *nic_dev)
err = hinic_rss_template_alloc(nic_dev->hwdev, &nic_dev->rss_tmpl_idx);
if (err) {
- nic_err(&nic_dev->pdev->dev,
- "Failed to alloc tmpl_idx for rss, can't enable rss for this
function\n");
+ if (err == -ENOSPC)
+ nic_warn(&nic_dev->pdev->dev,
+ "Failed to alloc tmpl_idx for rss, table is full\n");
+ else
+ nic_err(&nic_dev->pdev->dev,
+ "Failed to alloc tmpl_idx for rss, can't enable rss for this
function\n");
clear_bit(HINIC_RSS_ENABLE, &nic_dev->flags);
nic_dev->max_qps = 1;
nic_dev->rss_limit = nic_dev->max_qps;
@@ -2244,6 +2311,7 @@ static void hinic_try_to_enable_rss(struct hinic_nic_dev *nic_dev)
static int hinic_sw_init(struct hinic_nic_dev *adapter)
{
struct net_device *netdev = adapter->netdev;
+ u16 func_id;
int err = 0;
sema_init(&adapter->port_state_sem, 1);
@@ -2285,8 +2353,11 @@ static int hinic_sw_init(struct hinic_nic_dev *adapter)
eth_hw_addr_random(netdev);
}
- err = hinic_set_mac(adapter->hwdev, netdev->dev_addr, 0,
- hinic_global_func_id(adapter->hwdev));
+ err = hinic_global_func_id_get(adapter->hwdev, &func_id);
+ if (err)
+ goto func_id_err;
+
+ err = hinic_set_mac(adapter->hwdev, netdev->dev_addr, 0, func_id);
/* When this is VF driver, we must consider that PF has already set VF
* MAC, and we can't consider this condition is error status during
* driver probe procedure.
@@ -2309,6 +2380,7 @@ static int hinic_sw_init(struct hinic_nic_dev *adapter)
return 0;
set_mac_err:
+func_id_err:
err_mac:
get_mac_err:
if (test_bit(HINIC_RSS_ENABLE, &adapter->flags))
@@ -2405,16 +2477,20 @@ static void init_intr_coal_param(struct hinic_nic_dev *nic_dev)
info->resend_timer_cfg =
HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
info->pkt_rate_high = HINIC_RX_RATE_HIGH;
- info->rx_usecs_high = HINIC_RX_COAL_TIME_HIGH;
- info->rx_pending_limt_high = HINIC_RX_PENDING_LIMIT_HIGH;
+ info->rx_usecs_high = qp_coalesc_timer_high;
+ info->rx_pending_limt_high = qp_pending_limit_high;
info->pkt_rate_low = HINIC_RX_RATE_LOW;
- info->rx_usecs_low = HINIC_RX_COAL_TIME_LOW;
- info->rx_pending_limt_low = HINIC_RX_PENDING_LIMIT_LOW;
+ info->rx_usecs_low = qp_coalesc_timer_low;
+ info->rx_pending_limt_low = qp_pending_limit_low;
if (nic_dev->in_vm) {
+ if (qp_pending_limit_high ==
+ HINIC_RX_PENDING_LIMIT_HIGH)
+ qp_pending_limit_high =
+ HINIC_RX_PENDING_LIMIT_HIGH_VM;
info->pkt_rate_low = HINIC_RX_RATE_LOW_VM;
info->rx_pending_limt_high =
- HINIC_RX_PENDING_LIMIT_HIGH_VM;
+ qp_pending_limit_high;
}
}
}
@@ -2523,6 +2599,20 @@ static int hinic_validate_parameters(struct hinic_lld_dev
*lld_dev)
rx_buff = DEFAULT_RX_BUFF_LEN;
}
+ if (qp_coalesc_timer_high <= qp_coalesc_timer_low) {
+ nic_warn(&pdev->dev, "Module Parameter qp_coalesc_timer_high: %d,
qp_coalesc_timer_low: %d is invalid, resetting to default\n",
+ qp_coalesc_timer_high, qp_coalesc_timer_low);
+ qp_coalesc_timer_high = HINIC_RX_COAL_TIME_HIGH;
+ qp_coalesc_timer_low = HINIC_RX_COAL_TIME_LOW;
+ }
+
+ if (qp_pending_limit_high <= qp_pending_limit_low) {
+ nic_warn(&pdev->dev, "Module Parameter qp_pending_limit_high: %d,
qp_pending_limit_low: %d is invalid, resetting to default\n",
+ qp_pending_limit_high, qp_pending_limit_low);
+ qp_pending_limit_high = HINIC_RX_PENDING_LIMIT_HIGH;
+ qp_pending_limit_low = HINIC_RX_PENDING_LIMIT_LOW;
+ }
+
return 0;
}
@@ -2723,6 +2813,7 @@ static int nic_probe(struct hinic_lld_dev *lld_dev, void **uld_dev,
nic_dev->msg_enable = DEFAULT_MSG_ENABLE;
nic_dev->heart_status = true;
nic_dev->in_vm = !hinic_is_in_host();
+ nic_dev->is_vm_slave = is_multi_vm_slave(lld_dev->hwdev);
nic_dev->lro_replenish_thld = lro_replenish_thld;
nic_dev->rx_buff_len = (u16)(rx_buff * CONVERT_UNIT);
page_num = (RX_BUFF_NUM_PER_PAGE * nic_dev->rx_buff_len) / PAGE_SIZE;
@@ -2812,7 +2903,7 @@ static int nic_probe(struct hinic_lld_dev *lld_dev, void **uld_dev,
alloc_qps_err:
hinic_del_mac(nic_dev->hwdev, netdev->dev_addr, 0,
- hinic_global_func_id(nic_dev->hwdev));
+ hinic_global_func_id_hw(nic_dev->hwdev));
sw_init_err:
(void)hinic_set_super_cqe_state(nic_dev->hwdev, false);
@@ -2851,7 +2942,7 @@ static void nic_remove(struct hinic_lld_dev *lld_dev, void
*adapter)
hinic_clean_mac_list_filter(nic_dev);
hinic_del_mac(nic_dev->hwdev, netdev->dev_addr, 0,
- hinic_global_func_id(nic_dev->hwdev));
+ hinic_global_func_id_hw(nic_dev->hwdev));
if (test_bit(HINIC_RSS_ENABLE, &nic_dev->flags))
hinic_rss_template_free(nic_dev->hwdev, nic_dev->rss_tmpl_idx);
@@ -2927,7 +3018,12 @@ int hinic_enable_func_rss(struct hinic_nic_dev *nic_dev)
err = hinic_rss_template_alloc(nic_dev->hwdev, &nic_dev->rss_tmpl_idx);
if (err) {
- nicif_err(nic_dev, drv, netdev, "Failed to alloc RSS template\n");
+ if (err == -ENOSPC)
+ nicif_warn(nic_dev, drv, netdev,
+ "Failed to alloc RSS template,table is full\n");
+ else
+ nicif_err(nic_dev, drv, netdev,
+ "Failed to alloc RSS template\n");
} else {
set_bit(HINIC_RSS_ENABLE, &nic_dev->flags);
nicif_info(nic_dev, drv, netdev, "Success to alloc RSS template\n");
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mbox.c
b/drivers/net/ethernet/huawei/hinic/hinic_mbox.c
index bbefb5ef12cb..da8d590f1a62 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_mbox.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_mbox.c
@@ -207,7 +207,7 @@ struct hinic_set_random_id {
};
static bool check_func_id(struct hinic_hwdev *hwdev, u16 src_func_idx,
- void *buf_in, u16 in_size, u16 offset)
+ const void *buf_in, u16 in_size, u16 offset)
{
u16 func_idx;
@@ -402,7 +402,7 @@ void hinic_unregister_vf_mbox_cb(struct hinic_hwdev *hwdev,
clear_bit(HINIC_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]);
while (test_bit(HINIC_VF_MBOX_CB_RUNNING,
- &func_to_func->vf_mbox_cb_state[mod]))
+ &func_to_func->vf_mbox_cb_state[mod]))
usleep_range(900, 1000);
func_to_func->vf_mbox_cb[mod] = NULL;
@@ -495,7 +495,7 @@ recv_pf_from_ppf_handler(struct hinic_mbox_func_to_func
*func_to_func,
recv_mbox->mbox, recv_mbox->mbox_len,
buf_out, out_size);
} else {
- sdk_warn(func_to_func->hwdev->dev_hdl, "PF receive ppf mailbox callback is
not registered\n");
+ sdk_warn(func_to_func->hwdev->dev_hdl, "PF recvice ppf mailbox callback is
not registered\n");
ret = -EINVAL;
}
@@ -659,11 +659,11 @@ static void recv_func_mbox_handler(struct hinic_mbox_func_to_func
*func_to_func,
buf_out, out_size, src_func_idx,
HINIC_HWIF_RESPONSE, MBOX_ACK,
&msg_info);
- } else {
- kfree(recv_mbox->buf_out);
- kfree(recv_mbox->mbox);
- kfree(recv_mbox);
}
+
+ kfree(recv_mbox->buf_out);
+ kfree(recv_mbox->mbox);
+ kfree(recv_mbox);
}
static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
@@ -717,7 +717,7 @@ static void recv_mbox_handler(struct hinic_mbox_func_to_func
*func_to_func,
{
u64 mbox_header = *((u64 *)header);
void *mbox_body = MBOX_BODY_FROM_HDR(header);
- struct hinic_recv_mbox *asyc_rcv_mbox = NULL;
+ struct hinic_recv_mbox *rcv_mbox_temp = NULL;
u16 src_func_idx;
struct hinic_mbox_work *mbox_work;
int pos;
@@ -756,43 +756,34 @@ static void recv_mbox_handler(struct hinic_mbox_func_to_func
*func_to_func,
return;
}
- if (recv_mbox->ack_type == MBOX_NO_ACK) {
- asyc_rcv_mbox = kzalloc(sizeof(*asyc_rcv_mbox), GFP_KERNEL);
- if (!asyc_rcv_mbox) {
- sdk_err(func_to_func->hwdev->dev_hdl, "Allocate asynchronous receive mbox
memory failed.\n");
- return;
- }
- memcpy(asyc_rcv_mbox, recv_mbox, sizeof(*asyc_rcv_mbox));
+ rcv_mbox_temp = kzalloc(sizeof(*rcv_mbox_temp), GFP_KERNEL);
+ if (!rcv_mbox_temp) {
+ sdk_err(func_to_func->hwdev->dev_hdl, "Allocate receive mbox memory
failed.\n");
+ return;
+ }
+ memcpy(rcv_mbox_temp, recv_mbox, sizeof(*rcv_mbox_temp));
- asyc_rcv_mbox->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
- if (!asyc_rcv_mbox->mbox) {
- sdk_err(func_to_func->hwdev->dev_hdl, "Allocate asynchronous receive mbox
message memory failed.\n");
- goto asyc_rcv_mbox_msg_err;
- }
- memcpy(asyc_rcv_mbox->mbox, recv_mbox->mbox, MBOX_MAX_BUF_SZ);
+ rcv_mbox_temp->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
+ if (!rcv_mbox_temp->mbox) {
+ sdk_err(func_to_func->hwdev->dev_hdl, "Allocate receive mbox message memory
failed.\n");
+ goto rcv_mbox_msg_err;
+ }
+ memcpy(rcv_mbox_temp->mbox, recv_mbox->mbox, MBOX_MAX_BUF_SZ);
- asyc_rcv_mbox->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
- if (!asyc_rcv_mbox->buf_out) {
- sdk_err(func_to_func->hwdev->dev_hdl, "Allocate asynchronous receive mbox
out buffer memory failed.\n");
- goto asyc_rcv_mbox_buf_err;
- }
+ rcv_mbox_temp->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
+ if (!rcv_mbox_temp->buf_out) {
+ sdk_err(func_to_func->hwdev->dev_hdl, "Allocate receive mbox out buffer
memory failed.\n");
+ goto rcv_mbox_buf_err;
}
mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL);
if (!mbox_work) {
sdk_err(func_to_func->hwdev->dev_hdl, "Allocate mbox work memory
failed.\n");
- if (recv_mbox->ack_type == MBOX_NO_ACK)
- goto mbox_work_err;
- else
- return;
+ goto mbox_work_err;
}
mbox_work->func_to_func = func_to_func;
-
- if (recv_mbox->ack_type == MBOX_NO_ACK)
- mbox_work->recv_mbox = asyc_rcv_mbox;
- else
- mbox_work->recv_mbox = recv_mbox;
+ mbox_work->recv_mbox = rcv_mbox_temp;
mbox_work->src_func_idx = src_func_idx;
INIT_WORK(&mbox_work->work, recv_func_mbox_work_handler);
@@ -801,13 +792,13 @@ static void recv_mbox_handler(struct hinic_mbox_func_to_func
*func_to_func,
return;
mbox_work_err:
- kfree(asyc_rcv_mbox->buf_out);
+ kfree(rcv_mbox_temp->buf_out);
-asyc_rcv_mbox_buf_err:
- kfree(asyc_rcv_mbox->mbox);
+rcv_mbox_buf_err:
+ kfree(rcv_mbox_temp->mbox);
-asyc_rcv_mbox_msg_err:
- kfree(asyc_rcv_mbox);
+rcv_mbox_msg_err:
+ kfree(rcv_mbox_temp);
}
int set_vf_mbox_random_id(struct hinic_hwdev *hwdev, u16 func_id)
@@ -978,6 +969,13 @@ static void mbox_copy_send_data(struct hinic_hwdev *hwdev,
u32 *data = seg;
u32 data_len, chk_sz = sizeof(u32);
u32 i, idx_max;
+ u8 mbox_max_buf[MBOX_SEG_LEN] = {0};
+
+ /* The mbox message should be aligned in 4 bytes. */
+ if (seg_len % chk_sz) {
+ memcpy(mbox_max_buf, seg, seg_len);
+ data = (u32 *)mbox_max_buf;
+ }
data_len = seg_len;
idx_max = ALIGN(data_len, chk_sz) / chk_sz;
@@ -1124,7 +1122,7 @@ static int send_mbox_to_func(struct hinic_mbox_func_to_func
*func_to_func,
{
struct hinic_hwdev *hwdev = func_to_func->hwdev;
int err = 0;
- int seq_id = 0;
+ u32 seq_id = 0;
u16 seg_len = MBOX_SEG_LEN;
u16 left = msg_len;
u8 *msg_seg = (u8 *)msg;
@@ -1143,7 +1141,7 @@ static int send_mbox_to_func(struct hinic_mbox_func_to_func
*func_to_func,
/* The vf's offset to it's associated pf */
HINIC_MBOX_HEADER_SET(msg_info->msg_id, MSG_ID) |
HINIC_MBOX_HEADER_SET(msg_info->status, STATUS) |
- HINIC_MBOX_HEADER_SET(hinic_global_func_id(hwdev),
+ HINIC_MBOX_HEADER_SET(hinic_global_func_id_hw(hwdev),
SRC_GLB_FUNC_IDX);
while (!(HINIC_MBOX_HEADER_GET(header, LAST))) {
@@ -1335,10 +1333,16 @@ int hinic_mbox_to_pf(struct hinic_hwdev *hwdev,
return -EINVAL;
}
+ err = hinic_func_own_get(hwdev);
+ if (err)
+ return err;
+
/* port_to_port_idx - imply which PCIE interface PF is connected */
- return hinic_mbox_to_func(func_to_func, mod, cmd,
- hinic_pf_id_of_vf(hwdev), buf_in, in_size,
- buf_out, out_size, timeout);
+ err = hinic_mbox_to_func(func_to_func, mod, cmd,
+ hinic_pf_id_of_vf_hw(hwdev), buf_in, in_size,
+ buf_out, out_size, timeout);
+ hinic_func_own_free(hwdev);
+ return err;
}
int hinic_mbox_to_func_no_ack(struct hinic_hwdev *hwdev, u16 func_idx,
@@ -1367,8 +1371,16 @@ int hinic_mbox_to_func_no_ack(struct hinic_hwdev *hwdev, u16
func_idx,
int hinic_mbox_to_pf_no_ack(struct hinic_hwdev *hwdev, enum hinic_mod_type mod,
u8 cmd, void *buf_in, u16 in_size)
{
- return hinic_mbox_to_func_no_ack(hwdev, hinic_pf_id_of_vf(hwdev), mod,
- cmd, buf_in, in_size);
+ int err;
+
+ err = hinic_func_own_get(hwdev);
+ if (err)
+ return err;
+
+ err = hinic_mbox_to_func_no_ack(hwdev, hinic_pf_id_of_vf_hw(hwdev),
+ mod, cmd, buf_in, in_size);
+ hinic_func_own_free(hwdev);
+ return err;
}
int __hinic_mbox_to_vf(void *hwdev,
@@ -1409,9 +1421,8 @@ int __hinic_mbox_to_vf(void *hwdev,
}
int hinic_mbox_ppf_to_vf(void *hwdev,
- enum hinic_mod_type mod, u16 func_id, u8 cmd,
- void *buf_in, u16 in_size, void *buf_out,
- u16 *out_size, u32 timeout)
+ enum hinic_mod_type mod, u16 func_id, u8 cmd, void *buf_in,
+ u16 in_size, void *buf_out, u16 *out_size, u32 timeout)
{
struct hinic_mbox_func_to_func *func_to_func;
int err;
@@ -1581,8 +1592,7 @@ int hinic_vf_mbox_random_id_init(struct hinic_hwdev *hwdev)
for (vf_in_pf = 1; vf_in_pf <= hinic_func_max_vf(hwdev); vf_in_pf++) {
err = set_vf_mbox_random_id(hwdev,
- (hinic_glb_pf_vf_offset(hwdev) +
- vf_in_pf));
+ (hinic_glb_pf_vf_offset(hwdev) + vf_in_pf));
if (err)
break;
}
@@ -1656,6 +1666,9 @@ int hinic_func_to_func_init(struct hinic_hwdev *hwdev)
destroy_workqueue(func_to_func->workq);
create_mbox_workq_err:
+ spin_lock_deinit(&func_to_func->mbox_lock);
+ sema_deinit(&func_to_func->msg_send_sem);
+ sema_deinit(&func_to_func->mbox_send_sem);
kfree(func_to_func);
return err;
@@ -1671,9 +1684,7 @@ void hinic_func_to_func_free(struct hinic_hwdev *hwdev)
destroy_workqueue(func_to_func->workq);
free_mbox_wb_status(func_to_func);
-
free_mbox_info(func_to_func->mbox_resp);
-
free_mbox_info(func_to_func->mbox_send);
spin_lock_deinit(&func_to_func->mbox_lock);
sema_deinit(&func_to_func->mbox_send_sem);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mbox.h
b/drivers/net/ethernet/huawei/hinic/hinic_mbox.h
index c55d32394f9e..a54639d0df0d 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_mbox.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_mbox.h
@@ -215,12 +215,12 @@ int hinic_mbox_to_pf_no_ack(struct hinic_hwdev *hwdev, enum
hinic_mod_type mod,
int hinic_mbox_ppf_to_pf(struct hinic_hwdev *hwdev, enum hinic_mod_type mod,
u16 dst_pf_id, u8 cmd,
- void *buf_in, u16 in_size, void *buf_out,
- u16 *out_size, u32 timeout);
+ 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);
+ 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(void *hwdev,
enum hinic_mod_type mod, u16 vf_id, u8 cmd, void *buf_in,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mgmt.c
b/drivers/net/ethernet/huawei/hinic/hinic_mgmt.c
index 5543f1f22bfb..6a2c10923033 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_mgmt.c
@@ -34,6 +34,8 @@
#include "hinic_hwif.h"
#include "hinic_api_cmd.h"
#include "hinic_mgmt.h"
+#include "hinic_nic_cfg.h"
+#include "hinic_mgmt_interface.h"
#include "hinic_eqs.h"
#define BUF_OUT_DEFAULT_SIZE 1
@@ -219,7 +221,7 @@ static u16 mgmt_msg_len(u16 msg_data_len)
* @msg_id: message id
**/
static void prepare_header(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
- u64 *header, int msg_len, enum hinic_mod_type mod,
+ u64 *header, u16 msg_len, enum hinic_mod_type mod,
enum hinic_msg_ack_type ack_type,
enum hinic_msg_direction_type direction,
enum hinic_mgmt_cmd cmd, u32 msg_id)
@@ -241,11 +243,10 @@ static void prepare_header(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
}
static void clp_prepare_header(struct hinic_hwdev *hwdev,
- u64 *header, int msg_len,
- enum hinic_mod_type mod,
- enum hinic_msg_ack_type ack_type,
- enum hinic_msg_direction_type direction,
- enum hinic_mgmt_cmd cmd, u32 msg_id)
+ u64 *header, u16 msg_len, enum hinic_mod_type mod,
+ enum hinic_msg_ack_type ack_type,
+ enum hinic_msg_direction_type direction,
+ enum hinic_mgmt_cmd cmd, u32 msg_id)
{
struct hinic_hwif *hwif = hwdev->hwif;
@@ -270,7 +271,7 @@ static void clp_prepare_header(struct hinic_hwdev *hwdev,
* @msg: the data of the message
* @msg_len: the length of the message
**/
-static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, void *msg,
+static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, const void *msg,
int msg_len)
{
memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
@@ -392,16 +393,25 @@ static int send_msg_to_mgmt_sync(struct hinic_msg_pf_to_mgmt
*pf_to_mgmt,
int hinic_pf_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd,
void *buf_in, u16 in_size, void *buf_out,
- u16 *out_size, u32 timeout)
+ u16 *out_size, u32 timeout)
{
struct hinic_msg_pf_to_mgmt *pf_to_mgmt;
void *dev = ((struct hinic_hwdev *)hwdev)->dev_hdl;
struct hinic_recv_msg *recv_msg;
+ struct hinic_msg_head *msg_head;
struct completion *recv_done;
ulong timeo;
int err;
ulong ret;
+ /* set aeq fix num to 3, need to ensure response aeq id < 3*/
+ if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC) {
+ msg_head = buf_in;
+
+ if (msg_head->resp_aeq_num >= HINIC_MAX_AEQS)
+ msg_head->resp_aeq_num = 0;
+ }
+
pf_to_mgmt = ((struct hinic_hwdev *)hwdev)->pf_to_mgmt;
/* Lock the sync_msg_buf */
@@ -462,7 +472,7 @@ int hinic_pf_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8
cmd,
}
static int __get_clp_reg(void *hwdev, enum clp_data_type data_type,
- enum clp_reg_type reg_type, u32 *reg_addr)
+ enum clp_reg_type reg_type, u32 *reg_addr)
{
struct hinic_hwdev *dev = hwdev;
u32 offset;
@@ -506,8 +516,8 @@ static int __get_clp_reg(void *hwdev, enum clp_data_type data_type,
}
static int hinic_read_clp_reg(struct hinic_hwdev *hwdev,
- enum clp_data_type data_type,
- enum clp_reg_type reg_type, u32 *read_value)
+ enum clp_data_type data_type,
+ enum clp_reg_type reg_type, u32 *read_value)
{
int err;
u32 reg_addr, reg_value;
@@ -636,7 +646,7 @@ static void hinic_write_clp_reg(struct hinic_hwdev *hwdev,
}
static int hinic_read_clp_data(struct hinic_hwdev *hwdev,
- void *buf_out, u16 *out_size)
+ void *buf_out, u16 *out_size)
{
int err;
u32 reg = HINIC_CLP_DATA(RSP);
@@ -762,7 +772,7 @@ static int hinic_check_clp_init_status(struct hinic_hwdev *hwdev)
}
static void hinic_clear_clp_data(struct hinic_hwdev *hwdev,
- enum clp_data_type data_type)
+ enum clp_data_type data_type)
{
u32 reg = (data_type == HINIC_CLP_REQ_HOST) ?
HINIC_CLP_DATA(REQ) : HINIC_CLP_DATA(RSP);
@@ -775,8 +785,8 @@ static void hinic_clear_clp_data(struct hinic_hwdev *hwdev,
}
int hinic_pf_clp_to_mgmt(void *hwdev, enum hinic_mod_type mod, u8 cmd,
- void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size)
+ const void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
{
struct hinic_clp_pf_to_mgmt *clp_pf_to_mgmt;
struct hinic_hwdev *dev = hwdev;
@@ -1004,7 +1014,7 @@ static void mgmt_recv_msg_handler(struct hinic_msg_pf_to_mgmt
*pf_to_mgmt,
if (!pf_to_mgmt->recv_mgmt_msg_cb[mod] ||
!test_bit(HINIC_MGMT_MSG_CB_REG,
- &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod])) {
+ &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod])) {
sdk_warn(dev, "Receive mgmt callback is null, mod = %d\n",
mod);
clear_bit(HINIC_MGMT_MSG_CB_RUNNING,
@@ -1093,7 +1103,6 @@ static bool check_mgmt_seq_id_and_seg_len(struct hinic_recv_msg
*recv_msg,
} else {
if (seq_id != recv_msg->seq_id + 1)
return false;
-
recv_msg->seq_id = seq_id;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mgmt.h
b/drivers/net/ethernet/huawei/hinic/hinic_mgmt.h
index 9411d50462bd..38f747004518 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_mgmt.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_mgmt.h
@@ -57,7 +57,6 @@ enum clp_data_type {
HINIC_CLP_REQ_HOST = 0,
HINIC_CLP_RSP_HOST = 1
};
-
enum clp_reg_type {
HINIC_CLP_BA_HOST = 0,
HINIC_CLP_SIZE_HOST = 1,
@@ -65,7 +64,6 @@ enum clp_reg_type {
HINIC_CLP_START_REQ_HOST = 3,
HINIC_CLP_READY_RSP_HOST = 4
};
-
#define HINIC_CLP_REG_GAP (0x20)
#define HINIC_CLP_INPUT_BUFFER_LEN_HOST (2048UL)
#define HINIC_CLP_OUTPUT_BUFFER_LEN_HOST (2048UL)
@@ -202,7 +200,7 @@ struct hinic_msg_pf_to_mgmt {
struct comm_up_self_msg_info proc;
- /* spinlock when sending msg */
+ /* lock when sending msg */
spinlock_t sync_event_lock;
enum comm_pf_to_mgmt_event_state event_flag;
};
@@ -238,8 +236,8 @@ int hinic_pf_to_mgmt_async(void *hwdev, enum hinic_mod_type mod,
u8 cmd, void *buf_in, u16 in_size);
int hinic_pf_clp_to_mgmt(void *hwdev, enum hinic_mod_type mod, u8 cmd,
- void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size);
+ const void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
int hinic_clp_pf_to_mgmt_init(struct hinic_hwdev *hwdev);
void hinic_clp_pf_to_mgmt_free(struct hinic_hwdev *hwdev);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h
b/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h
index 14efbe1449f3..13bc351a0902 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h
@@ -24,6 +24,13 @@
/* up to driver event */
#define HINIC_PORT_CMD_MGMT_RESET 0x0
+struct hinic_msg_head {
+ u8 status;
+ u8 version;
+ u8 resp_aeq_num;
+ u8 rsvd0[5];
+};
+
struct hinic_register_vf {
u8 status;
u8 version;
@@ -909,12 +916,10 @@ struct hinic_link_ksettings_info {
u8 fec; /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */
u8 rsvd2[18]; /* reserved for duplex, port, etc. */
};
-
enum hinic_tx_promsic {
HINIC_TX_PROMISC_ENABLE = 0,
HINIC_TX_PROMISC_DISABLE = 1,
};
-
struct hinic_promsic_info {
u8 status;
u8 version;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_multi_host_mgmt.c
b/drivers/net/ethernet/huawei/hinic/hinic_multi_host_mgmt.c
index 05523596f3a8..aad4b2c38a4b 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_multi_host_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_multi_host_mgmt.c
@@ -63,18 +63,20 @@ void set_slave_host_enable(struct hinic_hwdev *hwdev, u8 host_id, bool
enable)
host_id, enable, reg_val);
}
-bool get_slave_host_enable(struct hinic_hwdev *hwdev, u8 host_id)
+bool hinic_get_slave_host_enable(void *hwdev, u8 host_id)
{
u32 reg_val;
+ struct hinic_hwdev *dev = hwdev;
- if (HINIC_FUNC_TYPE(hwdev) != TYPE_PPF)
+ if (HINIC_FUNC_TYPE(dev) != TYPE_PPF)
return false;
- reg_val = hinic_hwif_read_reg(hwdev->hwif,
+ reg_val = hinic_hwif_read_reg(dev->hwif,
HINIC_MULT_HOST_SLAVE_STATUS_ADDR);
return SLAVE_HOST_STATUS_GET(host_id, reg_val);
}
+EXPORT_SYMBOL(hinic_get_slave_host_enable);
void set_master_host_mbox_enable(struct hinic_hwdev *hwdev, bool enable)
{
@@ -138,6 +140,16 @@ void set_func_host_mode(struct hinic_hwdev *hwdev, enum
hinic_func_mode mode)
}
}
+bool is_multi_vm_slave(void *hwdev)
+{
+ struct hinic_hwdev *hw_dev = hwdev;
+
+ if (!hwdev)
+ return false;
+
+ return (hw_dev->func_mode == FUNC_MOD_MULTI_VM_SLAVE) ? true : false;
+}
+
int rectify_host_mode(struct hinic_hwdev *hwdev)
{
u16 cur_sdi_mode;
@@ -304,7 +316,7 @@ int sw_func_pf_mbox_handler(void *handle, u16 vf_id, u8 cmd, void
*buf_in,
int err;
switch (cmd) {
- case HINIC_SW_GET_SLAVE_FUNC_NIC_STATE:
+ case HINIC_SW_CMD_GET_SLAVE_FUNC_NIC_STATE:
nic_state = buf_in;
out_state = buf_out;
*out_size = sizeof(*nic_state);
@@ -416,8 +428,7 @@ static int multi_host_event_handler(struct hinic_hwdev *hwdev,
}
static int sw_fwd_msg_to_vf(struct hinic_hwdev *hwdev,
- void *buf_in, u16 in_size,
- void *buf_out, u16 *out_size)
+ void *buf_in, u16 in_size, void *buf_out, u16 *out_size)
{
struct hinic_host_fwd_head *fwd_head;
u16 fwd_head_len;
@@ -428,9 +439,9 @@ static int sw_fwd_msg_to_vf(struct hinic_hwdev *hwdev,
fwd_head_len = sizeof(struct hinic_host_fwd_head);
msg = (void *)((u8 *)buf_in + fwd_head_len);
err = hinic_mbox_ppf_to_vf(hwdev, fwd_head->mod,
- fwd_head->dst_glb_func_idx, fwd_head->cmd,
- msg, (in_size - fwd_head_len),
- buf_out, out_size, 0);
+ fwd_head->dst_glb_func_idx, fwd_head->cmd,
+ msg, (in_size - fwd_head_len),
+ buf_out, out_size, 0);
if (err)
nic_err(hwdev->dev_hdl,
"Fwd msg to func %u failed, err: %d\n",
@@ -438,7 +449,6 @@ static int sw_fwd_msg_to_vf(struct hinic_hwdev *hwdev,
return err;
}
-
static int __slave_host_sw_func_handler(struct hinic_hwdev *hwdev, u16 pf_idx,
u8 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
@@ -473,9 +483,12 @@ static int __slave_host_sw_func_handler(struct hinic_hwdev *hwdev,
u16 pf_idx,
case HINIC_SW_CMD_SEND_MSG_TO_VF:
err = sw_fwd_msg_to_vf(hwdev, buf_in, in_size,
- buf_out, out_size);
+ buf_out, out_size);
break;
+ case HINIC_SW_CMD_MIGRATE_READY:
+ hinic_migrate_report(hwdev);
+ break;
default:
err = -EINVAL;
break;
@@ -515,8 +528,7 @@ int __ppf_process_mbox_msg(struct hinic_hwdev *hwdev, u16 pf_idx, u16
vf_id,
if (IS_SLAVE_HOST(hwdev)) {
err = hinic_mbox_to_host_sync(hwdev, mod, cmd,
- buf_in, in_size, buf_out,
- out_size, 0);
+ buf_in, in_size, buf_out, out_size, 0);
if (err)
sdk_err(hwdev->dev_hdl, "send to mpf failed, err: %d\n",
err);
@@ -751,7 +763,7 @@ int hinic_set_func_nic_state(void *hwdev, struct hinic_func_nic_state
*state)
return -EFAULT;
}
- host_enable = get_slave_host_enable(hwdev, host_id);
+ host_enable = hinic_get_slave_host_enable(hwdev, host_id);
sdk_info(ppf_hwdev->dev_hdl, "Set slave host %d(status: %d) func %d %s
nic\n",
host_id, host_enable,
state->func_idx, state->state ? "enable" : "disable");
@@ -801,18 +813,23 @@ int hinic_get_func_nic_enable(void *hwdev, u16 glb_func_idx, bool
*en)
if (!hwdev || !en)
return -EINVAL;
-
+ /*if card mode is OVS, VFs donot need attach_uld, so return false.*/
if (!IS_SLAVE_HOST((struct hinic_hwdev *)hwdev)) {
- *en = true;
+ if (hinic_func_type(hwdev) == TYPE_VF &&
+ hinic_support_ovs(hwdev, NULL)) {
+ *en = false;
+ } else {
+ *en = true;
+ }
return 0;
}
if (hinic_func_type(hwdev) == TYPE_VF) {
nic_state.func_idx = glb_func_idx;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_SW_FUNC,
- HINIC_SW_GET_SLAVE_FUNC_NIC_STATE,
- &nic_state, sizeof(nic_state),
- &nic_state, &out_size, 0);
+ HINIC_SW_CMD_GET_SLAVE_FUNC_NIC_STATE,
+ &nic_state, sizeof(nic_state),
+ &nic_state, &out_size, 0);
if (err || !out_size || nic_state.status) {
sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, "Failed to get func %d nic
state, err: %d, out_size: 0x%x, status: 0x%x\n",
glb_func_idx, err, out_size, nic_state.status);
@@ -861,11 +878,16 @@ int hinic_multi_host_mgmt_init(struct hinic_hwdev *hwdev)
/* master ppf idx fix to 0 */
hwdev->mhost_mgmt->mhost_ppf_idx = 0;
- /* fix slave host ppf 6 and host 2 in bmwg mode
- * TODO: get ppf_idx and host_idx according to pf_infos
- */
- hwdev->mhost_mgmt->shost_ppf_idx = 6;
- hwdev->mhost_mgmt->shost_host_idx = 2;
+ if (IS_BMGW_MASTER_HOST(hwdev) || IS_BMGW_SLAVE_HOST(hwdev)) {
+ /* fix slave host ppf 6 and host 2 in bmwg mode
+ * TODO: get ppf_idx and host_idx according to pf_infos
+ */
+ hwdev->mhost_mgmt->shost_ppf_idx = 6;
+ hwdev->mhost_mgmt->shost_host_idx = 2;
+ } else {
+ hwdev->mhost_mgmt->shost_ppf_idx = 7;
+ hwdev->mhost_mgmt->shost_host_idx = 2;
+ }
hinic_register_ppf_mbox_cb(hwdev, HINIC_MOD_COMM,
comm_ppf_mbox_handler);
@@ -885,10 +907,16 @@ int hinic_multi_host_mgmt_init(struct hinic_hwdev *hwdev)
if (IS_SLAVE_HOST(hwdev)) {
/* PXE don't support to receive mbox from master host */
set_slave_host_enable(hwdev, hinic_pcie_itf_id(hwdev), true);
- if (IS_BMGW_SLAVE_HOST(hwdev)) {
+ if ((IS_VM_SLAVE_HOST(hwdev) &&
+ hinic_get_master_host_mbox_enable(hwdev)) ||
+ IS_BMGW_SLAVE_HOST(hwdev)) {
err = hinic_register_slave_ppf(hwdev, true);
- if (err)
+ if (err) {
+ set_slave_host_enable(hwdev,
+ hinic_pcie_itf_id(hwdev),
+ false);
goto out_free_mhost_mgmt;
+ }
}
} else {
/* slave host can send message to mgmt cpu after setup master
@@ -912,8 +940,7 @@ int hinic_multi_host_mgmt_free(struct hinic_hwdev *hwdev)
return 0;
if (IS_SLAVE_HOST(hwdev)) {
- if (IS_BMGW_SLAVE_HOST(hwdev))
- hinic_register_slave_ppf(hwdev, false);
+ hinic_register_slave_ppf(hwdev, false);
set_slave_host_enable(hwdev, hinic_pcie_itf_id(hwdev), false);
} else {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic.h
b/drivers/net/ethernet/huawei/hinic/hinic_nic.h
index be68f3cc5fef..7e9256354493 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic.h
@@ -41,6 +41,8 @@ struct hinic_rq {
u32 irq_id;
u16 msix_entry_idx;
+
+ dma_addr_t cqe_dma_addr;
};
struct hinic_qp {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c
b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c
index 56d6da9948c7..d7796d9dc1b8 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c
@@ -35,6 +35,7 @@
#include "hinic_nic.h"
#include "hinic_mgmt_interface.h"
#include "hinic_hwif.h"
+#include "hinic_eqs.h"
static unsigned char set_vf_link_state;
module_param(set_vf_link_state, byte, 0444);
@@ -150,8 +151,11 @@ int hinic_init_function_table(void *hwdev, u16 rx_buf_sz)
if (!hwdev)
return -EINVAL;
+ err = hinic_global_func_id_get(hwdev, &function_table.func_id);
+ if (err)
+ return err;
+
function_table.version = HINIC_CMD_VER_FUNC_ID;
- function_table.func_id = hinic_global_func_id(hwdev);
function_table.mtu = 0x3FFF; /* default, max mtu */
function_table.rx_wqe_buf_size = rx_buf_sz;
@@ -178,7 +182,9 @@ int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
if (!hwdev || !global_qpn)
return -EINVAL;
- cmd_qpn.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &cmd_qpn.func_id);
+ if (err)
+ return err;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
HINIC_PORT_CMD_GET_GLOBAL_QPN,
@@ -196,6 +202,7 @@ int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
return 0;
}
+#define HINIC_ADD_VLAN_IN_MAC 0x8000
#define HINIC_VLAN_ID_MASK 0x7FFF
int hinic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id)
@@ -332,6 +339,55 @@ int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16
vlan_id,
return 0;
}
+int hinic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
+{
+ struct hinic_hwdev *dev = hwdev;
+ struct vf_data_storage *vf_info;
+ u16 func_id, vlan_id;
+ int err;
+
+ if (!hwdev || !old_vlan || !new_vlan)
+ return -EINVAL;
+
+ vf_info = dev->nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+ if (!vf_info->pf_set_mac)
+ return 0;
+
+ func_id = hinic_glb_pf_vf_offset(dev) + (u16)vf_id;
+ vlan_id = old_vlan;
+ if (vlan_id)
+ vlan_id |= HINIC_ADD_VLAN_IN_MAC;
+ err = hinic_del_mac(dev, vf_info->vf_mac_addr, vlan_id,
+ func_id);
+ if (err) {
+ nic_err(dev->dev_hdl, "Failed to delete VF %d MAC %pM vlan %d\n",
+ HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, vlan_id);
+ return err;
+ }
+
+ vlan_id = new_vlan;
+ if (vlan_id)
+ vlan_id |= HINIC_ADD_VLAN_IN_MAC;
+ err = hinic_set_mac(dev, vf_info->vf_mac_addr, vlan_id,
+ func_id);
+ if (err) {
+ nic_err(dev->dev_hdl, "Failed to add VF %d MAC %pM vlan %d\n",
+ HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, vlan_id);
+ goto out;
+ }
+
+ return 0;
+
+out:
+ vlan_id = old_vlan;
+ if (vlan_id)
+ vlan_id |= HINIC_ADD_VLAN_IN_MAC;
+ hinic_set_mac(dev, vf_info->vf_mac_addr, vlan_id,
+ func_id);
+
+ return err;
+}
+
int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
{
struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
@@ -342,11 +398,13 @@ int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
if (!hwdev || !mac_addr)
return -EINVAL;
- mac_info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &mac_info.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC,
&mac_info, sizeof(mac_info),
- &mac_info, &out_size);
+ &mac_info, &out_size);
if (err || !out_size || mac_info.status) {
nic_err(nic_hwdev->dev_hdl,
"Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",
@@ -380,7 +438,10 @@ int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
return -EINVAL;
}
- mtu_info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &mtu_info.func_id);
+ if (err)
+ return err;
+
mtu_info.mtu = new_mtu;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
@@ -457,7 +518,10 @@ int hinic_enable_netq(void *hwdev, u8 en)
if (!hwdev)
return -EINVAL;
- netq_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &netq_cfg.func_id);
+ if (err)
+ return err;
+
netq_cfg.netq_en = en;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_NETQ,
@@ -500,8 +564,11 @@ int hinic_add_hw_rqfilter(void *hwdev, struct hinic_rq_filter_info
*filter_info)
return -EINVAL;
}
+ err = hinic_global_func_id_get(hwdev, &filter_msg.func_id);
+ if (err)
+ return err;
+
filter_msg.filter_type = filter_info->filter_type;
- filter_msg.func_id = hinic_global_func_id(hwdev);
filter_msg.qid = filter_info->qid;
filter_msg.qflag = filter_info->qflag;
@@ -547,8 +614,11 @@ int hinic_del_hw_rqfilter(void *hwdev, struct hinic_rq_filter_info
*filter_info)
return -EINVAL;
}
+ err = hinic_global_func_id_get(hwdev, &filter_msg.func_id);
+ if (err)
+ return err;
+
filter_msg.filter_type = filter_info->filter_type;
- filter_msg.func_id = hinic_global_func_id(hwdev);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_RQ_FILTER,
&filter_msg, sizeof(filter_msg),
@@ -628,7 +698,9 @@ int hinic_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl)
if (!hwdev)
return -EINVAL;
- vlan_filter.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &vlan_filter.func_id);
+ if (err)
+ return err;
vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
@@ -659,11 +731,13 @@ int hinic_get_port_info(void *hwdev, struct nic_port_info
*port_info)
if (!hwdev || !port_info)
return -EINVAL;
- port_msg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &port_msg.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
&port_msg, sizeof(port_msg),
- &port_msg, &out_size);
+ &port_msg, &out_size);
if (err || !out_size || port_msg.status) {
nic_err(nic_hwdev->dev_hdl,
"Failed to get port info, err: %d, status: 0x%x, out size: 0x%x\n",
@@ -691,7 +765,10 @@ int hinic_set_autoneg(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- autoneg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &autoneg.func_id);
+ if (err)
+ return err;
+
autoneg.enable = enable;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_AUTONEG,
@@ -739,7 +816,9 @@ int hinic_get_link_mode(void *hwdev, enum hinic_link_mode *supported,
if (!hwdev || !supported || !advertised)
return -EINVAL;
- link_mode.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &link_mode.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
&link_mode, sizeof(link_mode),
@@ -767,7 +846,10 @@ int hinic_set_port_link_status(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- link_status.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &link_status.func_id);
+ if (err)
+ return err;
+
link_status.enable = enable;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_LINK_STATUS,
@@ -793,7 +875,10 @@ int hinic_set_speed(void *hwdev, enum nic_speed_level speed)
if (!hwdev)
return -EINVAL;
- speed_info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &speed_info.func_id);
+ if (err)
+ return err;
+
speed_info.speed = speed;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_SPEED,
@@ -819,7 +904,9 @@ int hinic_get_speed(void *hwdev, enum nic_speed_level *speed)
if (!hwdev || !speed)
return -EINVAL;
- speed_info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &speed_info.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_SPEED,
&speed_info, sizeof(speed_info),
@@ -851,7 +938,9 @@ int hinic_get_link_state(void *hwdev, u8 *link_state)
return 0;
}
- get_link.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &get_link.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
&get_link, sizeof(get_link),
@@ -878,7 +967,10 @@ static int hinic_set_hw_pause_info(void *hwdev,
if (!hwdev)
return -EINVAL;
- pause_info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &pause_info.func_id);
+ if (err)
+ return err;
+
pause_info.auto_neg = nic_pause.auto_neg;
pause_info.rx_pause = nic_pause.rx_pause;
pause_info.tx_pause = nic_pause.tx_pause;
@@ -936,7 +1028,9 @@ int hinic_get_hw_pause_info(void *hwdev, struct nic_pause_config
*nic_pause)
if (!hwdev || !nic_pause)
return -EINVAL;
- pause_info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &pause_info.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
&pause_info, sizeof(pause_info),
@@ -982,7 +1076,10 @@ int hinic_set_rx_mode(void *hwdev, u32 enable)
if (!hwdev)
return -EINVAL;
- rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &rx_mode_cfg.func_id);
+ if (err)
+ return err;
+
rx_mode_cfg.rx_mode = enable;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
@@ -1008,7 +1105,10 @@ int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
if (!hwdev)
return -EINVAL;
- vlan_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &vlan_cfg.func_id);
+ if (err)
+ return err;
+
vlan_cfg.vlan_rx_offload = en;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
@@ -1033,7 +1133,10 @@ int hinic_set_rx_csum_offload(void *hwdev, u32 en)
if (!hwdev)
return -EINVAL;
- rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &rx_csum_cfg.func_id);
+ if (err)
+ return err;
+
rx_csum_cfg.rx_csum_offload = en;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
@@ -1058,7 +1161,10 @@ int hinic_set_tx_tso(void *hwdev, u8 tso_en)
if (!hwdev)
return -EINVAL;
- tso_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &tso_cfg.func_id);
+ if (err)
+ return err;
+
tso_cfg.tso_en = tso_en;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_TSO,
@@ -1144,7 +1250,10 @@ int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8
max_wqe_num)
if (!hwdev)
return -EINVAL;
- lro_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &lro_cfg.func_id);
+ if (err)
+ return err;
+
lro_cfg.lro_ipv4_en = ipv4_en;
lro_cfg.lro_ipv6_en = ipv6_en;
lro_cfg.lro_max_wqe_num = max_wqe_num;
@@ -1168,9 +1277,12 @@ static int hinic_dcb_set_hw_pfc(void *hwdev, u8 pfc_en, u8
pfc_bitmap)
u16 out_size = sizeof(pfc);
int err;
+ err = hinic_global_func_id_get(hwdev, &pfc.func_id);
+ if (err)
+ return err;
+
pfc.pfc_bitmap = pfc_bitmap;
pfc.pfc_en = pfc_en;
- pfc.func_id = hinic_global_func_id(hwdev);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PFC,
&pfc, sizeof(pfc), &pfc, &out_size);
@@ -1306,7 +1418,12 @@ int hinic_dcb_set_rq_iq_mapping(void *hwdev, u32 num_rqs, u8 *map)
dev = hwdev;
nic_io = dev->nic_io;
- rq_iq_mapping.func_id = hinic_global_func_id(hwdev);
+ hinic_qps_num_set(dev, nic_io->num_qps);
+
+ err = hinic_global_func_id_get(hwdev, &rq_iq_mapping.func_id);
+ if (err)
+ return err;
+
rq_iq_mapping.num_rqs = num_rqs;
rq_iq_mapping.rq_depth = (u16)ilog2(nic_io->rq_depth);
@@ -1323,6 +1440,7 @@ int hinic_dcb_set_rq_iq_mapping(void *hwdev, u32 num_rqs, u8 *map)
return 0;
}
+EXPORT_SYMBOL(hinic_dcb_set_rq_iq_mapping);
int hinic_set_pfc_threshold(void *hwdev, u16 op_type, u16 threshold)
{
@@ -1337,7 +1455,10 @@ int hinic_set_pfc_threshold(void *hwdev, u16 op_type, u16
threshold)
else
return -EINVAL;
- pfc_thd.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &pfc_thd.func_id);
+ if (err)
+ return err;
+
pfc_thd.op_type = op_type;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PFC_THD,
@@ -1468,7 +1589,9 @@ int hinic_get_rx_lro(void *hwdev, struct nic_lro_info *cfg)
if (!hwdev || !cfg)
return -EINVAL;
- lro_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &lro_cfg.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LRO,
&lro_cfg, sizeof(lro_cfg),
@@ -1577,7 +1700,10 @@ int hinic_set_vport_enable(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- en_state.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &en_state.func_id);
+ if (err)
+ return err;
+
en_state.state = enable ? 1 : 0;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
@@ -1608,8 +1734,11 @@ int hinic_set_port_enable(void *hwdev, bool enable)
if (HINIC_IS_VF(nic_hwdev))
return 0;
+ err = hinic_global_func_id_get(hwdev, &en_state.func_id);
+ if (err)
+ return err;
+
en_state.version = HINIC_CMD_VER_FUNC_ID;
- en_state.func_id = hinic_global_func_id(hwdev);
en_state.state = enable ? NIC_PORT_ENABLE : NIC_PORT_DISABLE;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
@@ -1691,7 +1820,10 @@ int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct
nic_rss_type *rss_type)
if (!hwdev || !rss_type)
return -EINVAL;
- ctx_tbl.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &ctx_tbl.func_id);
+ if (err)
+ return err;
+
ctx_tbl.template_id = (u8)tmpl_idx;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
@@ -1726,7 +1858,10 @@ int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, const u8
*temp)
if (!hwdev || !temp)
return -EINVAL;
- temp_key.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &temp_key.func_id);
+ if (err)
+ return err;
+
temp_key.template_id = (u8)tmpl_idx;
memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
@@ -1752,7 +1887,10 @@ int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8
*temp)
if (!hwdev || !temp)
return -EINVAL;
- temp_key.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &temp_key.func_id);
+ if (err)
+ return err;
+
temp_key.template_id = (u8)tmpl_idx;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
@@ -1779,7 +1917,10 @@ int hinic_rss_get_hash_engine(void *hwdev, u8 tmpl_idx, u8 *type)
if (!hwdev || !type)
return -EINVAL;
- hash_type.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &hash_type.func_id);
+ if (err)
+ return err;
+
hash_type.template_id = tmpl_idx;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,
@@ -1805,7 +1946,10 @@ int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
if (!hwdev)
return -EINVAL;
- hash_type.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &hash_type.func_id);
+ if (err)
+ return err;
+
hash_type.hash_engine = type;
hash_type.template_id = tmpl_idx;
@@ -1826,7 +1970,7 @@ int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, const u32
*indir_table)
struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
struct nic_rss_indirect_tbl *indir_tbl;
struct hinic_cmd_buf *cmd_buf;
- int i;
+ u32 i;
u32 *temp;
u32 indir_size;
u64 out_param;
@@ -1896,7 +2040,10 @@ int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32
*indir_table)
u16 out_size = sizeof(rss_cfg);
int err = 0, i;
- rss_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &rss_cfg.func_id);
+ if (err)
+ return err;
+
rss_cfg.template_id = (u8)tmpl_idx;
err = l2nic_msg_to_mgmt_sync(hwdev,
@@ -1927,7 +2074,10 @@ int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num,
u8 *prio_tc)
if (!hwdev || !prio_tc || (tc_num & (tc_num - 1)))
return -EINVAL;
- rss_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &rss_cfg.func_id);
+ if (err)
+ return err;
+
rss_cfg.rss_en = rss_en;
rss_cfg.template_id = tmpl_idx;
rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
@@ -1953,8 +2103,11 @@ int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats
*stats)
u16 out_size = sizeof(vport_stats);
int err;
+ err = hinic_global_func_id_get(hwdev, &stats_info.func_id);
+ if (err)
+ return err;
+
stats_info.stats_version = HINIC_PORT_STATS_VERSION;
- stats_info.func_id = hinic_global_func_id(hwdev);
stats_info.stats_size = sizeof(vport_stats);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
@@ -2087,13 +2240,20 @@ int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
if (!hwdev || !tmpl_idx)
return -EINVAL;
- template_mgmt.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &template_mgmt.func_id);
+ if (err)
+ return err;
+
template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
&template_mgmt, sizeof(template_mgmt),
&template_mgmt, &out_size);
if (err || !out_size || template_mgmt.status) {
+ if (template_mgmt.status == HINIC_MGMT_STATUS_ERR_FULL) {
+ nic_warn(nic_hwdev->dev_hdl, "Failed to alloc rss template, table is
full\n");
+ return -ENOSPC;
+ }
nic_err(nic_hwdev->dev_hdl, "Failed to alloc rss template, err: %d, status:
0x%x, out size: 0x%x\n",
err, template_mgmt.status, out_size);
return -EINVAL;
@@ -2114,7 +2274,10 @@ int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
if (!hwdev)
return -EINVAL;
- template_mgmt.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &template_mgmt.func_id);
+ if (err)
+ return err;
+
template_mgmt.template_id = tmpl_idx;
template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
@@ -2140,7 +2303,10 @@ int hinic_set_port_funcs_state(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- state.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &state.func_id);
+ if (err)
+ return err;
+
state.drop_en = enable ? 0 : 1;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_FUNCS_STATE,
@@ -2162,7 +2328,9 @@ int hinic_reset_port_link_cfg(void *hwdev)
u16 out_size = sizeof(reset_cfg);
int err;
- reset_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &reset_cfg.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
&reset_cfg, sizeof(reset_cfg),
@@ -2207,6 +2375,11 @@ static int hinic_change_vf_mtu_msg_handler(struct hinic_hwdev
*hwdev, u16 vf_id,
return 0;
}
+static bool is_ether_addr_zero(const u8 *addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
static int hinic_get_vf_mac_msg_handler(struct hinic_nic_io *nic_io, u16 vf,
void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
@@ -2215,10 +2388,18 @@ static int hinic_get_vf_mac_msg_handler(struct hinic_nic_io
*nic_io, u16 vf,
struct hinic_port_mac_set *mac_info = buf_out;
int err;
- if (nic_io->hwdev->func_mode == FUNC_MOD_MULTI_BM_SLAVE) {
+ if (nic_io->hwdev->func_mode == FUNC_MOD_MULTI_BM_SLAVE ||
+ nic_io->hwdev->func_mode == FUNC_MOD_MULTI_VM_SLAVE ||
+ (hinic_support_ovs(nic_io->hwdev, NULL))) {
err = hinic_pf_msg_to_mgmt_sync(nic_io->hwdev, HINIC_MOD_L2NIC,
HINIC_PORT_CMD_GET_MAC, buf_in,
in_size, buf_out, out_size, 0);
+
+ if (!err) {
+ if (is_ether_addr_zero(&mac_info->mac[0]))
+ memcpy(mac_info->mac,
+ vf_info->vf_mac_addr, ETH_ALEN);
+ }
return err;
}
@@ -2360,13 +2541,17 @@ static int hinic_set_vf_vlan(struct hinic_hwdev *hwdev, bool add,
u16 vid,
static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id)
{
struct vf_data_storage *vf_info;
- u16 func_id;
+ u16 func_id, vlan_id;
int err = 0;
vf_info = hwdev->nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
if (vf_info->pf_set_mac) {
func_id = hinic_glb_pf_vf_offset(hwdev) + vf_id;
- err = hinic_set_mac(hwdev, vf_info->vf_mac_addr, 0, func_id);
+ vlan_id = vf_info->pf_vlan;
+ if (vlan_id)
+ vlan_id |= HINIC_ADD_VLAN_IN_MAC;
+ err = hinic_set_mac(hwdev, vf_info->vf_mac_addr, vlan_id,
+ func_id);
if (err) {
nic_err(hwdev->dev_hdl, "Failed to set VF %d MAC\n",
HW_VF_ID_TO_OS(vf_id));
@@ -2774,7 +2959,8 @@ int hinic_kill_vf_vlan(void *hwdev, int vf_id)
err = hinic_set_vf_vlan(hw_dev, false,
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,
- nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos, vf_id);
+ nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos,
+ vf_id);
if (err)
return err;
@@ -3247,7 +3433,10 @@ int hinic_set_anti_attack(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- rate.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &rate.func_id);
+ if (err)
+ return err;
+
rate.enable = enable;
rate.cir = ANTI_ATTACK_DEFAULT_CIR;
rate.xir = ANTI_ATTACK_DEFAULT_XIR;
@@ -3277,7 +3466,12 @@ int hinic_flush_sq_res(void *hwdev)
u16 out_size = sizeof(sq_res);
int err;
- sq_res.func_id = hinic_global_func_id(hwdev);
+ if (!hwdev)
+ return -EINVAL;
+
+ err = hinic_global_func_id_get(hwdev, &sq_res.func_id);
+ if (err)
+ return err;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_SQ_RES,
&sq_res, sizeof(sq_res), &sq_res,
@@ -3290,6 +3484,7 @@ int hinic_flush_sq_res(void *hwdev)
return 0;
}
+EXPORT_SYMBOL(hinic_flush_sq_res);
static int __set_pf_bw(struct hinic_hwdev *hwdev, u8 speed_level);
@@ -3336,7 +3531,10 @@ int hinic_set_super_cqe_state(void *hwdev, bool enable)
if (!hwdev)
return -EINVAL;
- super_cqe.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &super_cqe.func_id);
+ if (err)
+ return err;
+
super_cqe.super_cqe_en = enable;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_SUPER_CQE,
@@ -3438,7 +3636,10 @@ static int __set_pf_bw(struct hinic_hwdev *hwdev, u8 speed_level)
pf_bw = 1;
}
- rate_cfg.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &rate_cfg.func_id);
+ if (err)
+ return err;
+
rate_cfg.tx_rate = pf_bw;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
@@ -3543,7 +3744,10 @@ int hinic_set_link_status_follow(void *hwdev,
return -EINVAL;
}
- follow.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &follow.func_id);
+ if (err)
+ return err;
+
follow.follow_status = status;
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
@@ -3617,7 +3821,10 @@ int hinic_set_link_settings(void *hwdev, struct
hinic_link_ksettings *settings)
u16 out_size = sizeof(info);
int err;
- info.func_id = hinic_global_func_id(hwdev);
+ err = hinic_global_func_id_get(hwdev, &info.func_id);
+ if (err)
+ return err;
+
info.valid_bitmap = settings->valid_bitmap;
info.autoneg = settings->autoneg;
info.speed = settings->speed;
@@ -3637,15 +3844,17 @@ int hinic_set_link_settings(void *hwdev, struct
hinic_link_ksettings *settings)
return info.status;
}
-
int hinic_disable_tx_promisc(void *hwdev)
{
struct hinic_promsic_info info = {0};
u16 out_size = sizeof(info);
int err;
+ err = hinic_global_func_id_get(hwdev, &info.func_id);
+ if (err)
+ return err;
+
info.cfg = HINIC_TX_PROMISC_DISABLE;
- info.func_id = hinic_global_func_id(hwdev);
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
HINIC_PORT_CMD_DISABLE_PROMISIC, &info,
sizeof(info), &info, &out_size, 0);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h
b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h
index 98a3e5320c95..0ea04ebd35a3 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h
@@ -53,6 +53,8 @@
#define HINIC_LRO_RX_TIMER_DEFAULT_PG_100GE 8
#define HINIC_LOWEST_LATENCY 1
+#define HINIC_MULTI_VM_LATENCY 32
+#define HINIC_MULTI_VM_PENDING_LIMIT 4
#define HINIC_RX_RATE_LOW 400000
#define HINIC_RX_COAL_TIME_LOW 20
#define HINIC_RX_PENDING_LIMIT_LOW 2
@@ -60,6 +62,7 @@
#define HINIC_RX_COAL_TIME_HIGH 225
#define HINIC_RX_PENDING_LIMIT_HIGH 50
#define HINIC_RX_RATE_THRESH 35000
+#define HINIC_TX_RATE_THRESH 35000
#define HINIC_RX_RATE_LOW_VM 400000
#define HINIC_RX_PENDING_LIMIT_HIGH_VM 50
@@ -413,6 +416,7 @@ int hinic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16
func_id);
int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac,
u16 vlan_id, u16 func_id);
+int hinic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id);
/* Obtaining the permanent mac */
int hinic_get_default_mac(void *hwdev, u8 *mac_addr);
/* Check whether the current solution is using this interface,
@@ -615,8 +619,8 @@ int hinic_set_link_settings(void *hwdev, struct hinic_link_ksettings
*settings);
int hinic_enable_netq(void *hwdev, u8 en);
int hinic_add_hw_rqfilter(void *hwdev,
- struct hinic_rq_filter_info *filter_info);
+ struct hinic_rq_filter_info *filter_info);
int hinic_del_hw_rqfilter(void *hwdev,
- struct hinic_rq_filter_info *filter_info);
+ struct hinic_rq_filter_info *filter_info);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dbg.c
b/drivers/net/ethernet/huawei/hinic/hinic_nic_dbg.c
index 90189f963740..7091fd12c508 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dbg.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dbg.c
@@ -163,7 +163,7 @@ int hinic_dbg_get_sq_db_addr(void *hwdev, u16 q_id, u64 **map_addr,
return 0;
}
-u16 hinic_dbg_get_global_qpn(void *hwdev)
+u16 hinic_dbg_get_global_qpn(const void *hwdev)
{
if (!hwdev)
return 0;
@@ -226,7 +226,7 @@ int hinic_dbg_get_rq_wqe_info(void *hwdev, u16 q_id, u16 idx, u16
wqebb_cnt,
return err;
}
-int hinic_dbg_get_hw_stats(void *hwdev, u8 *hw_stats, u16 *out_size)
+int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size)
{
if (*out_size != sizeof(struct hinic_hw_stats)) {
pr_err("Unexpect out buf size from user :%d, expect: %lu\n",
@@ -248,7 +248,8 @@ u16 hinic_dbg_clear_hw_stats(void *hwdev)
return sizeof(struct hinic_hw_stats);
}
-void hinic_get_chip_fault_stats(void *hwdev, u8 *chip_fault_stats, int offset)
+void hinic_get_chip_fault_stats(const void *hwdev,
+ u8 *chip_fault_stats, int offset)
{
int copy_len = offset + MAX_DRV_BUF_SIZE - HINIC_CHIP_FAULT_SIZE;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
index 8524c459bedd..d8439e67f766 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
@@ -30,7 +30,7 @@
#define HINIC_DRV_NAME "hinic"
#define HINIC_CHIP_NAME "hinic"
-#define HINIC_DRV_VERSION "1.8.3.1"
+#define HINIC_DRV_VERSION "2.3.2.1"
struct vf_data_storage;
#define HINIC_FUNC_IS_VF(hwdev) (hinic_func_type(hwdev) == TYPE_VF)
@@ -45,6 +45,7 @@ enum hinic_flags {
HINIC_SAME_RXTX,
HINIC_INTR_ADAPT,
HINIC_UPDATE_MAC_FILTER,
+ HINIC_ETS_ENABLE,
};
#define RX_BUFF_NUM_PER_PAGE 2
@@ -135,9 +136,9 @@ struct hinic_intr_coal_info {
#define HINIC_NIC_STATS_INC(nic_dev, field) \
{ \
- u64_stats_update_begin(&(nic_dev)->stats.syncp); \
- (nic_dev)->stats.field++; \
- u64_stats_update_end(&(nic_dev)->stats.syncp); \
+ u64_stats_update_begin(&nic_dev->stats.syncp); \
+ nic_dev->stats.field++; \
+ u64_stats_update_end(&nic_dev->stats.syncp); \
}
struct hinic_nic_stats {
@@ -232,6 +233,7 @@ struct hinic_nic_dev {
u32 his_link_speed;
/* interrupt coalesce must be different in virtual machine */
bool in_vm;
+ bool is_vm_slave;
#ifndef HAVE_NETDEV_STATS_IN_NETDEV
struct net_device_stats net_stats;
@@ -275,12 +277,12 @@ int hinic_enable_func_rss(struct hinic_nic_dev *nic_dev);
#define hinic_msg(level, nic_dev, msglvl, format, arg...) \
do { \
- if ((nic_dev)->netdev && (nic_dev)->netdev->reg_state \
+ if (nic_dev->netdev && nic_dev->netdev->reg_state \
== NETREG_REGISTERED) \
- nicif_##level((nic_dev), msglvl, (nic_dev)->netdev, \
+ nicif_##level(nic_dev, msglvl, nic_dev->netdev, \
format, ## arg); \
else \
- nic_##level(&(nic_dev)->pdev->dev, \
+ nic_##level(&nic_dev->pdev->dev, \
format, ## arg); \
} while (0)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c
b/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c
index 30398ee0cc4b..a2160f2ca20f 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c
@@ -107,9 +107,15 @@ struct hinic_sq_db {
u32 db_info;
};
+struct hinic_addr {
+ u32 addr_hi;
+ u32 addr_lo;
+};
+
struct hinic_clean_queue_ctxt {
struct hinic_qp_ctxt_header cmdq_hdr;
u32 ctxt_size;
+ struct hinic_addr cqe_dma_addr[HINIC_RQ_CQ_MAX];
};
static int init_sq(struct hinic_sq *sq, struct hinic_wq *wq, u16 q_id,
@@ -131,6 +137,7 @@ static int init_rq(struct hinic_rq *rq, void *dev_hdl, struct hinic_wq
*wq,
{
rq->wq = wq;
rq->q_id = q_id;
+ rq->cqe_dma_addr = 0;
rq->msix_entry_idx = rq_msix_idx;
@@ -144,6 +151,15 @@ static int init_rq(struct hinic_rq *rq, void *dev_hdl, struct
hinic_wq *wq,
return 0;
}
+void hinic_rq_cqe_addr_set(void *hwdev, u16 qid, dma_addr_t cqe_dma_ddr)
+{
+ struct hinic_hwdev *dev = (struct hinic_hwdev *)hwdev;
+ struct hinic_nic_io *nic_io;
+
+ nic_io = dev->nic_io;
+ nic_io->qps[qid].rq.cqe_dma_addr = cqe_dma_ddr;
+}
+
static void clean_rq(struct hinic_rq *rq, void *dev_hdl)
{
dma_free_coherent(dev_hdl, PAGE_SIZE, rq->pi_virt_addr,
@@ -624,8 +640,10 @@ static int clean_queue_offload_ctxt(struct hinic_nic_io *nic_io,
struct hinic_hwdev *hwdev = nic_io->hwdev;
struct hinic_clean_queue_ctxt *ctxt_block;
struct hinic_cmd_buf *cmd_buf;
+ dma_addr_t cqe_dma_addr;
+ struct hinic_addr *addr;
u64 out_param = 0;
- int err;
+ int i, err;
cmd_buf = hinic_alloc_cmd_buf(hwdev);
if (!cmd_buf) {
@@ -640,6 +658,15 @@ static int clean_queue_offload_ctxt(struct hinic_nic_io *nic_io,
/* TSO/LRO ctxt size: 0x0:0B; 0x1:160B; 0x2:200B; 0x3:240B */
ctxt_block->ctxt_size = 0x3;
+ if ((hinic_func_type(hwdev) == TYPE_VF) &&
+ ctxt_type == HINIC_QP_CTXT_TYPE_RQ) {
+ addr = ctxt_block->cqe_dma_addr;
+ for (i = 0; i < nic_io->max_qps; i++) {
+ cqe_dma_addr = nic_io->qps[i].rq.cqe_dma_addr;
+ addr[i].addr_hi = upper_32_bits(cqe_dma_addr);
+ addr[i].addr_lo = lower_32_bits(cqe_dma_addr);
+ }
+ }
hinic_cpu_to_be32(ctxt_block, sizeof(*ctxt_block));
@@ -725,6 +752,7 @@ int hinic_init_qp_ctxts(void *dev)
return err;
}
+EXPORT_SYMBOL(hinic_init_qp_ctxts);
void hinic_free_qp_ctxts(void *hwdev)
{
@@ -791,6 +819,7 @@ int hinic_init_nic_hwdev(void *hwdev, u16 rx_buff_len)
}
return 0;
}
+EXPORT_SYMBOL(hinic_init_nic_hwdev);
void hinic_free_nic_hwdev(void *hwdev)
{
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_io.h
b/drivers/net/ethernet/huawei/hinic/hinic_nic_io.h
index 92b683f90f26..e52f99f415b6 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_io.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_io.h
@@ -93,4 +93,7 @@ void hinic_be32_to_cpu(void *data, int len);
void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, u32 len);
dma_addr_t hinic_sge_to_dma(struct hinic_sge *sge);
+
+void hinic_rq_cqe_addr_set(void *hwdev, u16 qid, dma_addr_t cqe_dma_ddr);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nictool.c
b/drivers/net/ethernet/huawei/hinic/hinic_nictool.c
index f213f2cd660e..5e924ca8588a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nictool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nictool.c
@@ -39,6 +39,7 @@
#define MAJOR_DEV_NUM 921
#define HINIC_CMDQ_BUF_MAX_SIZE 2048U
#define MSG_MAX_IN_SIZE (2048 * 1024)
+#define MSG_MAX_OUT_SIZE (2048 * 1024)
static dev_t g_dev_id = {0};
/*lint -save -e104 -e808*/
@@ -153,6 +154,10 @@ static int alloc_buff_out(void *hwdev, struct msg_module *nt_msg,
cmd_buf = hinic_alloc_cmd_buf(hwdev);
*buf_out = (void *)cmd_buf;
} else {
+ if (out_size > MSG_MAX_OUT_SIZE) {
+ pr_err("out size(%u) more than 2M\n", out_size);
+ return -ENOMEM;
+ }
*buf_out = kzalloc(out_size, GFP_KERNEL);
}
if (!(*buf_out)) {
@@ -656,6 +661,248 @@ static int set_link_mode(struct hinic_nic_dev *nic_dev, void
*buf_in,
return 0;
}
+static int set_dcb_cfg(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ union _dcb_ctl dcb_ctl = {.data = 0};
+ int err;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ dcb_ctl.data = *((u32 *)buf_in);
+
+ err = hinic_setup_dcb_tool(nic_dev->netdev,
+ &dcb_ctl.dcb_data.dcb_en,
+ !!dcb_ctl.dcb_data.wr_flag);
+ if (err) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to setup dcb state to %d\n",
+ !!dcb_ctl.dcb_data.dcb_en);
+ err = EINVAL;
+ }
+ dcb_ctl.dcb_data.err = (u8)err;
+ *((u32 *)buf_out) = (u32)dcb_ctl.data;
+ *out_size = sizeof(u32);
+
+ return 0;
+}
+
+int get_pfc_info(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ union _pfc pfc = {.data = 0};
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ pfc.data = *((u32 *)buf_in);
+
+ hinic_dcbnl_set_pfc_en_tool(nic_dev->netdev,
+ &pfc.pfc_data.pfc_en, false);
+ hinic_dcbnl_get_pfc_cfg_tool(nic_dev->netdev,
+ &pfc.pfc_data.pfc_priority);
+ hinic_dcbnl_get_tc_num_tool(nic_dev->netdev,
+ &pfc.pfc_data.num_of_tc);
+ *((u32 *)buf_out) = (u32)pfc.data;
+ *out_size = sizeof(u32);
+
+ return 0;
+}
+
+int set_pfc_control(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ u8 pfc_en = 0;
+ u8 err = 0;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ pfc_en = *((u8 *)buf_in);
+ if (!(test_bit(HINIC_DCB_ENABLE, &nic_dev->flags))) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Need to enable dcb first.\n");
+ err = 0xff;
+ goto exit;
+ }
+
+ hinic_dcbnl_set_pfc_en_tool(nic_dev->netdev, &pfc_en, true);
+ err = hinic_dcbnl_set_pfc_tool(nic_dev->netdev);
+ if (err) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to set pfc to %s\n",
+ pfc_en ? "enable" : "disable");
+ }
+
+exit:
+ *((u8 *)buf_out) = (u8)err;
+ *out_size = sizeof(u8);
+ return 0;
+}
+
+int set_ets(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ struct _ets ets = {0};
+ u8 err = 0;
+ u8 i;
+ u8 support_tc = nic_dev->max_cos;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+ memcpy(&ets, buf_in, sizeof(struct _ets));
+
+ if (!(test_bit(HINIC_DCB_ENABLE, &nic_dev->flags))) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Need to enable dcb first.\n");
+ err = 0xff;
+ goto exit;
+ }
+ if (ets.flag_com.ets_flag.flag_ets_enable) {
+ hinic_dcbnl_set_ets_en_tool(nic_dev->netdev, &ets.ets_en, true);
+
+ if (!ets.ets_en)
+ goto exit;
+ }
+
+ if (!(test_bit(HINIC_ETS_ENABLE, &nic_dev->flags))) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Need to enable ets first.\n");
+ err = 0xff;
+ goto exit;
+ }
+ if (ets.flag_com.ets_flag.flag_ets_cos)
+ hinic_dcbnl_set_ets_tc_tool(nic_dev->netdev, ets.tc, true);
+
+ if (ets.flag_com.ets_flag.flag_ets_percent) {
+ for (i = support_tc; i < HINIC_DCB_TC_MAX; i++) {
+ if (ets.ets_percent[i]) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "ETS setting out of range\n");
+ break;
+ }
+ }
+
+ hinic_dcbnl_set_ets_pecent_tool(nic_dev->netdev,
+ ets.ets_percent, true);
+ }
+
+ if (ets.flag_com.ets_flag.flag_ets_strict)
+ hinic_dcbnl_set_ets_strict_tool(nic_dev->netdev,
+ &ets.strict, true);
+
+ err = hinic_dcbnl_set_ets_tool(nic_dev->netdev);
+ if (err) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to set ets [%d].\n", err);
+ }
+exit:
+ *((u8 *)buf_out) = err;
+ *out_size = sizeof(err);
+ return 0;
+}
+
+int get_support_up(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ u8 *up_num = buf_out;
+ u8 support_up = 0;
+ u8 i;
+ u8 up_valid_bitmap = nic_dev->up_valid_bitmap;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ if (*out_size != sizeof(*up_num)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Unexpect out buf size from user: %d, expect: %lu\n",
+ *out_size, sizeof(*up_num));
+ return -EFAULT;
+ }
+
+ for (i = 0; i < HINIC_DCB_UP_MAX; i++) {
+ if (up_valid_bitmap & BIT(i))
+ support_up++;
+ }
+
+ *up_num = support_up;
+
+ return 0;
+}
+
+int get_support_tc(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ u8 *tc_num = buf_out;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ if (*out_size != sizeof(*tc_num)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Unexpect out buf size from user :%d, expect: %lu\n",
+ *out_size, sizeof(*tc_num));
+ return -EFAULT;
+ }
+
+ hinic_dcbnl_get_tc_num_tool(nic_dev->netdev, tc_num);
+
+ return 0;
+}
+
+int get_ets_info(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ struct _ets *ets = buf_out;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ hinic_dcbnl_set_ets_pecent_tool(nic_dev->netdev,
+ ets->ets_percent, false);
+ hinic_dcbnl_set_ets_tc_tool(nic_dev->netdev, ets->tc, false);
+ hinic_dcbnl_set_ets_en_tool(nic_dev->netdev, &ets->ets_en, false);
+ hinic_dcbnl_set_ets_strict_tool(nic_dev->netdev, &ets->strict, false);
+ ets->err = 0;
+
+ *out_size = sizeof(*ets);
+ return 0;
+}
+
+int set_pfc_priority(struct hinic_nic_dev *nic_dev, void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ u8 pfc_prority = 0;
+ u8 err = 0;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ pfc_prority = *((u8 *)buf_in);
+ if (!((test_bit(HINIC_DCB_ENABLE, &nic_dev->flags)) &&
+ nic_dev->tmp_dcb_cfg.pfc_state)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Need to enable pfc first.\n");
+ err = 0xff;
+ goto exit;
+ }
+
+ hinic_dcbnl_set_pfc_cfg_tool(nic_dev->netdev, pfc_prority);
+
+ err = hinic_dcbnl_set_pfc_tool(nic_dev->netdev);
+ if (err) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to set pfc to %x priority\n",
+ pfc_prority);
+ }
+exit:
+ *((u8 *)buf_out) = (u8)err;
+ *out_size = sizeof(u8);
+
+ return 0;
+}
+
static int set_pf_bw_limit(struct hinic_nic_dev *nic_dev, void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
@@ -719,7 +966,6 @@ static int get_poll_weight(struct hinic_nic_dev *nic_dev, void
*buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
struct hinic_nic_poll_weight *weight_info = buf_out;
-
if (*out_size != sizeof(*weight_info)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%d, expect: %lu\n",
@@ -744,7 +990,6 @@ static int get_homologue(struct hinic_nic_dev *nic_dev, void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
struct hinic_homologues *homo = buf_out;
-
if (*out_size != sizeof(*homo)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%d, expect: %lu\n",
@@ -788,8 +1033,8 @@ static int get_sset_count(struct hinic_nic_dev *nic_dev, void
*buf_in,
if (!buf_in || in_size != sizeof(u32) || !out_size ||
*out_size != sizeof(u32) || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %d,
out_size: %d\n",
- in_size, *out_size);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Invalid parameters.\n");
return -EINVAL;
}
@@ -873,7 +1118,7 @@ static int get_func_id(void *hwdev, void *buf_in, u32 in_size,
return -EFAULT;
}
- func_id = hinic_global_func_id(hwdev);
+ func_id = hinic_global_func_id_hw(hwdev);
*(u16 *)buf_out = func_id;
*out_size = sizeof(u16);
return 0;
@@ -957,7 +1202,6 @@ static int get_device_id(void *hwdev, void *buf_in, u32 in_size,
{
u16 dev_id;
int err;
-
if (*out_size != sizeof(u16)) {
pr_err("Unexpect out buf size from user :%d, expect: %lu\n",
*out_size, sizeof(u16));
@@ -992,7 +1236,7 @@ static int is_driver_in_vm(void *hwdev, void *buf_in, u32 in_size,
}
static int get_pf_id(void *hwdev, void *buf_in, u32 in_size,
- void *buf_out, u32 *out_size)
+ void *buf_out, u32 *out_size)
{
struct hinic_pf_info *pf_info;
u32 port_id = 0;
@@ -1118,7 +1362,7 @@ static int knl_free_mem(char *dev_name, struct msg_module *nt_msg)
return 0;
}
-extern int hinic_get_card_func_info_by_card_name(char *chip_name,
+extern int hinic_get_card_func_info_by_card_name(const char *chip_name,
struct hinic_card_func_info
*card_func);
@@ -1220,6 +1464,14 @@ struct nic_drv_module_handle nic_driv_module_cmd_handle[] = {
{SET_HOMOLOGUE, set_homologue},
{GET_SSET_COUNT, get_sset_count},
{GET_SSET_ITEMS, get_sset_stats},
+ {SET_PFC_CONTROL, set_pfc_control},
+ {SET_ETS, set_ets},
+ {GET_ETS_INFO, get_ets_info},
+ {SET_PFC_PRIORITY, set_pfc_priority},
+ {SET_DCB_CFG, set_dcb_cfg},
+ {GET_PFC_INFO, get_pfc_info},
+ {GET_SUPPORT_UP, get_support_up},
+ {GET_SUPPORT_TC, get_support_tc},
};
struct hw_drv_module_handle hw_driv_module_cmd_handle[] = {
@@ -1550,7 +1802,7 @@ static int send_to_sm(void *hwdev, struct msg_module *nt_msg,
}
static bool is_hwdev_cmd_support(unsigned int mod,
- char *ifname, u32 up_api_type)
+ char *ifname, u32 up_api_type)
{
void *hwdev;
@@ -1606,7 +1858,7 @@ static bool is_hwdev_cmd_support(unsigned int mod,
}
static bool nictool_k_is_cmd_support(unsigned int mod,
- char *ifname, u32 up_api_type)
+ char *ifname, u32 up_api_type)
{
enum hinic_init_state init_state =
hinic_get_init_state_by_ifname(ifname);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nictool.h
b/drivers/net/ethernet/huawei/hinic/hinic_nictool.h
index f903e7782f3c..8e848a004d86 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nictool.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nictool.h
@@ -74,6 +74,50 @@ struct up_cmd_st {
};
};
+struct _dcb_data {
+ u8 wr_flag;
+ u8 dcb_en;
+ u8 err;
+ u8 rsvd;
+};
+
+union _dcb_ctl {
+ struct _dcb_data dcb_data;
+ u32 data;
+};
+
+struct _pfc_data {
+ u8 pfc_en;
+ u8 pfc_priority;
+ u8 num_of_tc;
+ u8 err;
+};
+
+union _pfc {
+ struct _pfc_data pfc_data;
+ u32 data;
+};
+
+union _flag_com {
+ struct _ets_flag {
+ u8 flag_ets_enable:1;
+ u8 flag_ets_percent:1;
+ u8 flag_ets_cos:1;
+ u8 flag_ets_strict:1;
+ u8 rev:4;
+ } ets_flag;
+ u8 data;
+};
+
+struct _ets {
+ u8 ets_en;
+ u8 err;
+ u8 strict;
+ u8 tc[8];
+ u8 ets_percent[8];
+ union _flag_com flag_com;
+};
+
#define API_CMD 0x1
#define API_CHAIN 0x2
#define API_CLP 0x3
@@ -209,8 +253,8 @@ struct hinic_card_func_info {
extern void *g_card_node_array[MAX_CARD_NUM];
extern void *g_card_vir_addr[MAX_CARD_NUM];
extern u64 g_card_phy_addr[MAX_CARD_NUM];
-extern int card_id;
extern struct mutex g_addr_lock;
+extern int card_id;
struct hinic_nic_loop_mode {
u32 loop_mode;
@@ -237,6 +281,7 @@ struct hinic_pf_info {
int nictool_k_init(void);
void nictool_k_uninit(void);
+
extern u32 hinic_get_io_stats_size(struct hinic_nic_dev *nic_dev);
extern void hinic_get_io_stats(struct hinic_nic_dev *nic_dev,
struct hinic_show_item *items);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h
b/drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h
index f45e54be9c3c..d225e543f68a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_pci_id_tbl.h
@@ -25,6 +25,7 @@
#define HINIC_DEV_ID_1822_PANGEA_TP_10GE 0x0204
#define HINIC_DEV_ID_1822_KR_40GE 0x020D
#define HINIC_DEV_ID_1822_KR_100GE 0x0205
+#define HINIC_DEV_ID_1822_DUAL_25GE 0x0206
#define HINIC_DEV_ID_1822_KR_25GE 0x0210
#define HINIC_DEV_ID_1822_MULTI_HOST 0x0211
#define HINIC_DEV_ID_1822_100GE 0x0200
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h
b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h
index 652d6429bbe8..47428103fab7 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h
@@ -1,19 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0*/
-/* Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
- *
- * File Name : hinic_port_cmd.h
- * Version : Initial Draft
- * Author : Qu Huichun
- * Created : 2018/5/29
- * Last Modified :
- * Description : Commands between NIC and uP
- * Function List :
- * History :
- * 1.Date : 2018/5/29
- * Author : Qu Huichun
- * Modification: Created file
- */
-
#ifndef __HINIC_PORT_CMD_H__
#define __HINIC_PORT_CMD_H__
@@ -225,7 +210,7 @@ enum hinic_mgmt_cmd {
HINIC_MGMT_CMD_MQM_FIX_INFO_GET = 0x16,
HINIC_MGMT_CMD_MQM_CFG_INFO_SET = 0x18,
- HINIC_MGMT_MQM_SRCH_GPA_SET = 0x20,
+ HINIC_MGMT_CMD_MQM_SRCH_GPA_SET = 0x20,
HINIC_MGMT_CMD_PPF_TMR_SET = 0x22,
HINIC_MGMT_CMD_PPF_HT_GPA_SET = 0x23,
HINIC_MGMT_CMD_RES_STATE_SET = 0x24,
@@ -276,9 +261,11 @@ enum hinic_mgmt_cmd {
HINIC_MGMT_CMD_GET_PHY_INIT_STATUS = 0x6A,
HINIC_MGMT_CMD_HEARTBEAT_SUPPORTED = 0x6B,
- HINIC_MGMT_HEARTBEAT_EVENT = 0x6C,
+ HINIC_MGMT_CMD_HEARTBEAT_EVENT = 0x6C,
HINIC_MGMT_CMD_GET_HW_PF_INFOS = 0x6D,
HINIC_MGMT_CMD_GET_SDI_MODE = 0x6E,
+
+ HINIC_MGMT_CMD_ENABLE_MIGRATE = 0x6F,
};
/* uCode relates commands */
@@ -299,9 +286,10 @@ enum hinic_ucode_cmd {
enum hinic_sw_funcs_cmd {
HINIC_SW_CMD_SLAVE_HOST_PPF_REGISTER = 0x0,
HINIC_SW_CMD_SLAVE_HOST_PPF_UNREGISTER = 0x1,
- HINIC_SW_GET_SLAVE_FUNC_NIC_STATE = 0x2,
+ HINIC_SW_CMD_GET_SLAVE_FUNC_NIC_STATE = 0x2,
HINIC_SW_CMD_SET_SLAVE_FUNC_NIC_STATE = 0x3,
HINIC_SW_CMD_SEND_MSG_TO_VF = 0x4,
+ HINIC_SW_CMD_MIGRATE_READY = 0x5,
};
enum sq_l4offload_type {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_qe_def.h
b/drivers/net/ethernet/huawei/hinic/hinic_qe_def.h
index 5a39ef678826..a5b4e6f85639 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_qe_def.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_qe_def.h
@@ -155,17 +155,17 @@ extern "C"{
SQ_TASK_INFO4_##member##_SHIFT)
/********************* SQ_DB *********************/
-#define SQ_DB_OFF 0x00000800
-#define SQ_DB_INFO_HI_PI_SHIFT 0
-#define SQ_DB_INFO_QID_SHIFT 8
+#define SQ_DB_OFF 0x00000800
+#define SQ_DB_INFO_HI_PI_SHIFT 0
+#define SQ_DB_INFO_QID_SHIFT 8
#define SQ_DB_INFO_CFLAG_SHIFT 23
-#define SQ_DB_INFO_COS_SHIFT 24
-#define SQ_DB_INFO_TYPE_SHIFT 27
-#define SQ_DB_INFO_HI_PI_MASK 0xFFU
-#define SQ_DB_INFO_QID_MASK 0x3FFU
-#define SQ_DB_INFO_CFLAG_MASK 0x1U
-#define SQ_DB_INFO_COS_MASK 0x7U
-#define SQ_DB_INFO_TYPE_MASK 0x1FU
+#define SQ_DB_INFO_COS_SHIFT 24
+#define SQ_DB_INFO_TYPE_SHIFT 27
+#define SQ_DB_INFO_HI_PI_MASK 0xFFU
+#define SQ_DB_INFO_QID_MASK 0x3FFU
+#define SQ_DB_INFO_CFLAG_MASK 0x1U
+#define SQ_DB_INFO_COS_MASK 0x7U
+#define SQ_DB_INFO_TYPE_MASK 0x1FU
#define SQ_DB_INFO_SET(val, member) (((u32)(val) & \
SQ_DB_INFO_##member##_MASK) << \
SQ_DB_INFO_##member##_SHIFT)
@@ -174,21 +174,21 @@ extern "C"{
#define SQ_DB_PI_LOW(pi) ((pi) & SQ_DB_PI_LOW_MASK)
#define SQ_DB_PI_HI_SHIFT 8
#define SQ_DB_PI_HIGH(pi) ((pi) >> SQ_DB_PI_HI_SHIFT)
-#define SQ_DB_ADDR(sq, pi) ((u64 *)((sq)->db_addr + SQ_DB_OFF) + \
- SQ_DB_PI_LOW(pi))
-#define SQ_DB 1
-#define SQ_CFLAG_DP 0
+#define SQ_DB_ADDR(sq, pi) ((u64 *)((sq)->db_addr + SQ_DB_OFF) + \
+ SQ_DB_PI_LOW(pi))
+#define SQ_DB 1
+#define SQ_CFLAG_DP 0 /* CFLAG_DATA_PATH */
/*********************** RQ_CTRL ******************/
#define RQ_CTRL_BUFDESC_SECT_LEN_SHIFT 0
#define RQ_CTRL_COMPLETE_FORMAT_SHIFT 15
#define RQ_CTRL_COMPLETE_LEN_SHIFT 27
-#define RQ_CTRL_LEN_SHIFT 29
+#define RQ_CTRL_LEN_SHIFT 29
#define RQ_CTRL_BUFDESC_SECT_LEN_MASK 0xFFU
#define RQ_CTRL_COMPLETE_FORMAT_MASK 0x1U
#define RQ_CTRL_COMPLETE_LEN_MASK 0x3U
-#define RQ_CTRL_LEN_MASK 0x3U
+#define RQ_CTRL_LEN_MASK 0x3U
#define RQ_CTRL_SET(val, member) (((val) & \
RQ_CTRL_##member##_MASK) << \
@@ -232,8 +232,8 @@ extern "C"{
#define RQ_CQE_SGE_VLAN_SHIFT 0
#define RQ_CQE_SGE_LEN_SHIFT 16
-#define RQ_CQE_SGE_VLAN_MASK 0xFFFFU
-#define RQ_CQE_SGE_LEN_MASK 0xFFFFU
+#define RQ_CQE_SGE_VLAN_MASK 0xFFFFU
+#define RQ_CQE_SGE_LEN_MASK 0xFFFFU
#define RQ_CQE_SGE_GET(val, member) (((val) >> \
RQ_CQE_SGE_##member##_SHIFT) & \
@@ -313,10 +313,10 @@ extern "C"{
#define WQS_PAGE_SIZE (WQS_BLOCKS_PER_PAGE * WQ_BLOCK_SIZE)
#define WQ_MAX_PAGES (WQ_BLOCK_SIZE >> WQ_PAGE_ADDR_SIZE_SHIFT)
-#define CMDQ_BLOCKS_PER_PAGE 8
-#define CMDQ_BLOCK_SIZE 512UL
-#define CMDQ_PAGE_SIZE ALIGN((CMDQ_BLOCKS_PER_PAGE * \
- CMDQ_BLOCK_SIZE), PAGE_SIZE)
+#define CMDQ_BLOCKS_PER_PAGE 8
+#define CMDQ_BLOCK_SIZE 512UL
+#define CMDQ_PAGE_SIZE ALIGN((CMDQ_BLOCKS_PER_PAGE * \
+ CMDQ_BLOCK_SIZE), PAGE_SIZE)
#define ADDR_4K_ALIGNED(addr) (0 == ((addr) & 0xfff))
#define ADDR_256K_ALIGNED(addr) (0 == ((addr) & 0x3ffff))
@@ -440,16 +440,16 @@ enum hinic_res_state {
((pkt_types) & RQ_CQE_PKT_TYPES_NON_L2_MASK)
#define HINIC_PKT_TYPES_L2(pkt_types) \
- ((pkt_types) & RQ_CQE_PKT_TYPES_L2_MASK)
+ (pkt_types & RQ_CQE_PKT_TYPES_L2_MASK)
#define HINIC_CSUM_ERR_BYPASSED(csum_err) \
- ((csum_err) == RQ_CQE_STATUS_CSUM_BYPASS_VAL)
+ (csum_err == RQ_CQE_STATUS_CSUM_BYPASS_VAL)
#define HINIC_CSUM_ERR_IP(csum_err) \
- ((csum_err) & RQ_CQE_STATUS_CSUM_ERR_IP_MASK)
+ (csum_err & RQ_CQE_STATUS_CSUM_ERR_IP_MASK)
#define HINIC_CSUM_ERR_L4(csum_err) \
- ((csum_err) & RQ_CQE_STATUS_CSUM_ERR_L4_MASK)
+ (csum_err & RQ_CQE_STATUS_CSUM_ERR_L4_MASK)
#define TX_MSS_DEFAULT 0x3E00
#define TX_MSS_MIN 0x50
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
index e0ce97dec159..6396fdd6c51e 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
@@ -1,5 +1,5 @@
-/*
- * Huawei HiNIC PCI Express Linux driver
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
@@ -43,15 +43,14 @@
static void hinic_clear_rss_config_user(struct hinic_nic_dev *nic_dev);
#define HINIC_RX_HDR_SIZE 256
-#define HINIC_RX_BUFFER_WRITE 16
#define HINIC_RX_IPV6_PKT 7
#define HINIC_RX_VXLAN_PKT 0xb
#define RXQ_STATS_INC(rxq, field) \
{ \
- u64_stats_update_begin(&(rxq)->rxq_stats.syncp); \
- (rxq)->rxq_stats.field++; \
- u64_stats_update_end(&(rxq)->rxq_stats.syncp); \
+ u64_stats_update_begin(&rxq->rxq_stats.syncp); \
+ rxq->rxq_stats.field++; \
+ u64_stats_update_end(&rxq->rxq_stats.syncp); \
}
static bool rx_alloc_mapped_page(struct hinic_rxq *rxq,
@@ -768,6 +767,7 @@ static int rx_alloc_cqe(struct hinic_rxq *rxq)
cqe_pa += sizeof(*rx_info->cqe);
}
+ hinic_rq_cqe_addr_set(nic_dev->hwdev, rxq->q_id, rxq->cqe_start_paddr);
return 0;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.h
b/drivers/net/ethernet/huawei/hinic/hinic_rx.h
index f496516638ec..89be4b6f9272 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.h
@@ -1,5 +1,5 @@
-/*
- * Huawei HiNIC PCI Express Linux driver
+/* SPDX-License-Identifier: GPL-2.0*/
+/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
#define HINIC_RX_BP_UPPER_THD 400
#define HINIC_SUPPORT_LRO_ADAP_QPS_MAX 16
+#define HINIC_RX_BUFFER_WRITE 16
enum {
HINIC_RX_STATUS_BP_EN,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sm_lt.h
b/drivers/net/ethernet/huawei/hinic/hinic_sm_lt.h
index 091bcccd9c75..78767c4e4a08 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_sm_lt.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_sm_lt.h
@@ -1,4 +1,4 @@
-/*SPDX-License-Identifier: GPL-2.0*/
+/* SPDX-License-Identifier: GPL-2.0*/
/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sml_counter.c
b/drivers/net/ethernet/huawei/hinic/hinic_sml_counter.c
index 7e1814520e43..9315aaeb8543 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_sml_counter.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_sml_counter.c
@@ -28,11 +28,11 @@
| (((x) & 0xff000000) >> 24))
#endif
-static void sml_ctr_htonl_n(u32 *node, u32 ullen)
+static void sml_ctr_htonl_n(u32 *node, u32 ulLen)
{
u32 i;
- for (i = 0; i < ullen; i++) {
+ for (i = 0; i < ulLen; i++) {
*node = HTONL(*node);
node++;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
index adc9b755c67b..ddfa32029206 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
@@ -310,6 +310,13 @@ int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16
vlan, u8 qos)
err = hinic_kill_vf_vlan(sriov_info->hwdev, OS_VF_ID_TO_HW(vf));
}
+ if (err)
+ return err;
+
+ err = hinic_update_mac_vlan(sriov_info->hwdev,
+ cur_vlanprio & VLAN_VID_MASK, vlan,
+ OS_VF_ID_TO_HW(vf));
+
out:
return err;
}
@@ -334,7 +341,7 @@ int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool
setting)
return 0;
err = hinic_set_vf_spoofchk(sriov_info->hwdev,
- OS_VF_ID_TO_HW(vf), setting);
+ OS_VF_ID_TO_HW(vf), setting);
if (!err) {
nicif_info(adapter, drv, netdev, "Set VF %d spoofchk %s\n",
@@ -490,4 +497,6 @@ int hinic_ndo_set_vf_bw(struct net_device *netdev, int vf, int
max_tx_rate)
#endif
return 0;
-} /*lint -restore*/
+}
+
+/*lint -restore*/
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
index 0088acc9836b..5b205dcb1e80 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
@@ -1,5 +1,5 @@
-/*
- * Huawei HiNIC PCI Express Linux driver
+// SPDX-License-Identifier: GPL-2.0
+/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
@@ -47,9 +47,9 @@
#define TXQ_STATS_INC(txq, field) \
{ \
- u64_stats_update_begin(&(txq)->txq_stats.syncp); \
- (txq)->txq_stats.field++; \
- u64_stats_update_end(&(txq)->txq_stats.syncp); \
+ u64_stats_update_begin(&txq->txq_stats.syncp); \
+ txq->txq_stats.field++; \
+ u64_stats_update_end(&txq->txq_stats.syncp); \
}
void hinic_txq_get_stats(struct hinic_txq *txq,
@@ -162,7 +162,7 @@ static int tx_map_skb(struct hinic_nic_dev *nic_dev, struct sk_buff
*skb,
}
dma_len[0].dma = dma_map_single(&pdev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
+ skb_headlen(skb), DMA_TO_DEVICE);
if (dma_mapping_error(&pdev->dev, dma_len[0].dma)) {
TXQ_STATS_INC(txq, map_frag_err);
err = -EFAULT;
@@ -181,8 +181,8 @@ static int tx_map_skb(struct hinic_nic_dev *nic_dev, struct sk_buff
*skb,
frag = &(skb_shinfo(skb)->frags[i]);
i++;
dma_len[i].dma = skb_frag_dma_map(&pdev->dev, frag, 0,
- skb_frag_size(frag),
- DMA_TO_DEVICE);
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
if (dma_mapping_error(&pdev->dev, dma_len[i].dma)) {
TXQ_STATS_INC(txq, map_frag_err);
i--;
@@ -298,14 +298,12 @@ static void get_inner_l3_l4_type(struct sk_buff *skb, union hinic_ip
*ip,
int pld_off = 0;
pld_off = ipv6_skip_exthdr(skb,
- (int)(exthdr -
- skb->data),
- l4_proto,
- &frag_off);
+ (int)(exthdr - skb->data),
+ l4_proto, &frag_off);
l4->hdr = skb->data + pld_off;
} else {
l4->hdr = exthdr;
- #endif
+#endif
}
} else {
*l3_type = UNKNOWN_L3TYPE;
@@ -804,7 +802,7 @@ static netdev_tx_t hinic_send_one_skb(struct sk_buff *skb,
num_sge = skb_nr_frags + 1;
- /* if skb->len is more than 65536B but num_sge is 1,
+ /* :if skb->len is more than 65536B but num_sge is 1,
* driver will drop it
*/
if (unlikely(skb->len > HINIC_GSO_MAX_SIZE && num_sge == 1)) {
@@ -874,20 +872,38 @@ static netdev_tx_t hinic_send_one_skb(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+netdev_tx_t hinic_lb_xmit_frame(struct sk_buff *skb,
+ struct net_device *netdev)
{
struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
+ u16 q_id = skb_get_queue_mapping(skb);
struct hinic_txq *txq;
+ u8 flag = 0;
+
+ if (unlikely(!nic_dev->heart_status)) {
+ dev_kfree_skb_any(skb);
+ HINIC_NIC_STATS_INC(nic_dev, tx_carrier_off_drop);
+ return NETDEV_TX_OK;
+ }
+
+ txq = &nic_dev->txqs[q_id];
+
+ return hinic_send_one_skb(skb, netdev, txq, &flag, HINIC_TX_NON_AVD);
+}
+
+netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
u16 q_id = skb_get_queue_mapping(skb);
+ struct hinic_txq *txq;
u8 flag = 0;
#ifdef HAVE_IP6_FRAG_ID_ENABLE_UFO
struct sk_buff *ufo_skb;
int err;
#endif
- if (unlikely((!netif_carrier_ok(netdev) &&
- !test_bit(HINIC_LP_TEST, &nic_dev->flags)) ||
- !nic_dev->heart_status)) {
+ if (unlikely(!netif_carrier_ok(netdev) ||
+ !nic_dev->heart_status)) {
dev_kfree_skb_any(skb);
HINIC_NIC_STATS_INC(nic_dev, tx_carrier_off_drop);
return NETDEV_TX_OK;
@@ -997,7 +1013,7 @@ int hinic_tx_poll(struct hinic_txq *txq, int budget)
/* Whether all of the wqebb of this wqe is completed */
if (hw_ci == sw_ci || ((hw_ci - sw_ci) &
- txq->q_mask) < tx_info->wqebb_cnt) {
+ txq->q_mask) < tx_info->wqebb_cnt) {
break;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.h
b/drivers/net/ethernet/huawei/hinic/hinic_tx.h
index 89fce0849e6e..04aeb3365cca 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.h
@@ -1,5 +1,5 @@
-/*
- * Huawei HiNIC PCI Express Linux driver
+/* SPDX-License-Identifier: GPL-2.0*/
+/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
* This program is free software; you can redistribute it and/or modify it
@@ -77,7 +77,8 @@ struct hinic_txq {
u16 q_depth;
u16 q_mask;
struct hinic_txq_stats txq_stats;
-
+ u64 last_moder_packets;
+ u64 last_moder_bytes;
struct hinic_tx_info *tx_info;
};
@@ -97,6 +98,9 @@ void hinic_txq_clean_stats(struct hinic_txq_stats *txq_stats);
void hinic_txq_get_stats(struct hinic_txq *txq,
struct hinic_txq_stats *stats);
+netdev_tx_t hinic_lb_xmit_frame(struct sk_buff *skb,
+ struct net_device *netdev);
+
netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
int hinic_setup_all_tx_resources(struct net_device *netdev);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_wq.c
b/drivers/net/ethernet/huawei/hinic/hinic_wq.c
index 43d34ea72363..06401a654629 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_wq.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_wq.c
@@ -663,7 +663,7 @@ void *hinic_read_wqe(struct hinic_wq *wq, int num_wqebbs, u16
*cons_idx)
return WQ_PAGE_ADDR(wq, *cons_idx) + WQE_PAGE_OFF(wq, *cons_idx);
}
-static inline int wqe_shadow(struct hinic_wq *wq, void *wqe)
+static inline int wqe_shadow(struct hinic_wq *wq, const void *wqe)
{
void *end_wqe_shadow_addr;
u32 wqe_shadow_size = wq->num_q_pages * wq->max_wqe_size;
diff --git a/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.c
b/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.c
index 4475206f0d95..798faa6f401d 100644
--- a/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.c
+++ b/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.c
@@ -19,12 +19,12 @@
#define OSSL_MINUTE_BASE (60)
-sdk_file *file_creat(char *file_name)
+sdk_file *file_creat(const char *file_name)
{
return filp_open(file_name, O_CREAT | O_RDWR | O_APPEND, 0);
}
-sdk_file *file_open(char *file_name)
+sdk_file *file_open(const char *file_name)
{
return filp_open(file_name, O_RDONLY, 0);
}
diff --git a/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.h
b/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.h
index 28b0bfbd9994..8cdcb1db2c3a 100644
--- a/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.h
+++ b/drivers/net/ethernet/huawei/hinic/ossl_knl_linux.h
@@ -432,9 +432,9 @@ static inline void __kc_eth_zero_addr(u8 *addr)
typedef struct file sdk_file;
-sdk_file *file_creat(char *file_name);
+sdk_file *file_creat(const char *file_name);
-sdk_file *file_open(char *file_name);
+sdk_file *file_open(const char *file_name);
void file_close(sdk_file *file_handle);
--
2.31.0