Add code for hardware operation, including configuration,
query and so on.

Signed-off-by: Ziyang Xuan <xuanziya...@huawei.com>
---
 drivers/net/hinic/base/hinic_pmd_cfg.c   |  269 ++++
 drivers/net/hinic/base/hinic_pmd_cfg.h   |  264 ++++
 drivers/net/hinic/base/hinic_pmd_hw.h    |   49 +
 drivers/net/hinic/base/hinic_pmd_hwdev.c | 1544 ++++++++++++++++++++++
 drivers/net/hinic/base/hinic_pmd_hwdev.h |  205 +++
 drivers/net/hinic/base/hinic_pmd_hwif.c  |  542 ++++++++
 drivers/net/hinic/base/hinic_pmd_hwif.h  |   90 ++
 7 files changed, 2963 insertions(+)
 create mode 100644 drivers/net/hinic/base/hinic_pmd_cfg.c
 create mode 100644 drivers/net/hinic/base/hinic_pmd_cfg.h
 create mode 100644 drivers/net/hinic/base/hinic_pmd_hw.h
 create mode 100644 drivers/net/hinic/base/hinic_pmd_hwdev.c
 create mode 100644 drivers/net/hinic/base/hinic_pmd_hwdev.h
 create mode 100644 drivers/net/hinic/base/hinic_pmd_hwif.c
 create mode 100644 drivers/net/hinic/base/hinic_pmd_hwif.h

diff --git a/drivers/net/hinic/base/hinic_pmd_cfg.c 
b/drivers/net/hinic/base/hinic_pmd_cfg.c
new file mode 100644
index 000000000..d4106995a
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_cfg.c
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#include "hinic_pmd_dpdev.h"
+
+static void parse_dev_cap(struct hinic_hwdev *dev,
+                         struct hinic_dev_cap *dev_cap,
+                         enum func_type type);
+
+bool hinic_support_nic(struct hinic_hwdev *hwdev, struct nic_service_cap *cap)
+{
+       if (!hwdev)
+               return false;
+
+       if (!IS_NIC_TYPE(hwdev))
+               return false;
+
+       if (cap)
+               memcpy(cap, &hwdev->cfg_mgmt->svc_cap.nic_cap, sizeof(*cap));
+
+       return true;
+}
+
+static void hinic_parse_shared_res_cap(struct service_cap *cap,
+                                       struct hinic_dev_cap *dev_cap,
+                                       __rte_unused enum func_type type)
+{
+       struct host_shared_resource_cap *shared_cap = &cap->shared_res_cap;
+
+       shared_cap->host_pctxs = dev_cap->host_pctx_num;
+
+       if (dev_cap->host_sf_en)
+               cap->sf_en = true;
+       else
+               cap->sf_en = false;
+
+       shared_cap->host_cctxs = dev_cap->host_ccxt_num;
+       shared_cap->host_scqs = dev_cap->host_scq_num;
+       shared_cap->host_srqs = dev_cap->host_srq_num;
+       shared_cap->host_mpts = dev_cap->host_mpt_num;
+
+       PMD_DRV_LOG(INFO, "Get share resource capability:");
+       PMD_DRV_LOG(INFO, "host_pctxs: 0x%x, host_cctxs: 0x%x, host_scqs: 0x%x, 
host_srqs: 0x%x, host_mpts: 0x%x",
+                   shared_cap->host_pctxs, shared_cap->host_cctxs,
+                   shared_cap->host_scqs, shared_cap->host_srqs,
+                   shared_cap->host_mpts);
+}
+
+static void hinic_parse_l2nic_res_cap(struct service_cap *cap,
+                               struct hinic_dev_cap *dev_cap,
+                               enum func_type type)
+{
+       struct nic_service_cap *nic_cap = &cap->nic_cap;
+
+       if (type == TYPE_PF || type == TYPE_PPF) {
+               nic_cap->max_sqs = dev_cap->nic_max_sq + 1;
+               nic_cap->max_rqs = dev_cap->nic_max_rq + 1;
+               nic_cap->vf_max_sqs = dev_cap->nic_vf_max_sq + 1;
+               nic_cap->vf_max_rqs = dev_cap->nic_vf_max_rq + 1;
+       } else {
+               nic_cap->max_sqs = dev_cap->nic_max_sq;
+               nic_cap->max_rqs = dev_cap->nic_max_rq;
+               nic_cap->vf_max_sqs = 0;
+               nic_cap->vf_max_rqs = 0;
+       }
+
+       if (dev_cap->nic_lro_en)
+               nic_cap->lro_en = true;
+       else
+               nic_cap->lro_en = false;
+
+       nic_cap->lro_sz = dev_cap->nic_lro_sz;
+       nic_cap->tso_sz = dev_cap->nic_tso_sz;
+
+       PMD_DRV_LOG(INFO, "Get l2nic resource capability:");
+       PMD_DRV_LOG(INFO, "max_sqs: 0x%x, max_rqs: 0x%x, vf_max_sqs: 0x%x, 
vf_max_rqs: 0x%x",
+                   nic_cap->max_sqs, nic_cap->max_rqs,
+                   nic_cap->vf_max_sqs, nic_cap->vf_max_rqs);
+}
+
+static int get_cap_from_fw(struct hinic_hwdev *dev, enum func_type type)
+{
+       int err;
+       u16 in_len, out_len;
+       struct hinic_dev_cap dev_cap;
+
+       memset(&dev_cap, 0, sizeof(dev_cap));
+       in_len = sizeof(dev_cap);
+       out_len = in_len;
+       dev_cap.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       err = hinic_msg_to_mgmt_sync(dev, HINIC_MOD_CFGM, HINIC_CFG_NIC_CAP,
+                                    &dev_cap, in_len, &dev_cap, &out_len, 0);
+       if (err || dev_cap.mgmt_msg_head.status || !out_len) {
+               PMD_DRV_LOG(ERR, "Get capability from FW failed, err: %d, 
status: %d, out_len: %d",
+                       err, dev_cap.mgmt_msg_head.status, out_len);
+               return -EFAULT;
+       }
+
+       parse_dev_cap(dev, &dev_cap, type);
+       return 0;
+}
+
+static int get_dev_cap(struct hinic_hwdev *dev)
+{
+       int err;
+       enum func_type type = HINIC_FUNC_TYPE(dev);
+
+       switch (type) {
+       case TYPE_PF:
+       case TYPE_PPF:
+               err = get_cap_from_fw(dev, type);
+               if (err) {
+                       PMD_DRV_LOG(ERR, "Get PF/PPF capability failed");
+                       return err;
+               }
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "Unsupported PCI function type");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+u16 hinic_func_max_qnum(void *hwdev)
+{
+       struct hinic_hwdev *dev = (struct hinic_hwdev *)hwdev;
+
+       return dev->cfg_mgmt->svc_cap.max_sqs;
+}
+
+int init_cfg_mgmt(struct hinic_hwdev *dev)
+{
+       struct cfg_mgmt_info *cfg_mgmt;
+
+       cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL);
+       if (!cfg_mgmt) {
+               PMD_DRV_LOG(ERR, "Alloc cfg mgmt failed");
+               return -ENOMEM;
+       }
+
+       dev->cfg_mgmt = cfg_mgmt;
+       cfg_mgmt->hwdev = dev;
+
+       return 0;
+}
+
+void free_cfg_mgmt(struct hinic_hwdev *dev)
+{
+       kfree(dev->cfg_mgmt);
+       dev->cfg_mgmt = NULL;
+}
+
+static void hinic_parse_pub_res_cap(struct service_cap *cap,
+                             struct hinic_dev_cap *dev_cap,
+                             enum func_type type)
+{
+       struct dev_sf_svc_attr *attr = &cap->sf_svc_attr;
+
+       if (dev_cap->sf_svc_attr & SF_SVC_FT_BIT)
+               attr->ft_en = true;
+       else
+               attr->ft_en = false;
+
+       if (dev_cap->sf_svc_attr & SF_SVC_RDMA_BIT)
+               attr->rdma_en = true;
+       else
+               attr->rdma_en = false;
+
+       if (type == TYPE_PPF) {
+               /* For PPF's SF EN flag, we assign it in get_dynamic_res_cap().
+                * we only save its VF's flag.
+                */
+               attr->sf_en_vf = dev_cap->sf_en_vf;
+       } else if (type == TYPE_PF) {
+               if (dev_cap->sf_en_pf)
+                       cap->sf_en = true;
+               else
+                       cap->sf_en = false;
+
+               attr->sf_en_vf = dev_cap->sf_en_vf;
+       }
+
+       cap->host_id = dev_cap->host_id;
+       cap->ep_id = dev_cap->ep_id;
+       cap->interrupt_type = dev_cap->intr_type;
+       cap->max_cos_id = dev_cap->max_cos_id;
+       cap->er_id = dev_cap->er_id;
+       cap->port_id = dev_cap->port_id;
+
+       if (type == TYPE_PF || type == TYPE_PPF) {
+               cap->max_vf = dev_cap->max_vf;
+               cap->pf_num = dev_cap->pf_num;
+               cap->pf_id_start = dev_cap->pf_id_start;
+               cap->vf_num = dev_cap->vf_num;
+               cap->vf_id_start = dev_cap->vf_id_start;
+               cap->max_sqs = dev_cap->nic_max_sq + 1;
+               cap->max_rqs = dev_cap->nic_max_rq + 1;
+       }
+
+       cap->chip_svc_type = CFG_SVC_NIC_BIT0;
+       cap->host_total_function = dev_cap->host_total_func;
+       cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val;
+       cap->max_connect_num = dev_cap->max_conn_num;
+       cap->max_stick2cache_num = dev_cap->max_stick2cache_num;
+       cap->bfilter_start_addr = dev_cap->max_bfilter_start_addr;
+       cap->bfilter_len = dev_cap->bfilter_len;
+       cap->hash_bucket_num = dev_cap->hash_bucket_num;
+       cap->dev_ver_info.cfg_file_ver = dev_cap->cfg_file_ver;
+       cap->net_port_mode = dev_cap->net_port_mode;
+
+       PMD_DRV_LOG(INFO, "Get public resource capability:");
+       PMD_DRV_LOG(INFO, "host_id: 0x%x, ep_id: 0x%x, intr_type: 0x%x, 
max_cos_id: 0x%x, er_id: 0x%x, port_id: 0x%x",
+                   cap->host_id, cap->ep_id, cap->intr_chip_en,
+                   cap->max_cos_id, cap->er_id, cap->port_id);
+       PMD_DRV_LOG(INFO, "host_total_function: 0x%x, host_oq_id_mask_val: 
0x%x, net_port_mode: 0x%x, max_vf: 0x%x",
+                   cap->host_total_function, cap->host_oq_id_mask_val,
+                   cap->net_port_mode, cap->max_vf);
+       PMD_DRV_LOG(INFO, "pf_num: 0x%x, pf_id_start: 0x%x, vf_num: 0x%x, 
vf_id_start: 0x%x",
+                   cap->pf_num, cap->pf_id_start,
+                   cap->vf_num, cap->vf_id_start);
+}
+
+static void parse_dev_cap(struct hinic_hwdev *dev,
+                         struct hinic_dev_cap *dev_cap,
+                         enum func_type type)
+{
+       struct service_cap *cap = &dev->cfg_mgmt->svc_cap;
+
+       /* Public resource */
+       hinic_parse_pub_res_cap(cap, dev_cap, type);
+
+       /* PPF managed dynamic resource */
+       if (type == TYPE_PPF)
+               hinic_parse_shared_res_cap(cap, dev_cap, type);
+
+       /* L2 NIC resource */
+       if (IS_NIC_TYPE(dev))
+               hinic_parse_l2nic_res_cap(cap, dev_cap, type);
+}
+
+int hinic_init_capability(struct hinic_nic_dev *nic_dev)
+{
+       int err;
+       struct hinic_hwdev *dev = nic_dev->hwdev;
+       struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt;
+
+       cfg_mgmt->svc_cap.sf_svc_attr.ft_pf_en = false;
+       cfg_mgmt->svc_cap.sf_svc_attr.rdma_pf_en = false;
+
+       cfg_mgmt->svc_cap.max_connect_num = 1024 * 1024; /* 1M */
+       cfg_mgmt->svc_cap.max_stick2cache_num = 12 * 1024;
+
+       cfg_mgmt->svc_cap.timer_en = true;
+       cfg_mgmt->svc_cap.bloomfilter_en = false;
+
+       err = get_dev_cap(dev);
+       if (err)
+               return err;
+
+       /* get nic capability */
+       if (!hinic_support_nic(dev, &nic_dev->nic_cap)) {
+               PMD_DRV_LOG(ERR, "Device does not support nic feature");
+               return -ENOTSUP;
+       }
+
+       return 0;
+}
diff --git a/drivers/net/hinic/base/hinic_pmd_cfg.h 
b/drivers/net/hinic/base/hinic_pmd_cfg.h
new file mode 100644
index 000000000..45654a4e3
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_cfg.h
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC_PMD_CFG_H_
+#define _HINIC_PMD_CFG_H_
+
+#define CFG_MAX_CMD_TIMEOUT     8000 /* ms */
+
+enum {
+       SF_SVC_FT_BIT = (1 << 0),
+       SF_SVC_RDMA_BIT = (1 << 1),
+};
+
+struct host_shared_resource_cap {
+       u32 host_pctxs; /* Parent Context max 1M, IOE and FCoE max 8K flows */
+       u32 host_cctxs; /* Child Context: max 8K */
+       u32 host_scqs;  /* shared CQ, chip interface module uses 1 SCQ
+                        * TOE/IOE/FCoE each uses 1 SCQ
+                        * RoCE/IWARP uses multiple SCQs
+                        * So 6 SCQ least
+                        */
+       u32 host_srqs; /* SRQ number: 256K */
+       u32 host_mpts; /* MR number:1M */
+};
+
+struct dev_sf_svc_attr {
+       bool ft_en;     /* business enable flag (not include RDMA) */
+       bool ft_pf_en;  /* In FPGA Test VF resource is in PF or not,
+                        * 0 - VF, 1 - PF, VF doesn't need this bit.
+                        */
+
+       bool rdma_en;
+       bool rdma_pf_en; /* In FPGA Test VF RDMA resource is in PF or not,
+                         * 0 - VF, 1 - PF, VF doesn't need this bit.
+                         */
+       u8 sf_en_vf;    /* SF_EN for PPF/PF's VF */
+};
+
+/* device capability */
+struct service_cap {
+       struct dev_sf_svc_attr sf_svc_attr;
+       enum cfg_svc_type_en svc_type;          /* user input service type */
+       enum cfg_svc_type_en chip_svc_type;     /* HW supported service type */
+
+       /* Host global resources */
+       u16 host_total_function;
+       u8 host_oq_id_mask_val;
+       u8 host_id;
+       u8 ep_id;
+       /* Don't get interrupt_type from firmware */
+       enum intr_type interrupt_type;
+       u8 intr_chip_en;
+       u8 max_cos_id;  /* PF/VF's max cos id */
+       u8 er_id;       /* PF/VF's ER */
+       u8 port_id;     /* PF/VF's physical port */
+       u8 max_vf;      /* max VF number that PF supported */
+       bool sf_en;     /* stateful business status */
+       u8 timer_en;    /* 0:disable, 1:enable */
+       u8 bloomfilter_en; /* 0:disable, 1:enable*/
+       u16 max_sqs;
+       u16 max_rqs;
+
+       /* PF BAT Bfliter CFG(16) is set when FT_EN=1 */
+       u32 max_connect_num;    /* PF/VF maximum connection number(1M) */
+       /* The maximum connections which can be stick to cache memory, max 1K */
+       u16 max_stick2cache_num;
+       /* Starting address in cache memory for bloom filter, 64Bytes aligned */
+       u16 bfilter_start_addr;
+       /* Length for bloom filter, aligned on 64Bytes. The size is length*64B.
+        * Bloom filter memory size + 1 must be power of 2.
+        * The maximum memory size of bloom filter is 4M
+        */
+       u16 bfilter_len;
+       /* The size of hash bucket tables, align on 64 entries.
+        * Be used to AND (&) the hash value. Bucket Size +1 must be power of 2.
+        * The maximum number of hash bucket is 4M
+        */
+       u16 hash_bucket_num;
+       u8 net_port_mode; /* 0:ETH,1:FIC,2:4FC */
+
+       u32 pf_num;
+       u32 pf_id_start;
+       u32 vf_num;
+       u32 vf_id_start;
+
+       struct host_shared_resource_cap shared_res_cap; /* shared capability */
+       struct dev_version_info     dev_ver_info;       /* version */
+       struct nic_service_cap      nic_cap;            /* NIC capability */
+};
+
+struct cfg_eq {
+       enum hinic_service_type type;
+       int eqn;
+       int free; /* 1 - allocated, 0- freed */
+};
+
+struct cfg_eq_info {
+       struct cfg_eq *eq;
+
+       u8 num_ceq;
+       u8 num_aeq;
+       u8 num_eq;      /* num_eq = num_ceq + num_aeq */
+
+       u8 num_ceq_remain;
+};
+
+struct cfg_mgmt_info {
+       struct hinic_hwdev *hwdev;
+       struct service_cap  svc_cap;
+       struct cfg_eq_info  eq_info;
+       u32 func_seq_num;   /* temporary */
+};
+
+enum cfg_sub_cmd {
+       /* PPF(PF) <-> FW */
+       HINIC_CFG_NIC_CAP = 0,
+       CFG_FW_VERSION,
+       CFG_UCODE_VERSION,
+       HINIC_CFG_MBOX_CAP = 6
+};
+
+struct hinic_dev_cap {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       /* Public resource */
+       u8 sf_svc_attr;
+       u8 host_id;
+       u8 sf_en_pf;
+       u8 sf_en_vf;
+
+       u8 ep_id;
+       u8 intr_type;
+       u8 max_cos_id;
+       u8 er_id;
+       u8 port_id;
+       u8 max_vf;
+       u16 svc_cap_en;
+       u16 host_total_func;
+       u8 host_oq_id_mask_val;
+       u8 max_vf_cos_id;
+
+       u32 max_conn_num;
+       u16 max_stick2cache_num;
+       u16 max_bfilter_start_addr;
+       u16 bfilter_len;
+       u16 hash_bucket_num;
+       u8 cfg_file_ver;
+       u8 net_port_mode;
+       u8 valid_cos_bitmap;    /* every bit indicate cos is valid */
+       u8 rsvd1;
+       u32 pf_num;
+       u32 pf_id_start;
+       u32 vf_num;
+       u32 vf_id_start;
+
+       /* shared resource */
+       u32 host_pctx_num;
+       u8 host_sf_en;
+       u8 rsvd2[3];
+       u32 host_ccxt_num;
+       u32 host_scq_num;
+       u32 host_srq_num;
+       u32 host_mpt_num;
+
+       /* l2nic */
+       u16 nic_max_sq;
+       u16 nic_max_rq;
+       u16 nic_vf_max_sq;
+       u16 nic_vf_max_rq;
+       u8 nic_lro_en;
+       u8 nic_lro_sz;
+       u8 nic_tso_sz;
+       u8 rsvd3;
+
+       /* RoCE */
+       u32 roce_max_qp;
+       u32 roce_max_cq;
+       u32 roce_max_srq;
+       u32 roce_max_mpt;
+
+       u32 roce_vf_max_qp;
+       u32 roce_vf_max_cq;
+       u32 roce_vf_max_srq;
+       u32 roce_vf_max_mpt;
+
+       u32 roce_cmtt_cl_start;
+       u32 roce_cmtt_cl_end;
+       u32 roce_cmtt_cl_size;
+
+       u32 roce_dmtt_cl_start;
+       u32 roce_dmtt_cl_end;
+       u32 roce_dmtt_cl_size;
+
+       u32 roce_wqe_cl_start;
+       u32 roce_wqe_cl_end;
+       u32 roce_wqe_cl_size;
+
+       /* IWARP */
+       u32 iwarp_max_qp;
+       u32 iwarp_max_cq;
+       u32 iwarp_max_mpt;
+
+       u32 iwarp_vf_max_qp;
+       u32 iwarp_vf_max_cq;
+       u32 iwarp_vf_max_mpt;
+
+       u32 iwarp_cmtt_cl_start;
+       u32 iwarp_cmtt_cl_end;
+       u32 iwarp_cmtt_cl_size;
+
+       u32 iwarp_dmtt_cl_start;
+       u32 iwarp_dmtt_cl_end;
+       u32 iwarp_dmtt_cl_size;
+
+       u32 iwarp_wqe_cl_start;
+       u32 iwarp_wqe_cl_end;
+       u32 iwarp_wqe_cl_size;
+
+       /* FCoE */
+       u32 fcoe_max_qp;
+       u32 fcoe_max_cq;
+       u32 fcoe_max_srq;
+
+       u32 fcoe_max_cctx;
+       u32 fcoe_cctx_id_start;
+
+       u8 fcoe_vp_id_start;
+       u8 fcoe_vp_id_end;
+       u8 rsvd4[2];
+
+       /* IoE */
+       u32 ioe_max_pctx;
+       u32 ioe_max_cctx;
+
+       /* ToE */
+       u32 toe_max_pctx;
+       u32 toe_max_cq;
+       u32 toe_max_srq;
+       u32 toe_srq_id_start;
+
+       /* FC */
+       u32 fc_max_pctx;
+       u32 fc_max_scq;
+       u32 fc_max_srq;
+
+       u32 fc_max_cctx;
+       u32 fc_cctx_id_start;
+
+       u8 fc_vp_id_start;
+       u8 fc_vp_id_end;
+       u8 rsvd5[2];
+};
+
+int init_cfg_mgmt(struct hinic_hwdev *hwdev);
+void free_cfg_mgmt(struct hinic_hwdev *hwdev);
+
+/*for clear ucode&MIB stats*/
+void hinic_clear_vport_stats(struct hinic_hwdev *hwdev);
+void hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev);
+
+bool hinic_support_nic(struct hinic_hwdev *hwdev, struct nic_service_cap *cap);
+
+#endif /* _HINIC_PMD_CFG_H_ */
diff --git a/drivers/net/hinic/base/hinic_pmd_hw.h 
b/drivers/net/hinic/base/hinic_pmd_hw.h
new file mode 100644
index 000000000..16334fe4b
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_hw.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC_PMD_HW_H_
+#define _HINIC_PMD_HW_H_
+
+#ifndef __BIG_ENDIAN__
+#define __BIG_ENDIAN__    0x4321
+#endif
+
+#ifndef __LITTLE_ENDIAN__
+#define __LITTLE_ENDIAN__    0x1234
+#endif
+
+#ifdef __BYTE_ORDER__
+#undef __BYTE_ORDER__
+#endif
+/* X86 */
+#define __BYTE_ORDER__    __LITTLE_ENDIAN__
+
+#define HINIC_RECV_NEXT_AEQE   (HINIC_ERROR)
+#define HINIC_RECV_DONE                (HINIC_OK)
+
+enum hinic_mod_type {
+       HINIC_MOD_COMM = 0,     /* HW communication module */
+       HINIC_MOD_L2NIC = 1,    /* L2NIC module */
+       HINIC_MOD_CFGM = 7,     /* Configuration module */
+       HINIC_MOD_HILINK = 14,
+       HINIC_MOD_MAX   = 15
+};
+
+struct hinic_cmd_buf {
+       void            *buf;
+       dma_addr_t      dma_addr;
+       struct rte_mbuf *mbuf;
+       u16             size;
+};
+
+enum hinic_ack_type {
+       HINIC_ACK_TYPE_CMDQ,
+       HINIC_ACK_TYPE_SHARE_CQN,
+       HINIC_ACK_TYPE_APP_CQN,
+
+       HINIC_MOD_ACK_MAX = 15,
+
+};
+
+#endif /* _HINIC_PMD_HW_H_ */
diff --git a/drivers/net/hinic/base/hinic_pmd_hwdev.c 
b/drivers/net/hinic/base/hinic_pmd_hwdev.c
new file mode 100644
index 000000000..01255f3e9
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_hwdev.c
@@ -0,0 +1,1544 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#include "hinic_pmd_dpdev.h"
+
+#define HINIC_DEAULT_EQ_MSIX_PENDING_LIMIT     0
+#define HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF
+#define HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG  7
+
+#define HINIC_FLR_TIMEOUT                      1000
+
+#define HINIC_MGMT_CHANNEL_STATUS_SHIFT                0x0
+#define HINIC_MGMT_CHANNEL_STATUS_MASK         0x1
+
+#define FFM_RECORD_NUM_MAX                     32
+
+#define        HINIC_MSIX_CNT_RESEND_TIMER_SHIFT       29
+#define        HINIC_MSIX_CNT_RESEND_TIMER_MASK        0x7U
+
+#define HINIC_MSIX_CNT_SET(val, member)                \
+               (((val) & HINIC_MSIX_CNT_##member##_MASK) << \
+               HINIC_MSIX_CNT_##member##_SHIFT)
+
+#define HINIC_GET_MGMT_CHANNEL_STATUS(val, member)     \
+       (((val) >> HINIC_##member##_SHIFT) & HINIC_##member##_MASK)
+
+struct hinic_cons_idx_attr {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16     func_idx;
+       u8      dma_attr_off;
+       u8      pending_limit;
+       u8      coalescing_time;
+       u8      intr_en;
+       u16     intr_idx;
+       u32     l2nic_sqn;
+       u32     sq_id;
+       u64     ci_addr;
+};
+
+struct hinic_clear_doorbell {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16     func_idx;
+       u8      ppf_idx;
+       u8      rsvd1;
+};
+
+struct hinic_clear_resource {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16     func_idx;
+       u8      ppf_idx;
+       u8      rsvd1;
+};
+
+struct hinic_cmd_set_res_state {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16     func_idx;
+       u8      state;
+       u8      rsvd1;
+       u32     rsvd2;
+};
+
+const int hinic_hw_rx_buf_size[] = {
+       HINIC_RX_BUF_SIZE_32B,
+       HINIC_RX_BUF_SIZE_64B,
+       HINIC_RX_BUF_SIZE_96B,
+       HINIC_RX_BUF_SIZE_128B,
+       HINIC_RX_BUF_SIZE_192B,
+       HINIC_RX_BUF_SIZE_256B,
+       HINIC_RX_BUF_SIZE_384B,
+       HINIC_RX_BUF_SIZE_512B,
+       HINIC_RX_BUF_SIZE_768B,
+       HINIC_RX_BUF_SIZE_1K,
+       HINIC_RX_BUF_SIZE_1_5K,
+       HINIC_RX_BUF_SIZE_2K,
+       HINIC_RX_BUF_SIZE_3K,
+       HINIC_RX_BUF_SIZE_4K,
+       HINIC_RX_BUF_SIZE_8K,
+       HINIC_RX_BUF_SIZE_16K,
+};
+
+struct hinic_msix_config {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16     func_id;
+       u16     msix_index;
+       u8      pending_cnt;
+       u8      coalesct_timer_cnt;
+       u8      lli_tmier_cnt;
+       u8      lli_credit_cnt;
+       u8      resend_timer_cnt;
+       u8      rsvd1[3];
+};
+
+struct hinic_cmd_fault_event {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       struct hinic_fault_event event;
+};
+
+struct hinic_mgmt_watchdog_info {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u32 curr_time_h;
+       u32 curr_time_l;
+       u32 task_id;
+       u32 rsv;
+
+       u32 reg[13];
+       u32 pc;
+       u32 lr;
+       u32 cpsr;
+
+       u32 stack_top;
+       u32 stack_bottom;
+       u32 sp;
+       u32 curr_used;
+       u32 peak_used;
+       u32 is_overflow;
+
+       u32 stack_actlen;
+       u8 data[1024];
+};
+
+#define MAX_PCIE_DFX_BUF_SIZE (1024)
+
+struct hinic_pcie_dfx_ntc {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       int len;
+       u32 rsvd;
+};
+
+struct hinic_pcie_dfx_info {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u8 host_id;
+       u8 last;
+       u8 rsvd[2];
+       u32 offset;
+
+       u8 data[MAX_PCIE_DFX_BUF_SIZE];
+};
+
+struct ffm_intr_info {
+       u8 node_id;
+       /* error level of the interrupt source */
+       u8 err_level;
+       /* Classification by interrupt source properties */
+       u16 err_type;
+       u32 err_csr_addr;
+       u32 err_csr_value;
+};
+
+struct hinic_comm_board_info {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       struct hinic_board_info info;
+
+       u32     rsvd1[5];
+};
+
+struct hi30_ctle_data {
+       u8 ctlebst[3];
+       u8 ctlecmband[3];
+       u8 ctlermband[3];
+       u8 ctleza[3];
+       u8 ctlesqh[3];
+       u8 ctleactgn[3];
+       u8 ctlepassgn;
+};
+
+struct hi30_ffe_data {
+       u8 PRE2;
+       u8 PRE1;
+       u8 POST1;
+       u8 POST2;
+       u8 MAIN;
+};
+
+struct hinic_link_info {
+       u8      vendor_name[16];
+       /* port type:
+        * 1 - fiber; 2 - electric; 3 - copper; 4 - AOC; 5 - backplane;
+        * 6 - baseT; 0xffff - unknown
+        *
+        * port subtype:
+        * Only when port_type is fiber:
+        * 1 - SR; 2 - LR
+        */
+       u32     port_type;
+       u32     port_sub_type;
+       u32     cable_length;
+       u8      cable_temp;
+       u8      cable_max_speed;/* 1(G)/10(G)/25(G)... */
+       u8      sfp_type;       /* 0 - qsfp; 1 - sfp */
+       u8      rsvd0;
+       u32     power[4];       /* uW; if is sfp, only power[2] is valid */
+
+       u8      an_state;       /* 0 - off; 1 - on */
+       u8      fec;            /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */
+       u16     speed;          /* 1(G)/10(G)/25(G)... */
+
+       u8      cable_absent;   /* 0 - cable present; 1 - cable unpresent */
+       u8      alos;           /* 0 - yes; 1 - no */
+       u8      rx_los;         /* 0 - yes; 1 - no */
+       u8      pma_status;
+       u32     pma_dbg_info_reg;       /* pma debug info: */
+       u32     pma_signal_ok_reg;      /* signal ok: */
+
+       u32     pcs_err_blk_cnt_reg;    /* error block counter: */
+       u32     rf_lf_status_reg;       /* RF/LF status: */
+       u8      pcs_link_reg;           /* pcs link: */
+       u8      mac_link_reg;           /* mac link: */
+       u8      mac_tx_en;
+       u8      mac_rx_en;
+       u32     pcs_err_cnt;
+
+       u8      lane_used;
+       u8      hi30_ffe[5];
+       u8      hi30_ctle[19];
+       u8      hi30_dfe[14];
+       u8      rsvd4;
+};
+
+struct hinic_hilink_link_info {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16     port_id;
+       u8      info_type;      /* 1: link up  2: link down  3 cable plugged */
+       u8      rsvd1;
+
+       struct hinic_link_info info;
+
+       u8      rsvd2[780];
+};
+
+enum hinic_link_port_type {
+       LINK_PORT_FIBRE = 1,
+       LINK_PORT_ELECTRIC,
+       LINK_PORT_COPPER,
+       LINK_PORT_AOC,
+       LINK_PORT_BACKPLANE,
+       LINK_PORT_BASET,
+       LINK_PORT_MAX_TYPE,
+};
+
+enum hilink_fibre_subtype {
+       FIBRE_SUBTYPE_SR = 1,
+       FIBRE_SUBTYPE_LR,
+       FIBRE_SUBTYPE_MAX,
+};
+
+enum hilink_fec_type {
+       HILINK_FEC_RSFEC,
+       HILINK_FEC_BASEFEC,
+       HILINK_FEC_NOFEC,
+       HILINK_FEC_MAX_TYPE,
+};
+
+static const char *__hw_to_char_fec[HILINK_FEC_MAX_TYPE] = {
+       "RS-FEC", "BASE-FEC", "NO-FEC"};
+
+static const char *__hw_to_char_port_type[LINK_PORT_MAX_TYPE] = {
+       "Unknown", "Fibre", "Electric", "Direct Attach Copper", "AOC",
+       "Back plane", "BaseT"
+};
+
+static const char *hinic_module_link_err[LINK_ERR_NUM] = {
+       "Unrecognized module",
+};
+
+#define HINIC_DMA_ATTR_ENTRY_ST_SHIFT                          0
+#define HINIC_DMA_ATTR_ENTRY_AT_SHIFT                          8
+#define HINIC_DMA_ATTR_ENTRY_PH_SHIFT                          10
+#define HINIC_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT                 12
+#define HINIC_DMA_ATTR_ENTRY_TPH_EN_SHIFT                      13
+
+#define HINIC_DMA_ATTR_ENTRY_ST_MASK                           0xFF
+#define HINIC_DMA_ATTR_ENTRY_AT_MASK                           0x3
+#define HINIC_DMA_ATTR_ENTRY_PH_MASK                           0x3
+#define HINIC_DMA_ATTR_ENTRY_NO_SNOOPING_MASK                  0x1
+#define HINIC_DMA_ATTR_ENTRY_TPH_EN_MASK                       0x1
+
+#define HINIC_DMA_ATTR_ENTRY_SET(val, member)                  \
+               (((u32)(val) & HINIC_DMA_ATTR_ENTRY_##member##_MASK) << \
+                       HINIC_DMA_ATTR_ENTRY_##member##_SHIFT)
+
+#define HINIC_DMA_ATTR_ENTRY_CLEAR(val, member)                \
+               ((val) & (~(HINIC_DMA_ATTR_ENTRY_##member##_MASK        \
+                       << HINIC_DMA_ATTR_ENTRY_##member##_SHIFT)))
+
+#define HINIC_PCIE_ST_DISABLE                  0
+#define HINIC_PCIE_AT_DISABLE                  0
+#define HINIC_PCIE_PH_DISABLE                  0
+
+#define PCIE_MSIX_ATTR_ENTRY                   0
+
+#define HINIC_MSG_TO_MGMT_MAX_LEN              2016
+
+/**
+ * hinic_cpu_to_be32 - convert data to big endian 32 bit format
+ * @data: the data to convert
+ * @len: length of data to convert, must be Multiple of 4B
+ **/
+void hinic_cpu_to_be32(void *data, int len)
+{
+       u32 i;
+       u32 *mem = (u32 *)data;
+
+       for (i = 0; i < ((u32)len >> 2); i++) {
+               *mem = cpu_to_be32(*mem);
+               mem++;
+       }
+}
+
+/**
+ * hinic_cpu_to_be32 - convert data from big endian 32 bit format
+ * @data: the data to convert
+ * @len: length of data to convert
+ **/
+void hinic_be32_to_cpu(void *data, int len)
+{
+       int i, chunk_sz = sizeof(u32);
+       u32 *mem = (u32 *)data;
+
+       len = len / chunk_sz;
+
+       for (i = 0; i < len; i++) {
+               *mem = be32_to_cpu(*mem);
+               mem++;
+       }
+}
+
+/**
+ * hinic_set_sge - set dma area in scatter gather entry
+ * @sge: scatter gather entry
+ * @addr: dma address
+ * @len: length of relevant data in the dma address
+ **/
+void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, u32 len)
+{
+       sge->hi_addr = upper_32_bits(addr);
+       sge->lo_addr = lower_32_bits(addr);
+       sge->len  = len;
+}
+
+/**
+ * hinic_set_ci_table - set ci attribute table
+ * @hwdev: the hardware interface of a nic device
+ * @q_id: Queue id of SQ
+ * @attr: Point to SQ CI attribute table
+ * @return
+ *   0 on success and ci attribute table is filled,
+ *   negative error value otherwise.
+ **/
+int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr)
+{
+       struct hinic_cons_idx_attr cons_idx_attr;
+
+       memset(&cons_idx_attr, 0, sizeof(cons_idx_attr));
+       cons_idx_attr.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       cons_idx_attr.func_idx = hinic_global_func_id(hwdev);
+       cons_idx_attr.dma_attr_off  = attr->dma_attr_off;
+       cons_idx_attr.pending_limit = attr->pending_limit;
+       cons_idx_attr.coalescing_time = attr->coalescing_time;
+       if (attr->intr_en) {
+               cons_idx_attr.intr_en = attr->intr_en;
+               cons_idx_attr.intr_idx = attr->intr_idx;
+       }
+
+       cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
+       cons_idx_attr.sq_id = q_id;
+       cons_idx_attr.ci_addr = attr->ci_dma_base;
+
+       return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                     HINIC_MGMT_CMD_L2NIC_SQ_CI_ATTR_SET,
+                                     &cons_idx_attr, sizeof(cons_idx_attr),
+                                     NULL, NULL, 0);
+}
+
+/**
+ * get_hw_rx_buf_size - translate rx_buf_size into hw_rx_buf_size
+ * @rx_buf_sz: receive buffer size
+ * @return
+ *   hw rx buffer size
+ **/
+static u16 get_hw_rx_buf_size(int rx_buf_sz)
+{
+       u16 num_hw_types = sizeof(hinic_hw_rx_buf_size)
+                          / sizeof(hinic_hw_rx_buf_size[0]);
+       u16 i;
+
+       for (i = 0; i < num_hw_types; i++) {
+               if (hinic_hw_rx_buf_size[i] == rx_buf_sz)
+                       return i;
+       }
+
+       PMD_DRV_LOG(ERR, "Hw can't support rx buf size of %d", rx_buf_sz);
+
+       return DEFAULT_RX_BUF_SIZE;     /* default 2K */
+}
+
+/**
+ * hinic_set_pagesize - set page size to vat table
+ * @hwdev: the hardware interface of a nic device
+ * @page_size: vat page size
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+int hinic_set_pagesize(void *hwdev, u8 page_size)
+{
+       struct hinic_page_size cmd;
+
+       if (page_size > HINIC_PAGE_SIZE_MAX) {
+               PMD_DRV_LOG(ERR, "Invalid page_size %u, bigger than %u",
+                      page_size, HINIC_PAGE_SIZE_MAX);
+               return -EINVAL;
+       }
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       cmd.func_idx = hinic_global_func_id(hwdev);
+       cmd.ppf_idx = hinic_ppf_idx(hwdev);
+       cmd.page_size = page_size;
+
+       return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                       HINIC_MGMT_CMD_PAGESIZE_SET,
+                                       &cmd, sizeof(cmd),
+                                       NULL, NULL, 0);
+}
+
+/**
+ * hinic_set_root_ctxt - init root context in NIC
+ * @hwdev: the hardware interface of a nic device
+ * @rq_depth: the depth of receive queue
+ * @sq_depth: the depth of transmit queue
+ * @rx_buf_sz: receive buffer size from app
+ * Return: 0 on success, negative error value otherwise.
+ **/
+int hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz)
+{
+       struct hinic_root_ctxt root_ctxt;
+
+       memset(&root_ctxt, 0, sizeof(root_ctxt));
+       root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       root_ctxt.func_idx = hinic_global_func_id(hwdev);
+       root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
+       root_ctxt.set_cmdq_depth = 0;
+       root_ctxt.cmdq_depth = 0;
+       root_ctxt.lro_en = 1;
+       root_ctxt.rq_depth  = (u16)ilog2(rq_depth);
+       root_ctxt.rx_buf_sz = get_hw_rx_buf_size(rx_buf_sz);
+       root_ctxt.sq_depth  = (u16)ilog2(sq_depth);
+
+       return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                     HINIC_MGMT_CMD_VAT_SET,
+                                     &root_ctxt, sizeof(root_ctxt),
+                                     NULL, NULL, 0);
+}
+
+/**
+ * hinic_clean_root_ctxt - clean root context table in NIC
+ * @hwdev: the hardware interface of a nic device
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+int hinic_clean_root_ctxt(void *hwdev)
+{
+       struct hinic_root_ctxt root_ctxt;
+
+       memset(&root_ctxt, 0, sizeof(root_ctxt));
+       root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       root_ctxt.func_idx = hinic_global_func_id(hwdev);
+       root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
+       root_ctxt.set_cmdq_depth = 0;
+       root_ctxt.cmdq_depth = 0;
+       root_ctxt.lro_en = 0;
+       root_ctxt.rq_depth  = 0;
+       root_ctxt.rx_buf_sz = 0;
+       root_ctxt.sq_depth  = 0;
+
+       return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                     HINIC_MGMT_CMD_VAT_SET,
+                                     &root_ctxt, sizeof(root_ctxt),
+                                     NULL, NULL, 0);
+}
+
+static int wait_for_flr_finish(struct hinic_hwif *hwif)
+{
+       unsigned long end;
+       enum hinic_pf_status status;
+
+       end = jiffies + msecs_to_jiffies(HINIC_FLR_TIMEOUT);
+       do {
+               status = hinic_get_pf_status(hwif);
+               if (status == HINIC_PF_STATUS_FLR_FINISH_FLAG) {
+                       hinic_set_pf_status(hwif, HINIC_PF_STATUS_ACTIVE_FLAG);
+                       return 0;
+               }
+
+               rte_delay_ms(10);
+       } while (time_before(jiffies, end));
+
+       return -EFAULT;
+}
+
+#define HINIC_WAIT_CMDQ_IDLE_TIMEOUT           1000
+
+static int wait_cmdq_stop(struct hinic_hwdev *hwdev)
+{
+       enum hinic_cmdq_type cmdq_type;
+       struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
+       unsigned long end;
+       int err = 0;
+
+       if (!(cmdqs->status & HINIC_CMDQ_ENABLE))
+               return 0;
+
+       cmdqs->status &= ~HINIC_CMDQ_ENABLE;
+
+       end = jiffies + msecs_to_jiffies(HINIC_WAIT_CMDQ_IDLE_TIMEOUT);
+       do {
+               err = 0;
+               cmdq_type = HINIC_CMDQ_SYNC;
+               for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
+                       if (!hinic_cmdq_idle(&cmdqs->cmdq[cmdq_type])) {
+                               err = -EBUSY;
+                               break;
+                       }
+               }
+
+               if (!err)
+                       return 0;
+
+               rte_delay_ms(1);
+       } while (time_before(jiffies, end));
+
+       cmdqs->status |= HINIC_CMDQ_ENABLE;
+
+       return err;
+}
+
+/**
+ * hinic_pf_rx_tx_flush - clean up hardware resource
+ * @hwdev: the hardware interface of a nic device
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
+{
+       struct hinic_hwif *hwif = hwdev->hwif;
+       struct hinic_clear_doorbell clear_db;
+       struct hinic_clear_resource clr_res;
+       int err;
+
+       rte_delay_ms(100);
+
+       err = wait_cmdq_stop(hwdev);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Cmdq is still working");
+               return err;
+       }
+
+       hinic_disable_doorbell(hwif);
+       memset(&clear_db, 0, sizeof(clear_db));
+       clear_db.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       clear_db.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+       clear_db.ppf_idx  = HINIC_HWIF_PPF_IDX(hwif);
+       err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                    HINIC_MGMT_CMD_FLUSH_DOORBELL, &clear_db,
+                                    sizeof(clear_db), NULL, NULL, 0);
+       if (err)
+               PMD_DRV_LOG(WARNING, "Flush doorbell failed");
+
+       hinic_set_pf_status(hwif, HINIC_PF_STATUS_FLR_START_FLAG);
+       memset(&clr_res, 0, sizeof(clr_res));
+       clr_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       clr_res.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+       clr_res.ppf_idx  = HINIC_HWIF_PPF_IDX(hwif);
+
+       err = hinic_msg_to_mgmt_no_ack(hwdev, HINIC_MOD_COMM,
+                                      HINIC_MGMT_CMD_START_FLR, &clr_res,
+                                      sizeof(clr_res), NULL, NULL);
+       if (err)
+               PMD_DRV_LOG(WARNING, "Notice flush message failed");
+
+       err = wait_for_flr_finish(hwif);
+       if (err)
+               PMD_DRV_LOG(WARNING, "Wait firmware FLR timeout");
+
+       hinic_enable_doorbell(hwif);
+
+       err = hinic_reinit_cmdq_ctxts(hwdev);
+       if (err)
+               PMD_DRV_LOG(WARNING, "Reinit cmdq failed");
+
+       return 0;
+}
+
+int hinic_func_rx_tx_flush(struct hinic_hwdev *hwdev)
+{
+       return hinic_pf_rx_tx_flush(hwdev);
+}
+
+/**
+ * hinic_get_interrupt_cfg - get interrupt configuration from NIC
+ * @hwdev: the hardware interface of a nic device
+ * @interrupt_info: Information of Interrupt aggregation
+ * Return: 0 on success, negative error value otherwise.
+ **/
+static int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
+                               struct nic_interrupt_info *interrupt_info)
+{
+       struct hinic_msix_config msix_cfg;
+       u16 out_size = sizeof(msix_cfg);
+       int err;
+
+       memset(&msix_cfg, 0, sizeof(msix_cfg));
+       msix_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       msix_cfg.func_id = hinic_global_func_id(hwdev);
+       msix_cfg.msix_index = interrupt_info->msix_index;
+
+       err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                    HINIC_MGMT_CMD_MSI_CTRL_REG_RD_BY_UP,
+                                    &msix_cfg, sizeof(msix_cfg),
+                                    &msix_cfg, &out_size, 0);
+       if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Get interrupt config failed, ret: %d",
+                       msix_cfg.mgmt_msg_head.status);
+               return -EINVAL;
+       }
+
+       interrupt_info->lli_credit_limit = msix_cfg.lli_credit_cnt;
+       interrupt_info->lli_timer_cfg = msix_cfg.lli_tmier_cnt;
+       interrupt_info->pending_limt = msix_cfg.pending_cnt;
+       interrupt_info->coalesc_timer_cfg = msix_cfg.coalesct_timer_cnt;
+       interrupt_info->resend_timer_cfg = msix_cfg.resend_timer_cnt;
+       return 0;
+}
+
+/**
+ * hinic_set_interrupt_cfg - set interrupt configuration to NIC
+ * @hwdev: the hardware interface of a nic device
+ * @interrupt_info: Information of Interrupt aggregation
+ * Return: 0 on success, negative error value otherwise.
+ **/
+int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
+                           struct nic_interrupt_info interrupt_info)
+{
+       struct hinic_msix_config msix_cfg;
+       struct nic_interrupt_info temp_info;
+       u16 out_size = sizeof(msix_cfg);
+       int err;
+
+       memset(&msix_cfg, 0, sizeof(msix_cfg));
+       msix_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       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;
+
+       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;
+       msix_cfg.coalesct_timer_cnt = temp_info.coalesc_timer_cfg;
+       msix_cfg.resend_timer_cnt = temp_info.resend_timer_cfg;
+
+       if (interrupt_info.lli_set) {
+               msix_cfg.lli_credit_cnt = interrupt_info.lli_credit_limit;
+               msix_cfg.lli_tmier_cnt = interrupt_info.lli_timer_cfg;
+       }
+
+       if (interrupt_info.interrupt_coalesc_set) {
+               msix_cfg.pending_cnt = interrupt_info.pending_limt;
+               msix_cfg.coalesct_timer_cnt = interrupt_info.coalesc_timer_cfg;
+               msix_cfg.resend_timer_cnt = interrupt_info.resend_timer_cfg;
+       }
+
+       err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                    HINIC_MGMT_CMD_MSI_CTRL_REG_WR_BY_UP,
+                                    &msix_cfg, sizeof(msix_cfg),
+                                    &msix_cfg, &out_size, 0);
+       if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Set interrupt config failed, ret: %d",
+                       msix_cfg.mgmt_msg_head.status);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * hinic_misx_intr_clear_resend_bit - clear interrupt resend configuration
+ * @hwdev: the hardware interface of a nic device
+ * @msix_idx: Index of msix interrupt
+ * @clear_resend_en: enable flag of clear resend configuration
+ **/
+void hinic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx,
+                                     u8 clear_resend_en)
+{
+       struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+       u32 msix_ctrl = 0, addr;
+
+       msix_ctrl = HINIC_MSIX_CNT_SET(clear_resend_en, RESEND_TIMER);
+
+       addr = HINIC_CSR_MSIX_CNT_ADDR(msix_idx);
+
+       hinic_hwif_write_reg(hwif, addr, msix_ctrl);
+}
+
+/**
+ * init_aeqs_msix_attr - Init interrupt attributes of aeq
+ * @hwdev: the hardware interface of a nic device
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+int init_aeqs_msix_attr(void *hwdev)
+{
+       struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
+       struct hinic_aeqs *aeqs = nic_hwdev->aeqs;
+       struct nic_interrupt_info info = {0};
+       struct hinic_eq *eq;
+       u16 q_id;
+       int err;
+
+       info.lli_set = 0;
+       info.interrupt_coalesc_set = 1;
+       info.pending_limt = HINIC_DEAULT_EQ_MSIX_PENDING_LIMIT;
+       info.coalesc_timer_cfg = HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG;
+       info.resend_timer_cfg = HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
+
+       for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) {
+               eq = &aeqs->aeq[q_id];
+               info.msix_index = eq->eq_irq.msix_entry_idx;
+               err = hinic_set_interrupt_cfg(hwdev, info);
+               if (err) {
+                       PMD_DRV_LOG(ERR, "Set msix attr for aeq %d failed",
+                                   q_id);
+                       return -EFAULT;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * set_pf_dma_attr_entry - set the dma attributes for entry
+ * @hwdev: the pointer to the private hardware device object
+ * @entry_idx: the entry index in the dma table
+ * @st: PCIE TLP steering tag
+ * @at:        PCIE TLP AT field
+ * @ph: PCIE TLP Processing Hint field
+ * @no_snooping: PCIE TLP No snooping
+ * @tph_en: PCIE TLP Processing Hint Enable
+ **/
+static void set_pf_dma_attr_entry(struct hinic_hwdev *hwdev, u32 entry_idx,
+                                 u8 st, u8 at, u8 ph,
+                                 enum hinic_pcie_nosnoop no_snooping,
+                                 enum hinic_pcie_tph tph_en)
+{
+       u32 addr, val, dma_attr_entry;
+
+       /* Read Modify Write */
+       addr = HINIC_CSR_DMA_ATTR_TBL_ADDR(entry_idx);
+
+       val = hinic_hwif_read_reg(hwdev->hwif, addr);
+       val = HINIC_DMA_ATTR_ENTRY_CLEAR(val, ST)       &
+               HINIC_DMA_ATTR_ENTRY_CLEAR(val, AT)     &
+               HINIC_DMA_ATTR_ENTRY_CLEAR(val, PH)     &
+               HINIC_DMA_ATTR_ENTRY_CLEAR(val, NO_SNOOPING)    &
+               HINIC_DMA_ATTR_ENTRY_CLEAR(val, TPH_EN);
+
+       dma_attr_entry = HINIC_DMA_ATTR_ENTRY_SET(st, ST)       |
+                        HINIC_DMA_ATTR_ENTRY_SET(at, AT)       |
+                        HINIC_DMA_ATTR_ENTRY_SET(ph, PH)       |
+                        HINIC_DMA_ATTR_ENTRY_SET(no_snooping, NO_SNOOPING) |
+                        HINIC_DMA_ATTR_ENTRY_SET(tph_en, TPH_EN);
+
+       val |= dma_attr_entry;
+       hinic_hwif_write_reg(hwdev->hwif, addr, val);
+}
+
+/**
+ * dma_attr_table_init - initialize the the default dma attributes
+ * @hwdev: the pointer to the private hardware device object
+ **/
+static void dma_attr_table_init(struct hinic_hwdev *hwdev)
+{
+       if (HINIC_IS_VF(hwdev))
+               return;
+
+       set_pf_dma_attr_entry(hwdev, PCIE_MSIX_ATTR_ENTRY,
+                             HINIC_PCIE_ST_DISABLE,
+                             HINIC_PCIE_AT_DISABLE,
+                             HINIC_PCIE_PH_DISABLE,
+                             HINIC_PCIE_SNOOP,
+                             HINIC_PCIE_TPH_DISABLE);
+}
+
+int hinic_init_attr_table(struct hinic_hwdev *hwdev)
+{
+       dma_attr_table_init(hwdev);
+
+       return init_aeqs_msix_attr(hwdev);
+}
+
+static int hinic_get_mgmt_channel_status(void *handle)
+{
+       struct hinic_hwdev *hwdev = (struct hinic_hwdev *)handle;
+       u32 val;
+
+       if (!hwdev)
+               return true;
+
+       val = hinic_hwif_read_reg(hwdev->hwif, HINIC_ICPL_RESERVD_ADDR);
+
+       return HINIC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
+}
+
+int hinic_msg_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)
+{
+       int rc = HINIC_ERROR;
+
+       if (!hwdev || in_size > HINIC_MSG_TO_MGMT_MAX_LEN)
+               return -EINVAL;
+
+       /* If status is hot upgrading, don't send message to mgmt */
+       if (hinic_get_mgmt_channel_status(hwdev))
+               return -EPERM;
+
+       rc = hinic_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in,
+                                  in_size, buf_out, out_size,
+                                  timeout);
+
+       return rc;
+}
+
+#define FAULT_SHOW_STR_LEN 16
+static void fault_report_show(struct hinic_hwdev *hwdev,
+                             struct hinic_fault_event *event)
+{
+       char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = {
+               "chip", "ucode", "mem rd timeout", "mem wr timeout",
+               "reg rd timeout", "reg wr timeout"};
+       char fault_level[FAULT_LEVEL_MAX][FAULT_SHOW_STR_LEN + 1] = {
+               "fatal", "reset", "flr", "general", "suggestion"};
+       char type_str[FAULT_SHOW_STR_LEN + 1] = { 0 };
+       char level_str[FAULT_SHOW_STR_LEN + 1] = { 0 };
+       u8 err_level;
+
+       PMD_DRV_LOG(WARNING, "Fault event report received, func_id: %d",
+                hinic_global_func_id(hwdev));
+
+       if (event->type < FAULT_TYPE_MAX)
+               strncpy(type_str, fault_type[event->type], FAULT_SHOW_STR_LEN);
+       else
+               strncpy(type_str, "unknown", FAULT_SHOW_STR_LEN);
+       PMD_DRV_LOG(WARNING, "fault type:    %d [%s]",
+                event->type, type_str);
+       PMD_DRV_LOG(WARNING, "fault val[0]:  0x%08x",
+                event->event.val[0]);
+       PMD_DRV_LOG(WARNING, "fault val[1]:  0x%08x",
+                event->event.val[1]);
+       PMD_DRV_LOG(WARNING, "fault val[2]:  0x%08x",
+                event->event.val[2]);
+       PMD_DRV_LOG(WARNING, "fault val[3]:  0x%08x",
+                event->event.val[3]);
+
+       switch (event->type) {
+       case FAULT_TYPE_CHIP:
+               err_level = event->event.chip.err_level;
+               if (err_level < FAULT_LEVEL_MAX)
+                       strncpy(level_str, fault_level[err_level],
+                               FAULT_SHOW_STR_LEN);
+               else
+                       strncpy(level_str, "unknown",
+                               FAULT_SHOW_STR_LEN);
+
+               PMD_DRV_LOG(WARNING, "err_level:     %d [%s]",
+                        err_level, level_str);
+
+               if (err_level == FAULT_LEVEL_SERIOUS_FLR) {
+                       PMD_DRV_LOG(WARNING, "flr func_id:   %d",
+                                event->event.chip.func_id);
+               } else {
+                       PMD_DRV_LOG(WARNING, "node_id:       %d",
+                                event->event.chip.node_id);
+                       PMD_DRV_LOG(WARNING, "err_type:      %d",
+                                event->event.chip.err_type);
+                       PMD_DRV_LOG(WARNING, "err_csr_addr:  %d",
+                                event->event.chip.err_csr_addr);
+                       PMD_DRV_LOG(WARNING, "err_csr_value: %d",
+                                event->event.chip.err_csr_value);
+               }
+               break;
+       case FAULT_TYPE_UCODE:
+               PMD_DRV_LOG(WARNING, "cause_id:      %d",
+                        event->event.ucode.cause_id);
+               PMD_DRV_LOG(WARNING, "core_id:       %d",
+                        event->event.ucode.core_id);
+               PMD_DRV_LOG(WARNING, "c_id:          %d",
+                        event->event.ucode.c_id);
+               PMD_DRV_LOG(WARNING, "epc:           %d",
+                        event->event.ucode.epc);
+               break;
+       case FAULT_TYPE_MEM_RD_TIMEOUT:
+       case FAULT_TYPE_MEM_WR_TIMEOUT:
+               PMD_DRV_LOG(WARNING, "err_csr_ctrl:  %d",
+                        event->event.mem_timeout.err_csr_ctrl);
+               PMD_DRV_LOG(WARNING, "err_csr_data:  %d",
+                        event->event.mem_timeout.err_csr_data);
+               PMD_DRV_LOG(WARNING, "ctrl_tab:      %d",
+                        event->event.mem_timeout.ctrl_tab);
+               PMD_DRV_LOG(WARNING, "mem_index:     %d",
+                        event->event.mem_timeout.mem_index);
+               break;
+       case FAULT_TYPE_REG_RD_TIMEOUT:
+       case FAULT_TYPE_REG_WR_TIMEOUT:
+               PMD_DRV_LOG(WARNING, "err_csr:       %d",
+                        event->event.reg_timeout.err_csr);
+               break;
+       default:
+               break;
+       }
+}
+
+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;
+
+       memset(&res_state, 0, sizeof(res_state));
+       res_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       res_state.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+       res_state.state = state;
+
+       return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                HINIC_MGMT_CMD_RES_STATE_SET,
+                                &res_state, sizeof(res_state), NULL, NULL, 0);
+}
+
+/**
+ * hinic_activate_hwdev_state - Active host nic state and notify mgmt channel
+ * that host nic is ready.
+ * @hwdev: the hardware interface of a nic device
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+int hinic_activate_hwdev_state(struct hinic_hwdev *hwdev)
+{
+       int rc = HINIC_OK;
+
+       if (!hwdev)
+               return -EINVAL;
+
+       if (!HINIC_IS_VF(hwdev))
+               hinic_set_pf_status(hwdev->hwif,
+                                   HINIC_PF_STATUS_ACTIVE_FLAG);
+
+       rc = resources_state_set(hwdev, HINIC_RES_ACTIVE);
+       if (rc) {
+               PMD_DRV_LOG(ERR, "Initialize resources state failed");
+               return rc;
+       }
+
+       return 0;
+}
+
+/**
+ * hinic_deactivate_hwdev_state - Deactivate host nic state and notify mgmt
+ * channel that host nic is not ready.
+ * @hwdev: the pointer to the private hardware device object
+ **/
+void hinic_deactivate_hwdev_state(struct hinic_hwdev *hwdev)
+{
+       int rc = HINIC_OK;
+
+       if (!hwdev)
+               return;
+
+       rc = resources_state_set(hwdev, HINIC_RES_CLEAN);
+       if (rc)
+               PMD_DRV_LOG(ERR, "Deinit resources state failed");
+
+       if (!HINIC_IS_VF(hwdev))
+               hinic_set_pf_status(hwdev->hwif, HINIC_PF_STATUS_INIT);
+}
+
+int hinic_get_board_info(void *hwdev, struct hinic_board_info *info)
+{
+       struct hinic_comm_board_info board_info;
+       u16 out_size = sizeof(board_info);
+       int err;
+
+       if (!hwdev || !info)
+               return -EINVAL;
+
+       memset(&board_info, 0, sizeof(board_info));
+       board_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                    HINIC_MGMT_CMD_GET_BOARD_INFO,
+                                    &board_info, sizeof(board_info),
+                                    &board_info, &out_size, 0);
+       if (err || board_info.mgmt_msg_head.status || !out_size) {
+               PMD_DRV_LOG(ERR, "Failed to get board info, err: %d, status: 
0x%x, out size: 0x%x",
+                       err, board_info.mgmt_msg_head.status, out_size);
+               return -EFAULT;
+       }
+
+       memcpy(info, &board_info.info, sizeof(*info));
+       return 0;
+}
+
+/**
+ * hinic_l2nic_reset - Restore the initial state of NIC
+ * @hwdev: the hardware interface of a nic device
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
+{
+       struct hinic_hwif *hwif = hwdev->hwif;
+       struct hinic_l2nic_reset l2nic_reset;
+       int err = 0;
+
+       err = hinic_set_vport_enable(hwdev, false);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Set vport disable failed");
+               return err;
+       }
+
+       rte_delay_ms(100);
+
+       memset(&l2nic_reset, 0, sizeof(l2nic_reset));
+       l2nic_reset.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       l2nic_reset.func_id = HINIC_HWIF_GLOBAL_IDX(hwif);
+       err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                    HINIC_MGMT_CMD_L2NIC_RESET,
+                                    &l2nic_reset, sizeof(l2nic_reset),
+                                    NULL, NULL, 0);
+       if (err || l2nic_reset.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Reset L2NIC resources failed");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static void hinic_show_sw_watchdog_timeout_info(struct hinic_hwdev *hwdev,
+                                               void *buf_in, u16 in_size,
+                                               void *buf_out, u16 *out_size)
+{
+       struct hinic_mgmt_watchdog_info *watchdog_info;
+       u32 *dump_addr, *reg, stack_len, i, j;
+
+       if (in_size != sizeof(*watchdog_info)) {
+               PMD_DRV_LOG(ERR, "Invalid mgmt watchdog report, length: %d, 
should be %ld",
+                       in_size, sizeof(*watchdog_info));
+               return;
+       }
+
+       watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_in;
+
+       PMD_DRV_LOG(ERR, "Mgmt deadloop time: 0x%x 0x%x, task id: 0x%x, sp: 
0x%x",
+               watchdog_info->curr_time_h, watchdog_info->curr_time_l,
+               watchdog_info->task_id, watchdog_info->sp);
+       PMD_DRV_LOG(ERR, "Stack current used: 0x%x, peak used: 0x%x, overflow 
flag: 0x%x, top: 0x%x, bottom: 0x%x",
+               watchdog_info->curr_used, watchdog_info->peak_used,
+               watchdog_info->is_overflow, watchdog_info->stack_top,
+               watchdog_info->stack_bottom);
+
+       PMD_DRV_LOG(ERR, "Mgmt pc: 0x%08x, lr: 0x%08x, cpsr:0x%08x",
+               watchdog_info->pc, watchdog_info->lr, watchdog_info->cpsr);
+
+       PMD_DRV_LOG(ERR, "Mgmt register info");
+
+       for (i = 0; i < 3; i++) {
+               reg = watchdog_info->reg + (u64)(u32)(4 * i);
+               PMD_DRV_LOG(ERR, "0x%08x 0x%08x 0x%08x 0x%08x",
+                       *(reg), *(reg + 1), *(reg + 2), *(reg + 3));
+       }
+
+       PMD_DRV_LOG(ERR, "0x%08x", watchdog_info->reg[12]);
+
+       if (watchdog_info->stack_actlen <= 1024) {
+               stack_len = watchdog_info->stack_actlen;
+       } else {
+               PMD_DRV_LOG(ERR, "Oops stack length: 0x%x is wrong",
+                       watchdog_info->stack_actlen);
+               stack_len = 1024;
+       }
+
+       PMD_DRV_LOG(ERR, "Mgmt dump stack, 16Bytes per line(start from sp)");
+       for (i = 0; i < (stack_len / 16); i++) {
+               dump_addr = (u32 *)(watchdog_info->data + ((u64)(u32)(i * 16)));
+               PMD_DRV_LOG(ERR, "0x%08x 0x%08x 0x%08x 0x%08x",
+                       *dump_addr, *(dump_addr + 1), *(dump_addr + 2),
+                       *(dump_addr + 3));
+       }
+
+       for (j = 0; j < ((stack_len % 16) / 4); j++) {
+               dump_addr = (u32 *)(watchdog_info->data +
+                           ((u64)(u32)(i * 16 + j * 4)));
+               PMD_DRV_LOG(ERR, "0x%08x", *dump_addr);
+       }
+
+       *out_size = sizeof(*watchdog_info);
+       watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_out;
+       watchdog_info->mgmt_msg_head.status = 0;
+}
+
+static void hinic_show_pcie_dfx_info(struct hinic_hwdev *hwdev,
+                                    void *buf_in, u16 in_size,
+                                    void *buf_out, u16 *out_size)
+{
+       struct hinic_pcie_dfx_ntc *notice_info =
+               (struct hinic_pcie_dfx_ntc *)buf_in;
+       struct hinic_pcie_dfx_info dfx_info;
+       u16 size = 0;
+       u16 cnt = 0;
+       u32 num = 0;
+       u32 i, j;
+       int err;
+       u32 *reg;
+
+       if (in_size != sizeof(*notice_info)) {
+               PMD_DRV_LOG(ERR, "Invalid pcie dfx notice info, length: %d, 
should be %ld.",
+                       in_size, sizeof(*notice_info));
+               return;
+       }
+
+       ((struct hinic_pcie_dfx_ntc *)buf_out)->mgmt_msg_head.status = 0;
+       *out_size = sizeof(*notice_info);
+       memset(&dfx_info, 0, sizeof(dfx_info));
+       num = (u32)(notice_info->len / 1024);
+       PMD_DRV_LOG(INFO, "INFO LEN: %d", notice_info->len);
+       PMD_DRV_LOG(INFO, "PCIE DFX:");
+       dfx_info.host_id = 0;
+       dfx_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       for (i = 0; i < num; i++) {
+               dfx_info.offset = i * MAX_PCIE_DFX_BUF_SIZE;
+               if (i == (num - 1))
+                       dfx_info.last = 1;
+               size = sizeof(dfx_info);
+               err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+                                            HINIC_MGMT_CMD_PCIE_DFX_GET,
+                                            &dfx_info, sizeof(dfx_info),
+                                            &dfx_info, &size, 0);
+               if (err || dfx_info.mgmt_msg_head.status || !size) {
+                       PMD_DRV_LOG(ERR, "Failed to get pcie dfx info, err: %d, 
status: 0x%x, out size: 0x%x",
+                               err, dfx_info.mgmt_msg_head.status, size);
+                       return;
+               }
+
+               reg = (u32 *)dfx_info.data;
+               for (j = 0; j < 256; j = j + 8) {
+                       PMD_DRV_LOG(ERR, "0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x 
0x%08x 0x%08x 0x%08x 0x%08x",
+                               cnt, reg[j], reg[(u32)(j + 1)],
+                               reg[(u32)(j + 2)], reg[(u32)(j + 3)],
+                               reg[(u32)(j + 4)], reg[(u32)(j + 5)],
+                               reg[(u32)(j + 6)], reg[(u32)(j + 7)]);
+                       cnt = cnt + 32;
+               }
+               memset(dfx_info.data, 0, MAX_PCIE_DFX_BUF_SIZE);
+       }
+}
+
+static void
+hinic_show_ffm_info(struct hinic_hwdev *hwdev, void *buf_in, u16 in_size,
+                       void *buf_out, u16 *out_size)
+{
+       struct ffm_intr_info *intr;
+       struct hinic_nic_dev *nic_dev = (struct hinic_nic_dev *)hwdev->dev_hdl;
+
+       if (in_size != sizeof(struct ffm_intr_info)) {
+               PMD_DRV_LOG(ERR, "Invalid input buffer len, length: %d, should 
be %ld.",
+                       in_size, sizeof(struct ffm_intr_info));
+               return;
+       }
+
+       if (nic_dev->ffm_num < FFM_RECORD_NUM_MAX) {
+               nic_dev->ffm_num++;
+               intr = (struct ffm_intr_info *)buf_in;
+               PMD_DRV_LOG(WARNING, 
"node_id(%d),err_csr_addr(0x%x),err_csr_val(0x%x),err_level(0x%x),err_type(0x%x)",
+                           intr->node_id,
+                           intr->err_csr_addr,
+                           intr->err_csr_value,
+                           intr->err_level,
+                           intr->err_type);
+       }
+}
+
+void hinic_comm_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
+                                  void *buf_in, u16 in_size,
+                                  void *buf_out, u16 *out_size)
+{
+       struct hinic_cmd_fault_event *fault_event, *ret_fault_event;
+
+       if (!hwdev)
+               return;
+
+       *out_size = 0;
+
+       switch (cmd) {
+       case HINIC_MGMT_CMD_FAULT_REPORT:
+               if (in_size != sizeof(*fault_event)) {
+                       PMD_DRV_LOG(ERR, "Invalid fault event report, length: 
%d, should be %ld",
+                               in_size, sizeof(*fault_event));
+                       return;
+               }
+
+               fault_event = (struct hinic_cmd_fault_event *)buf_in;
+               fault_report_show(hwdev, &fault_event->event);
+
+               if (hinic_func_type(hwdev) != TYPE_VF) {
+                       ret_fault_event =
+                               (struct hinic_cmd_fault_event *)buf_out;
+                       ret_fault_event->mgmt_msg_head.status = 0;
+                       *out_size = sizeof(*ret_fault_event);
+               }
+               break;
+
+       case HINIC_MGMT_CMD_WATCHDOG_INFO:
+               hinic_show_sw_watchdog_timeout_info(hwdev, buf_in, in_size,
+                                                   buf_out, out_size);
+               break;
+
+       case HINIC_MGMT_CMD_PCIE_DFX_NTC:
+               hinic_show_pcie_dfx_info(hwdev, buf_in, in_size,
+                                        buf_out, out_size);
+               break;
+
+       case HINIC_MGMT_CMD_FFM_SET:
+               hinic_show_ffm_info(hwdev, buf_in, in_size, buf_out, out_size);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void hinic_cable_status_event(struct hinic_hwdev *hwdev, u8 cmd,
+                                    void *buf_in, u16 in_size, void *buf_out,
+                                    u16 *out_size)
+{
+       struct hinic_cable_plug_event *plug_event;
+       struct hinic_link_err_event *link_err;
+
+       if (cmd == HINIC_PORT_CMD_CABLE_PLUG_EVENT) {
+               plug_event = (struct hinic_cable_plug_event *)buf_in;
+               PMD_DRV_LOG(INFO, "Port module event: Cable %s",
+                        plug_event->plugged ? "plugged" : "unplugged");
+
+               *out_size = sizeof(*plug_event);
+               plug_event = (struct hinic_cable_plug_event *)buf_out;
+               plug_event->mgmt_msg_head.status = 0;
+       } else if (cmd == HINIC_PORT_CMD_LINK_ERR_EVENT) {
+               link_err = (struct hinic_link_err_event *)buf_in;
+               if (link_err->err_type >= LINK_ERR_NUM) {
+                       PMD_DRV_LOG(ERR, "Link failed, Unknown type: 0x%x",
+                               link_err->err_type);
+               } else {
+                       PMD_DRV_LOG(INFO, "Link failed, type: 0x%x: %s",
+                                link_err->err_type,
+                                hinic_module_link_err[link_err->err_type]);
+               }
+
+               *out_size = sizeof(*link_err);
+               link_err = (struct hinic_link_err_event *)buf_out;
+               link_err->mgmt_msg_head.status = 0;
+       }
+}
+
+void hinic_l2nic_async_event_handle(struct hinic_hwdev *hwdev,
+                                   void *param, u8 cmd,
+                                   void *buf_in, u16 in_size,
+                                   void *buf_out, u16 *out_size)
+{
+       struct hinic_port_link_status *in_link;
+       struct rte_eth_dev *eth_dev;
+
+       if (!hwdev)
+               return;
+
+       *out_size = 0;
+
+       switch (cmd) {
+       case HINIC_PORT_CMD_LINK_STATUS_REPORT:
+               eth_dev = (struct rte_eth_dev *)param;
+               in_link = (struct hinic_port_link_status *)buf_in;
+               PMD_DRV_LOG(INFO, "Link status event report, dev_name: %s, 
port_id: %d, link_status: %s",
+                        eth_dev->data->name, eth_dev->data->port_id,
+                        in_link->link ? "UP" : "DOWN");
+
+               hinic_lsc_process(eth_dev, in_link->link);
+               break;
+
+       case HINIC_PORT_CMD_CABLE_PLUG_EVENT:
+       case HINIC_PORT_CMD_LINK_ERR_EVENT:
+               hinic_cable_status_event(hwdev, cmd, buf_in, in_size,
+                                        buf_out, out_size);
+               break;
+
+       case HINIC_PORT_CMD_MGMT_RESET:
+               PMD_DRV_LOG(WARNING, "Mgmt is reset");
+               break;
+
+       default:
+               PMD_DRV_LOG(ERR, "Unsupported event %d to process",
+                       cmd);
+               break;
+       }
+}
+
+static void print_cable_info(struct hinic_hwdev *hwdev,
+                            struct hinic_link_info *info)
+{
+       char tmp_str[512] = {0};
+       char tmp_vendor[17] = {0};
+       const char *port_type = "Unknown port type";
+       int i;
+
+       if (info->cable_absent) {
+               PMD_DRV_LOG(INFO, "Cable unpresent");
+               return;
+       }
+
+       if (info->port_type < LINK_PORT_MAX_TYPE)
+               port_type = __hw_to_char_port_type[info->port_type];
+       else
+               PMD_DRV_LOG(INFO, "Unknown port type: %u",
+                        info->port_type);
+       if (info->port_type == LINK_PORT_FIBRE) {
+               if (info->port_sub_type == FIBRE_SUBTYPE_SR)
+                       port_type = "Fibre-SR";
+               else if (info->port_sub_type == FIBRE_SUBTYPE_LR)
+                       port_type = "Fibre-LR";
+       }
+
+       for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) {
+               if (info->vendor_name[i] == ' ')
+                       info->vendor_name[i] = '\0';
+               else
+                       break;
+       }
+
+       memcpy(tmp_vendor, info->vendor_name, sizeof(info->vendor_name));
+       snprintf(tmp_str, (sizeof(tmp_str) - 1),
+                "Vendor: %s, %s, %s, length: %um, max_speed: %uGbps",
+                tmp_vendor, info->sfp_type ? "SFP" : "QSFP", port_type,
+                info->cable_length, info->cable_max_speed);
+       if (info->port_type != LINK_PORT_COPPER)
+               snprintf(tmp_str + strlen(tmp_str), (sizeof(tmp_str) - 1),
+                        "%s, Temperature: %u", tmp_str,
+                        info->cable_temp);
+
+       PMD_DRV_LOG(INFO, "Cable information: %s", tmp_str);
+}
+
+static void print_hi30_status(struct hinic_hwdev *hwdev,
+                             struct hinic_link_info *info)
+{
+       struct hi30_ffe_data *ffe_data;
+       struct hi30_ctle_data *ctle_data;
+
+       ffe_data = (struct hi30_ffe_data *)info->hi30_ffe;
+       ctle_data = (struct hi30_ctle_data *)info->hi30_ctle;
+
+       PMD_DRV_LOG(INFO, "TX_FFE: PRE2=%s%d; PRE1=%s%d; MAIN=%d; POST1=%s%d; 
POST1X=%s%d",
+                (ffe_data->PRE1 & 0x10) ? "-" : "",
+                (int)(ffe_data->PRE1 & 0xf),
+                (ffe_data->PRE2 & 0x10) ? "-" : "",
+                (int)(ffe_data->PRE2 & 0xf),
+                (int)ffe_data->MAIN,
+                (ffe_data->POST1 & 0x10) ? "-" : "",
+                (int)(ffe_data->POST1 & 0xf),
+                (ffe_data->POST2 & 0x10) ? "-" : "",
+                (int)(ffe_data->POST2 & 0xf));
+       PMD_DRV_LOG(INFO, "RX_CTLE: Gain1~3=%u %u %u; Boost1~3=%u %u %u; 
Zero1~3=%u %u %u; Squelch1~3=%u %u %u",
+                ctle_data->ctlebst[0], ctle_data->ctlebst[1],
+                ctle_data->ctlebst[2], ctle_data->ctlecmband[0],
+                ctle_data->ctlecmband[1], ctle_data->ctlecmband[2],
+                ctle_data->ctlermband[0], ctle_data->ctlermband[1],
+                ctle_data->ctlermband[2], ctle_data->ctleza[0],
+                ctle_data->ctleza[1], ctle_data->ctleza[2]);
+}
+
+static void print_link_info(struct hinic_hwdev *hwdev,
+                           struct hinic_link_info *info,
+                           enum hilink_info_print_event type)
+{
+       const char *fec = "None";
+
+       if (info->fec < HILINK_FEC_MAX_TYPE)
+               fec = __hw_to_char_fec[info->fec];
+       else
+               PMD_DRV_LOG(INFO, "Unknown fec type: %u",
+                        info->fec);
+
+       if (type == HILINK_EVENT_LINK_UP || !info->an_state) {
+               PMD_DRV_LOG(INFO, "Link information: speed %dGbps, %s, autoneg 
%s",
+                        info->speed, fec, info->an_state ? "on" : "off");
+       } else {
+               PMD_DRV_LOG(INFO, "Link information: antoneg: %s",
+                        info->an_state ? "on" : "off");
+       }
+}
+
+static const char *hilink_info_report_type[HILINK_EVENT_MAX_TYPE] = {
+       "", "link up", "link down", "cable plugged"
+};
+
+static void hinic_print_hilink_info(struct hinic_hwdev *hwdev, void *buf_in,
+                                   u16 in_size, void *buf_out, u16 *out_size)
+{
+       struct hinic_hilink_link_info *hilink_info =
+               (struct hinic_hilink_link_info *)buf_in;
+       struct hinic_link_info *info;
+       enum hilink_info_print_event type;
+
+       if (in_size != sizeof(*hilink_info)) {
+               PMD_DRV_LOG(ERR, "Invalid hilink info message size %d, should 
be %ld",
+                       in_size, sizeof(*hilink_info));
+               return;
+       }
+
+       ((struct hinic_hilink_link_info *)buf_out)->mgmt_msg_head.status = 0;
+       *out_size = sizeof(*hilink_info);
+
+       info = &hilink_info->info;
+       type = hilink_info->info_type;
+
+       if (type < HILINK_EVENT_LINK_UP || type >= HILINK_EVENT_MAX_TYPE) {
+               PMD_DRV_LOG(INFO, "Invalid hilink info report, type: %d",
+                        type);
+               return;
+       }
+
+       PMD_DRV_LOG(INFO, "Hilink info report after %s",
+                hilink_info_report_type[type]);
+
+       print_cable_info(hwdev, info);
+
+       print_link_info(hwdev, info, type);
+
+       print_hi30_status(hwdev, info);
+
+       if (type == HILINK_EVENT_LINK_UP)
+               return;
+
+       if (type == HILINK_EVENT_CABLE_PLUGGED) {
+               PMD_DRV_LOG(INFO, "alos: %u, rx_los: %u",
+                        info->alos, info->rx_los);
+               return;
+       }
+
+       PMD_DRV_LOG(INFO, "PMA ctrl: %s, MAC tx %s, MAC rx %s, PMA debug 
inforeg: 0x%x, PMA signal ok reg: 0x%x, RF/LF status reg: 0x%x",
+                info->pma_status ? "on" : "off",
+                info->mac_tx_en ? "enable" : "disable",
+                info->mac_rx_en ? "enable" : "disable", info->pma_dbg_info_reg,
+                info->pma_signal_ok_reg, info->rf_lf_status_reg);
+       PMD_DRV_LOG(INFO, "alos: %u, rx_los: %u, PCS block counter reg: 
0x%x,PCS link: 0x%x, MAC link: 0x%x PCS_err_cnt: 0x%x",
+                info->alos, info->rx_los, info->pcs_err_blk_cnt_reg,
+                info->pcs_link_reg, info->mac_link_reg, info->pcs_err_cnt);
+}
+
+void hinic_hilink_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
+                                    void *buf_in, u16 in_size,
+                                    void *buf_out, u16 *out_size)
+{
+       if (!hwdev)
+               return;
+
+       *out_size = 0;
+
+       switch (cmd) {
+       case HINIC_HILINK_CMD_GET_LINK_INFO:
+               hinic_print_hilink_info(hwdev, buf_in, in_size, buf_out,
+                                       out_size);
+               break;
+
+       default:
+               PMD_DRV_LOG(ERR, "Unsupported event %d to process",
+                       cmd);
+               break;
+       }
+}
+
+/**
+ * hinic_convert_rx_buf_size - convert rx buffer size to hw size
+ * @rx_buf_sz: receive buffer size of mbuf
+ * @match_sz: receive buffer size of hardware
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ **/
+int hinic_convert_rx_buf_size(u32 rx_buf_sz, u32 *match_sz)
+{
+       u32 i, num_hw_types, best_match_sz;
+
+       if (unlikely(!match_sz || rx_buf_sz < HINIC_RX_BUF_SIZE_32B))
+               return -EINVAL;
+
+       if (rx_buf_sz >= HINIC_RX_BUF_SIZE_16K) {
+               best_match_sz =  HINIC_RX_BUF_SIZE_16K;
+               goto size_matched;
+       }
+
+       num_hw_types = sizeof(hinic_hw_rx_buf_size) /
+               sizeof(hinic_hw_rx_buf_size[0]);
+       best_match_sz = hinic_hw_rx_buf_size[0];
+       for (i = 0; i < num_hw_types; i++) {
+               if (rx_buf_sz == hinic_hw_rx_buf_size[i]) {
+                       best_match_sz = hinic_hw_rx_buf_size[i];
+                       break;
+               } else if (rx_buf_sz < hinic_hw_rx_buf_size[i]) {
+                       break;
+               }
+               best_match_sz = hinic_hw_rx_buf_size[i];
+       }
+
+size_matched:
+       *match_sz = best_match_sz;
+
+       return 0;
+}
diff --git a/drivers/net/hinic/base/hinic_pmd_hwdev.h 
b/drivers/net/hinic/base/hinic_pmd_hwdev.h
new file mode 100644
index 000000000..b1c667934
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_hwdev.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC_PMD_HWDEV_H_
+#define _HINIC_PMD_HWDEV_H_
+
+#define HINIC_PAGE_SIZE_MAX    20
+#define HINIC_PAGE_SIZE_DPDK   6
+
+#define HINIC_PCIE_LINK_DOWN           0xFFFFFFFF
+
+#define HINIC_DEV_ACTIVE_FW_TIMEOUT    (35 * 1000)
+#define HINIC_DEV_BUSY_ACTIVE_FW       0xFE
+
+struct hinic_page_addr {
+       void *virt_addr;
+       u64 phys_addr;
+};
+
+struct nic_interrupt_info {
+       u32 lli_set;
+       u32 interrupt_coalesc_set;
+       u16 msix_index;
+       u8 lli_credit_limit;
+       u8 lli_timer_cfg;
+       u8 pending_limt;
+       u8 coalesc_timer_cfg;
+       u8 resend_timer_cfg;
+};
+
+struct hinic_sq_attr {
+       u8 dma_attr_off;
+       u8 pending_limit;
+       u8 coalescing_time;
+       u8 intr_en;
+       u16 intr_idx;
+       u32 l2nic_sqn;
+       /* bit[63:2] is addr's high 62bit, bit[0] is valid flag */
+       u64 ci_dma_base;
+};
+
+struct hinic_board_info {
+       u32     board_type;
+       u32     port_num;
+       u32     port_speed;
+       u32     pcie_width;
+       u32     host_num;
+       u32     pf_num;
+       u32     vf_total_num;
+       u32     tile_num;
+       u32     qcm_num;
+       u32     core_num;
+       u32     work_mode;
+       u32     service_mode;
+       u32     pcie_mode;
+       u32     cfg_addr;
+       u32     boot_sel;
+};
+
+/* defined by chip */
+enum hinic_fault_type {
+       FAULT_TYPE_CHIP,
+       FAULT_TYPE_UCODE,
+       FAULT_TYPE_MEM_RD_TIMEOUT,
+       FAULT_TYPE_MEM_WR_TIMEOUT,
+       FAULT_TYPE_REG_RD_TIMEOUT,
+       FAULT_TYPE_REG_WR_TIMEOUT,
+       FAULT_TYPE_MAX,
+};
+
+/* defined by chip */
+enum hinic_fault_err_level {
+       /* default err_level=FAULT_LEVEL_FATAL if
+        * type==FAULT_TYPE_MEM_RD_TIMEOUT || FAULT_TYPE_MEM_WR_TIMEOUT ||
+        *       FAULT_TYPE_REG_RD_TIMEOUT || FAULT_TYPE_REG_WR_TIMEOUT ||
+        *       FAULT_TYPE_UCODE
+        * other: err_level in event.chip.err_level if type==FAULT_TYPE_CHIP
+        */
+       FAULT_LEVEL_FATAL,
+       FAULT_LEVEL_SERIOUS_RESET,
+       FAULT_LEVEL_SERIOUS_FLR,
+       FAULT_LEVEL_GENERAL,
+       FAULT_LEVEL_SUGGESTION,
+       FAULT_LEVEL_MAX
+};
+
+/* defined by chip */
+struct hinic_fault_event {
+       /* enum hinic_fault_type */
+       u8 type;
+       u8 rsvd0[3];
+       union {
+               u32 val[4];
+               /* valid only type==FAULT_TYPE_CHIP */
+               struct {
+                       u8 node_id;
+                       /* enum hinic_fault_err_level */
+                       u8 err_level;
+                       u8 err_type;
+                       u8 rsvd1;
+                       u32 err_csr_addr;
+                       u32 err_csr_value;
+               /* func_id valid only err_level==FAULT_LEVEL_SERIOUS_FLR */
+                       u16 func_id;
+                       u16 rsvd2;
+               } chip;
+
+               /* valid only type==FAULT_TYPE_UCODE */
+               struct {
+                       u8 cause_id;
+                       u8 core_id;
+                       u8 c_id;
+                       u8 rsvd3;
+                       u32 epc;
+                       u32 rsvd4;
+                       u32 rsvd5;
+               } ucode;
+
+               /* valid only type==FAULT_TYPE_MEM_RD_TIMEOUT ||
+                *              FAULT_TYPE_MEM_WR_TIMEOUT
+                */
+               struct {
+                       u32 err_csr_ctrl;
+                       u32 err_csr_data;
+                       u32 ctrl_tab;
+                       u32 mem_index;
+               } mem_timeout;
+
+               /* valid only type==FAULT_TYPE_REG_RD_TIMEOUT ||
+                *                  FAULT_TYPE_REG_WR_TIMEOUT
+                */
+               struct {
+                       u32 err_csr;
+                       u32 rsvd6;
+                       u32 rsvd7;
+                       u32 rsvd8;
+               } reg_timeout;
+       } event;
+};
+
+struct hinic_hwdev {
+       struct rte_pci_device *pcidev_hdl;
+       void *dev_hdl;
+
+       struct hinic_hwif *hwif;
+
+       struct hinic_nic_io *nic_io;
+       struct cfg_mgmt_info *cfg_mgmt;
+
+       struct hinic_aeqs *aeqs;
+
+       struct hinic_mbox_func_to_func *func_to_func;
+
+       struct hinic_msg_pf_to_mgmt *pf_to_mgmt;
+
+       struct hinic_cmdqs *cmdqs;
+
+       struct hinic_page_addr page_pa0;
+       struct hinic_page_addr page_pa1;
+};
+
+int hinic_get_board_info(void *hwdev, struct hinic_board_info *info);
+
+int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr);
+
+int hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int 
rx_buf_sz);
+int hinic_clean_root_ctxt(void *hwdev);
+
+int hinic_func_rx_tx_flush(struct hinic_hwdev *hwdev);
+
+int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
+                           struct nic_interrupt_info interrupt_info);
+
+void hinic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx,
+                                     u8 clear_resend_en);
+
+int init_aeqs_msix_attr(void *hwdev);
+
+int hinic_msg_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);
+
+void hinic_comm_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
+                                  void *buf_in, u16 in_size,
+                                  void *buf_out, u16 *out_size);
+
+void hinic_l2nic_async_event_handle(struct hinic_hwdev *hwdev, void *param,
+                                   u8 cmd, void *buf_in, u16 in_size,
+                                   void *buf_out, u16 *out_size);
+
+void hinic_hilink_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
+                                    void *buf_in, u16 in_size, void *buf_out,
+                                    u16 *out_size);
+
+int hinic_init_attr_table(struct hinic_hwdev *hwdev);
+
+int hinic_activate_hwdev_state(struct hinic_hwdev *hwdev);
+void hinic_deactivate_hwdev_state(struct hinic_hwdev *hwdev);
+
+int hinic_l2nic_reset(struct hinic_hwdev *hwdev);
+
+int hinic_convert_rx_buf_size(u32 rx_buf_sz, u32 *match_sz);
+
+#endif /* _HINIC_PMD_HWDEV_H_ */
diff --git a/drivers/net/hinic/base/hinic_pmd_hwif.c 
b/drivers/net/hinic/base/hinic_pmd_hwif.c
new file mode 100644
index 000000000..0979871b4
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_hwif.c
@@ -0,0 +1,542 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include "hinic_pmd_dpdev.h"
+
+#define HINIC_CFG_REGS_BAR     0
+#define HINIC_INTR_MSI_BAR     2
+#define HINIC_DB_MEM_BAR       4
+#define HINIC_ASSERT_ON                1
+
+static inline void __iomem *
+io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
+{
+       /* io_mapping only for compile using hinic kernel, dwqe not support */
+       u32 hinic_assert = HINIC_ASSERT_ON;
+
+       HINIC_BUG_ON(hinic_assert);
+
+       return ((char __force __iomem *)mapping) + offset;
+}
+
+static inline void
+io_mapping_unmap(void __iomem *vaddr)
+{
+       /* io_mapping only for compile using hinic kernel, dwqe not support */
+       u32 hinic_assert = HINIC_ASSERT_ON;
+       HINIC_BUG_ON(hinic_assert);
+
+       *((u32 *)vaddr) = 0;
+}
+
+/**
+ * hwif_ready - test if the HW initialization passed
+ * @hwdev: the pointer to the private hardware device object
+ * Return: 0 - success, negative - failure
+ **/
+static int hwif_ready(struct hinic_hwdev *hwdev)
+{
+       u32 addr, attr1;
+
+       addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
+       attr1  = hinic_hwif_read_reg(hwdev->hwif, addr);
+
+       if (!HINIC_AF1_GET(attr1, MGMT_INIT_STATUS))
+               return -EBUSY;
+
+       return 0;
+}
+
+/**
+ * set_hwif_attr - set the attributes as members in hwif
+ * @hwif: the hardware interface of a pci function device
+ * @attr0: the first attribute that was read from the hw
+ * @attr1: the second attribute that was read from the hw
+ * @attr2: the third attribute that was read from the hw
+ **/
+static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1,
+                         u32 attr2)
+{
+       hwif->attr.func_global_idx = HINIC_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+       hwif->attr.port_to_port_idx = HINIC_AF0_GET(attr0, P2P_IDX);
+       hwif->attr.pci_intf_idx = HINIC_AF0_GET(attr0, PCI_INTF_IDX);
+       hwif->attr.vf_in_pf = HINIC_AF0_GET(attr0, VF_IN_PF);
+       hwif->attr.func_type = HINIC_AF0_GET(attr0, FUNC_TYPE);
+
+       hwif->attr.ppf_idx = HINIC_AF1_GET(attr1, PPF_IDX);
+
+       hwif->attr.num_aeqs = BIT(HINIC_AF1_GET(attr1, AEQS_PER_FUNC));
+       hwif->attr.num_ceqs = BIT(HINIC_AF1_GET(attr1, CEQS_PER_FUNC));
+       hwif->attr.num_irqs = BIT(HINIC_AF1_GET(attr1, IRQS_PER_FUNC));
+       hwif->attr.num_dma_attr = BIT(HINIC_AF1_GET(attr1, DMA_ATTR_PER_FUNC));
+
+       hwif->attr.global_vf_id_of_pf = HINIC_AF2_GET(attr2,
+                                                     GLOBAL_VF_ID_OF_PF);
+}
+
+/**
+ * get_hwif_attr - read and set the attributes as members in hwif
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void get_hwif_attr(struct hinic_hwif *hwif)
+{
+       u32 addr, attr0, attr1, attr2;
+
+       addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
+       attr0  = hinic_hwif_read_reg(hwif, addr);
+
+       addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
+       attr1  = hinic_hwif_read_reg(hwif, addr);
+
+       addr   = HINIC_CSR_FUNC_ATTR2_ADDR;
+       attr2  = hinic_hwif_read_reg(hwif, addr);
+
+       set_hwif_attr(hwif, attr0, attr1, attr2);
+}
+
+void hinic_set_pf_status(struct hinic_hwif *hwif, enum hinic_pf_status status)
+{
+       u32 attr5 = HINIC_AF5_SET(status, PF_STATUS);
+       u32 addr  = HINIC_CSR_FUNC_ATTR5_ADDR;
+
+       hinic_hwif_write_reg(hwif, addr, attr5);
+}
+
+enum hinic_pf_status hinic_get_pf_status(struct hinic_hwif *hwif)
+{
+       u32 attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR);
+
+       return HINIC_AF5_GET(attr5, PF_STATUS);
+}
+
+static enum hinic_doorbell_ctrl
+hinic_get_doorbell_ctrl_status(struct hinic_hwif *hwif)
+{
+       u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
+
+       return HINIC_AF4_GET(attr4, DOORBELL_CTRL);
+}
+
+static enum hinic_outbound_ctrl
+hinic_get_outbound_ctrl_status(struct hinic_hwif *hwif)
+{
+       u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
+
+       return HINIC_AF4_GET(attr4, OUTBOUND_CTRL);
+}
+
+void hinic_enable_doorbell(struct hinic_hwif *hwif)
+{
+       u32 addr, attr4;
+
+       addr = HINIC_CSR_FUNC_ATTR4_ADDR;
+       attr4 = hinic_hwif_read_reg(hwif, addr);
+
+       attr4 = HINIC_AF4_CLEAR(attr4, DOORBELL_CTRL);
+       attr4 |= HINIC_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL);
+
+       hinic_hwif_write_reg(hwif, addr, attr4);
+}
+
+void hinic_disable_doorbell(struct hinic_hwif *hwif)
+{
+       u32 addr, attr4;
+
+       addr = HINIC_CSR_FUNC_ATTR4_ADDR;
+       attr4 = hinic_hwif_read_reg(hwif, addr);
+
+       attr4 = HINIC_AF4_CLEAR(attr4, DOORBELL_CTRL);
+       attr4 |= HINIC_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL);
+
+       hinic_hwif_write_reg(hwif, addr, attr4);
+}
+
+/**
+ * set_ppf - try to set hwif as ppf and set the type of hwif in this case
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void set_ppf(struct hinic_hwif *hwif)
+{
+       struct hinic_func_attr *attr = &hwif->attr;
+       u32 addr, val, ppf_election;
+
+       /* Read Modify Write */
+       addr  = HINIC_CSR_PPF_ELECTION_ADDR;
+
+       val = hinic_hwif_read_reg(hwif, addr);
+       val = HINIC_PPF_ELECTION_CLEAR(val, IDX);
+
+       ppf_election =  HINIC_PPF_ELECTION_SET(attr->func_global_idx, IDX);
+       val |= ppf_election;
+
+       hinic_hwif_write_reg(hwif, addr, val);
+
+       /* Check PPF */
+       val = hinic_hwif_read_reg(hwif, addr);
+
+       attr->ppf_idx = HINIC_PPF_ELECTION_GET(val, IDX);
+       if (attr->ppf_idx == attr->func_global_idx)
+               attr->func_type = TYPE_PPF;
+}
+
+/**
+ * get_mpf - get the mpf index into the hwif
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void get_mpf(struct hinic_hwif *hwif)
+{
+       struct hinic_func_attr *attr = &hwif->attr;
+       u32 mpf_election, addr;
+
+       addr = HINIC_CSR_GLOBAL_MPF_ELECTION_ADDR;
+
+       mpf_election = hinic_hwif_read_reg(hwif, addr);
+       attr->mpf_idx = HINIC_MPF_ELECTION_GET(mpf_election, IDX);
+}
+
+/**
+ * set_mpf - try to set hwif as mpf and set the mpf idx in hwif
+ * @hwif: the hardware interface of a pci function device
+ **/
+static void set_mpf(struct hinic_hwif *hwif)
+{
+       struct hinic_func_attr *attr = &hwif->attr;
+       u32 addr, val, mpf_election;
+
+       /* Read Modify Write */
+       addr  = HINIC_CSR_GLOBAL_MPF_ELECTION_ADDR;
+
+       val = hinic_hwif_read_reg(hwif, addr);
+
+       val = HINIC_MPF_ELECTION_CLEAR(val, IDX);
+       mpf_election = HINIC_MPF_ELECTION_SET(attr->func_global_idx, IDX);
+
+       val |= mpf_election;
+       hinic_hwif_write_reg(hwif, addr, val);
+
+       get_mpf(hwif);
+}
+
+static void init_db_area_idx(struct hinic_free_db_area *free_db_area)
+{
+       u32 i;
+
+       for (i = 0; i < HINIC_DB_MAX_AREAS; i++)
+               free_db_area->db_idx[i] = i;
+
+       free_db_area->alloc_pos = 0;
+       free_db_area->return_pos = 0;
+
+       free_db_area->num_free = HINIC_DB_MAX_AREAS;
+
+       spin_lock_init(&free_db_area->idx_lock);
+}
+
+static int get_db_idx(struct hinic_hwif *hwif, u32 *idx)
+{
+       struct hinic_free_db_area *free_db_area = &hwif->free_db_area;
+       u32 pos;
+       u32 pg_idx;
+
+       spin_lock(&free_db_area->idx_lock);
+
+       if (free_db_area->num_free == 0) {
+               spin_unlock(&free_db_area->idx_lock);
+               return -ENOMEM;
+       }
+
+       free_db_area->num_free--;
+
+       pos = free_db_area->alloc_pos++;
+       pos &= HINIC_DB_MAX_AREAS - 1;
+
+       pg_idx = free_db_area->db_idx[pos];
+
+       free_db_area->db_idx[pos] = 0xFFFFFFFF;
+
+       spin_unlock(&free_db_area->idx_lock);
+
+       *idx = pg_idx;
+
+       return 0;
+}
+
+static void free_db_idx(struct hinic_hwif *hwif, u32 idx)
+{
+       struct hinic_free_db_area *free_db_area = &hwif->free_db_area;
+       u32 pos;
+
+       spin_lock(&free_db_area->idx_lock);
+
+       pos = free_db_area->return_pos++;
+       pos &= HINIC_DB_MAX_AREAS - 1;
+
+       free_db_area->db_idx[pos] = idx;
+
+       free_db_area->num_free++;
+
+       spin_unlock(&free_db_area->idx_lock);
+}
+
+void hinic_free_db_addr(void *hwdev, void __iomem *db_base,
+                       void __iomem *dwqe_base)
+{
+       struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+       u32 idx = DB_IDX(db_base, hwif->db_base);
+
+       if (dwqe_base)
+               io_mapping_unmap(dwqe_base);
+
+       free_db_idx(hwif, idx);
+}
+
+int hinic_alloc_db_addr(void *hwdev, void __iomem **db_base,
+                       void __iomem **dwqe_base)
+{
+       struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+       u64 offset;
+       u32 idx;
+       int err;
+
+       err = get_db_idx(hwif, &idx);
+       if (err)
+               return -EFAULT;
+
+       *db_base = hwif->db_base + idx * HINIC_DB_PAGE_SIZE;
+
+       if (!dwqe_base)
+               return 0;
+
+       offset = ((u64)idx) << PAGE_SHIFT;
+       *dwqe_base = io_mapping_map_wc(hwif->dwqe_mapping, offset);
+       if (!(*dwqe_base)) {
+               hinic_free_db_addr(hwdev, *db_base, NULL);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+void hinic_set_msix_state(void *hwdev, u16 msix_idx, enum hinic_msix_state 
flag)
+{
+       struct hinic_hwdev *hw = (struct hinic_hwdev *)hwdev;
+       struct hinic_hwif *hwif = hw->hwif;
+       u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE
+               + HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL;
+       u32 mask_bits;
+
+       /* vfio-pci does not mmap msi-x vector table to user space,
+        * we can not access the space when kernel driver is vfio-pci
+        */
+       if (hw->pcidev_hdl->kdrv == RTE_KDRV_VFIO)
+               return;
+
+       mask_bits = readl(hwif->intr_regs_base + offset);
+       mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
+       if (flag)
+               mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
+
+       writel(mask_bits, hwif->intr_regs_base + offset);
+}
+
+static void disable_all_msix(struct hinic_hwdev *hwdev)
+{
+       u16 num_irqs = hwdev->hwif->attr.num_irqs;
+       u16 i;
+
+       for (i = 0; i < num_irqs; i++)
+               hinic_set_msix_state(hwdev, i, HINIC_MSIX_DISABLE);
+}
+
+static int wait_until_doorbell_and_outbound_enabled(struct hinic_hwif *hwif)
+{
+       unsigned long end;
+       enum hinic_doorbell_ctrl db_ctrl;
+       enum hinic_outbound_ctrl outbound_ctrl;
+
+       end = jiffies +
+               msecs_to_jiffies(HINIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT);
+       do {
+               db_ctrl = hinic_get_doorbell_ctrl_status(hwif);
+               outbound_ctrl = hinic_get_outbound_ctrl_status(hwif);
+
+               if (outbound_ctrl == ENABLE_OUTBOUND &&
+                   db_ctrl == ENABLE_DOORBELL)
+                       return 0;
+
+               rte_delay_ms(1);
+       } while (time_before(jiffies, end));
+
+       return -EFAULT;
+}
+
+u16 hinic_global_func_id(void *hwdev)
+{
+       struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.func_global_idx;
+}
+
+enum func_type hinic_func_type(void *hwdev)
+{
+       struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.func_type;
+}
+
+u8 hinic_ppf_idx(void *hwdev)
+{
+       struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.ppf_idx;
+}
+
+/**
+ * hinic_init_hwif - initialize the hw interface
+ * @hwdev: the pointer to the private hardware device object
+ * @cfg_reg_base: base physical address of configuration registers
+ * @intr_reg_base: base physical address of msi-x vector table
+ * @db_base_phy: base physical address of doorbell registers
+ * @db_base: base virtual address of doorbell registers
+ * @dwqe_mapping: direct wqe io mapping address
+ * Return: 0 - success, negative - failure
+ **/
+int hinic_init_hwif(struct hinic_hwdev *hwdev, void *cfg_reg_base,
+                   void *intr_reg_base, u64 db_base_phy,
+                   void *db_base, void *dwqe_mapping)
+{
+       struct hinic_hwif *hwif;
+       int err;
+
+       hwif = hwdev->hwif;
+
+       hwif->cfg_regs_base = (u8 __iomem *)cfg_reg_base;
+       hwif->intr_regs_base = (u8 __iomem *)intr_reg_base;
+
+       hwif->db_base_phy = db_base_phy;
+       hwif->db_base = (u8 __iomem *)db_base;
+       hwif->dwqe_mapping = (struct io_mapping *)dwqe_mapping;
+       init_db_area_idx(&hwif->free_db_area);
+
+       get_hwif_attr(hwif);
+
+       err = hwif_ready(hwdev);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Hwif is not ready");
+               goto hwif_ready_err;
+       }
+
+       err = wait_until_doorbell_and_outbound_enabled(hwif);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Hw doorbell/outbound is disabled");
+               goto hwif_ready_err;
+       }
+
+       if (!HINIC_IS_VF(hwdev)) {
+               set_ppf(hwif);
+
+               if (HINIC_IS_PPF(hwdev))
+                       set_mpf(hwif);
+
+               get_mpf(hwif);
+       }
+
+       return 0;
+
+hwif_ready_err:
+       spin_lock_deinit(&hwif->free_db_area.idx_lock);
+
+       return err;
+}
+
+#define HINIC_HWIF_ATTR_REG_PRINT_NUM        (6)
+#define HINIC_HWIF_APICMD_REG_PRINT_NUM      (2)
+#define HINIC_HWIF_EQ_REG_PRINT_NUM          (2)
+
+static void hinic_parse_hwif_attr(struct hinic_nic_dev *nic_dev)
+{
+       struct hinic_hwif *hwif;
+
+       if (!nic_dev->hwdev || !nic_dev->hwdev->hwif) {
+               PMD_DRV_LOG(ERR, "Hwif not initialized");
+               return;
+       }
+
+       hwif = nic_dev->hwdev->hwif;
+       PMD_DRV_LOG(INFO, "Device %s hwif attribute:", nic_dev->proc_dev_name);
+       PMD_DRV_LOG(INFO, "func_idx:%u, p2p_idx:%u, pciintf_idx:%u, "
+                   "vf_in_pf:%u, ppf_idx:%u, global_vf_id:%u, func_type:%u",
+                   hwif->attr.func_global_idx,
+                   hwif->attr.port_to_port_idx, hwif->attr.pci_intf_idx,
+                   hwif->attr.vf_in_pf, hwif->attr.ppf_idx,
+                   hwif->attr.global_vf_id_of_pf, hwif->attr.func_type);
+       PMD_DRV_LOG(INFO, "num_aeqs:%u, num_ceqs:%u, num_irqs:%u, dma_attr:%u",
+                   hwif->attr.num_aeqs, hwif->attr.num_ceqs,
+                   hwif->attr.num_irqs, hwif->attr.num_dma_attr);
+}
+
+static void hinic_get_mmio(struct hinic_nic_dev *nic_dev, void **cfg_regs_base,
+                         void **intr_base, void **db_base)
+{
+       struct rte_pci_device *pci_dev = nic_dev->hwdev->pcidev_hdl;
+
+       *cfg_regs_base = pci_dev->mem_resource[HINIC_CFG_REGS_BAR].addr;
+       *intr_base = pci_dev->mem_resource[HINIC_INTR_MSI_BAR].addr;
+       *db_base = pci_dev->mem_resource[HINIC_DB_MEM_BAR].addr;
+}
+
+void hinic_hwif_res_free(struct hinic_nic_dev *nic_dev)
+{
+       rte_free(nic_dev->hwdev->hwif);
+       nic_dev->hwdev->hwif = NULL;
+}
+
+int hinic_hwif_res_init(struct hinic_nic_dev *nic_dev)
+{
+       int err = HINIC_ERROR;
+       void *cfg_regs_base, *db_base, *intr_base = NULL;
+       struct hinic_hwdev *hwdev = nic_dev->hwdev;
+
+       /* hinic related init */
+       hwdev->hwif = (struct hinic_hwif *)rte_zmalloc("hinic_hwif",
+                       sizeof(*hwdev->hwif), RTE_CACHE_LINE_SIZE);
+       if (!hwdev->hwif) {
+               PMD_DRV_LOG(ERR, "Allocate hwif failed, dev_name: %s",
+                           nic_dev->proc_dev_name);
+               return -ENOMEM;
+       }
+
+       hinic_get_mmio(nic_dev, &cfg_regs_base, &intr_base, &db_base);
+
+       err = hinic_init_hwif(hwdev, cfg_regs_base,
+                             intr_base, 0, db_base, NULL);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Initialize hwif failed, dev_name: %s",
+                           nic_dev->proc_dev_name);
+               goto init_hwif_err;
+       }
+
+       /* disable msix interrupt in hw device */
+       disable_all_msix(hwdev);
+
+       /* print hwif attributes */
+       hinic_parse_hwif_attr(nic_dev);
+
+       return HINIC_OK;
+
+init_hwif_err:
+       rte_free(nic_dev->hwdev->hwif);
+       nic_dev->hwdev->hwif = NULL;
+
+       return err;
+}
diff --git a/drivers/net/hinic/base/hinic_pmd_hwif.h 
b/drivers/net/hinic/base/hinic_pmd_hwif.h
new file mode 100644
index 000000000..66295754d
--- /dev/null
+++ b/drivers/net/hinic/base/hinic_pmd_hwif.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC_PMD_HWIF_H_
+#define _HINIC_PMD_HWIF_H_
+
+#define HINIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT       30000
+
+struct io_mapping;
+struct hinic_hwdev;
+
+struct hinic_free_db_area {
+       u32             db_idx[HINIC_DB_MAX_AREAS];
+
+       u32             num_free;
+
+       u32             alloc_pos;
+       u32             return_pos;
+       /* spinlock for idx */
+       spinlock_t      idx_lock;
+};
+
+struct hinic_func_attr {
+       u16                     func_global_idx;
+       u8                      port_to_port_idx;
+       u8                      pci_intf_idx;
+       u8                      vf_in_pf;
+       enum func_type          func_type;
+
+       u8                      mpf_idx;
+
+       u8                      ppf_idx;
+
+       u16                     num_irqs;               /* max: 2 ^ 15 */
+       u8                      num_aeqs;               /* max: 2 ^ 3 */
+       u8                      num_ceqs;               /* max: 2 ^ 7 */
+
+       u8                      num_dma_attr;           /* max: 2 ^ 6 */
+
+       u16                     global_vf_id_of_pf;
+};
+
+struct hinic_hwif {
+       u8 __iomem                      *cfg_regs_base;
+       u8 __iomem                      *intr_regs_base;
+       u64                             db_base_phy;
+       u8 __iomem                      *db_base;
+       struct io_mapping               *dwqe_mapping;
+
+       struct hinic_free_db_area       free_db_area;
+
+       struct hinic_func_attr          attr;
+};
+
+static inline u32 hinic_hwif_read_reg(struct hinic_hwif *hwif, u32 reg)
+{
+       return be32_to_cpu(readl(hwif->cfg_regs_base + reg));
+}
+
+static inline void hinic_hwif_write_reg(struct hinic_hwif *hwif, u32 reg,
+                                       u32 val)
+{
+       writel(cpu_to_be32(val), hwif->cfg_regs_base + reg);
+}
+
+void hinic_set_pf_status(struct hinic_hwif *hwif, enum hinic_pf_status status);
+
+enum hinic_pf_status hinic_get_pf_status(struct hinic_hwif *hwif);
+
+void hinic_enable_doorbell(struct hinic_hwif *hwif);
+
+void hinic_disable_doorbell(struct hinic_hwif *hwif);
+
+int hinic_alloc_db_addr(void *hwdev, void __iomem **db_base,
+                       void __iomem **dwqe_base);
+
+void hinic_free_db_addr(void *hwdev, void __iomem *db_base,
+                       void __iomem *dwqe_base);
+
+void hinic_set_msix_state(void *hwdev, u16 msix_idx,
+                         enum hinic_msix_state flag);
+
+u8 hinic_ppf_idx(void *hwdev);
+
+int hinic_init_hwif(struct hinic_hwdev *hwdev, void *cfg_reg_base,
+                   void *intr_reg_base, u64 db_base_phy,
+                   void *db_base, void *dwqe_mapping);
+
+#endif /* _HINIC_PMD_HWIF_H_ */
-- 
2.18.0

Reply via email to