From a93d34c65e30c4f97574e26294de200fa54768c2 Mon Sep 17 00:00:00 2001
From: Xue <xuechaojing@huawei.com>
Date: Tue, 23 Jul 2019 21:16:20 +0800
Subject: [PATCH 2770/2944] openeuler: net: update hinic driver to 2.3.2.1

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@huawei.com>
Signed-off-by: Xue <xuechaojing@huawei.com>
Reviewed-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Xin Hao <haoxing990@gmail.com>
Reviewed-by: Baolin Wang <baolin.wang@openanolis.org>
---
 drivers/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 +-
 drivers/net/ethernet/huawei/hinic/hinic_cmdq.c     |  54 +++-
 drivers/net/ethernet/huawei/hinic/hinic_ctx_def.h  |  11 +-
 drivers/net/ethernet/huawei/hinic/hinic_dbg.h      |   7 +-
 .../net/ethernet/huawei/hinic/hinic_dbgtool_knl.c  |  43 +--
 .../net/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 +
 drivers/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 +-
 drivers/net/ethernet/huawei/hinic/hinic_ethtool.c  |  32 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw.h       |  20 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h  |  19 +-
 drivers/net/ethernet/huawei/hinic/hinic_hwdev.c    | 213 +++++++------
 drivers/net/ethernet/huawei/hinic/hinic_hwdev.h    |  34 ++-
 drivers/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 +
 drivers/net/ethernet/huawei/hinic/hinic_main.c     | 160 ++++++++--
 drivers/net/ethernet/huawei/hinic/hinic_mbox.c     | 119 ++++----
 drivers/net/ethernet/huawei/hinic/hinic_mbox.h     |  10 +-
 drivers/net/ethernet/huawei/hinic/hinic_mgmt.c     |  43 +--
 drivers/net/ethernet/huawei/hinic/hinic_mgmt.h     |   8 +-
 .../ethernet/huawei/hinic/hinic_mgmt_interface.h   |   9 +-
 .../ethernet/huawei/hinic/hinic_multi_host_mgmt.c  |  83 +++--
 drivers/net/ethernet/huawei/hinic/hinic_nic.h      |   2 +
 drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c  | 319 ++++++++++++++++----
 drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h  |   8 +-
 drivers/net/ethernet/huawei/hinic/hinic_nic_dbg.c  |   7 +-
 drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h  |  16 +-
 drivers/net/ethernet/huawei/hinic/hinic_nic_io.c   |  31 +-
 drivers/net/ethernet/huawei/hinic/hinic_nic_io.h   |   3 +
 drivers/net/ethernet/huawei/hinic/hinic_nictool.c  | 272 ++++++++++++++++-
 drivers/net/ethernet/huawei/hinic/hinic_nictool.h  |  47 ++-
 .../net/ethernet/huawei/hinic/hinic_pci_id_tbl.h   |   1 +
 drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h |  24 +-
 drivers/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 +-
 drivers/net/ethernet/huawei/hinic/hinic_sm_lt.h    |   2 +-
 .../net/ethernet/huawei/hinic/hinic_sml_counter.c  |   4 +-
 drivers/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 +-
 drivers/net/ethernet/huawei/hinic/ossl_knl_linux.c |   4 +-
 drivers/net/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 de190ba..6ead689 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 fbacba1..6662119 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 55d0383..8ca0764 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 e9f9f0a..3f52123 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 0b61e22..71ccb1f 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 @@
 
 #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 bfc6aa4..f87bedf 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dbg.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dbg.h
@@ -39,7 +39,7 @@
 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_sm_ctr_wr64_pair(void *hwdev, u8 node, u8 instance, u32 ctr_id,
 
 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 96fb8db..0cf65bf 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(&param, 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 833d3fd..33aaca1 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 @@ struct dbgtool_param {
 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 0d1bb2a..8f80a8f 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 0d6c025..056b722 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dcb.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dcb.h
@@ -48,5 +48,20 @@ enum HINIC_DCB_FLAGS {
 
 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 ff99352..cb5fe47 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 3d6dbc7..80650f8 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 @@
 
 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 102dd18..5813c4b 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 76443f8..e563d8a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -140,7 +140,7 @@ struct hinic_stats {
 	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,9 +2450,11 @@ 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,
 	.get_drvinfo = hinic_get_drvinfo,
@@ -2521,7 +2525,9 @@ static int hinic_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
 
 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 9850a8e..69b069b 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 d4bb6fa..f2143c05 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 86e6da1..2693998 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 @@ struct hinic_heartbeat_event {
 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 @@ struct hinic_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 e0d76b1..eebd74b 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_ppf_process_mbox_msg(struct hinic_hwdev *hwdev, u16 pf_idx, u16 vf_id,
 
 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 fad2d6d..260c61d 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 4260ed4..f653694 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 @@ struct hinic_pcidev {
 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 int hinic_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	{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 deaeb95..844fb5f2 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_lld.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.h
@@ -109,6 +109,11 @@ int hinic_get_chip_cos_up_map(struct pci_dev *pdev, bool *is_setted,
 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 @@ int hinic_get_chip_cos_up_map(struct pci_dev *pdev, bool *is_setted,
 
 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 9fd3411..a2238b9 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -105,8 +105,23 @@
 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 @@ static int hinic_set_mac_addr(struct net_device *netdev, void *addr)
 {
 	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 @@ static int hinic_set_mac_addr(struct net_device *netdev, void *addr)
 {
 	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 bbefb5e..da8d590 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 @@ static int recv_vf_mbox_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 c55d323..a54639d 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 5543f1f..6a2c109 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 9411d50..38f7470 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 14efbe1..13bc351 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 0552359..aad4b2c 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 be68f3c..7e92563 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 56d6da9..d7796d9 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 98a3e53..0ea04eb 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 @@ enum hinic_lro_en_status {
 
 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_status_follow(void *hwdev,
 
 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 90189f9..7091fd1 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 8524c45..d8439e6 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 nic_ioctl(void *uld_dev, u32 cmd, void *buf_in,
 
 #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 30398ee..a2160f2 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 92b683f..e52f99f 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 @@ struct hinic_sge {
 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 f213f2c..5e924ca 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 f903e77..8e848a0 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 f45e54b..d225e54 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 652d642..4742810 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 5a39ef6..a5b4e6f 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 @@
 		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 @@
 #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 @@
 #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 @@
 #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 1620a53..e5316d6 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 f496516..89be4b6 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 091bccc..78767c4 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 7e18145..9315aae 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 adc9b75..ddfa320 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 0088acc..5b205dc 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 89fce08..04aeb33 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 @@ enum hinic_tx_avd_type {
 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 43d34ea..06401a6 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 4475206..798faa6 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 28b0bfb..8cdcb1d 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);
 
-- 
1.8.3.1

