Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1699129 > unrolled thread

[PATCH V5 net-next 0/8] Hisilicon Network Subsystem 3 Ethernet Driver

Started bySalil Mehta <salil.mehta@huawei.com>
First post2017-07-29 00:30 +0200
Last post2017-07-29 00:40 +0200
Articles 12 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH V5 net-next 0/8] Hisilicon Network Subsystem 3 Ethernet Driver Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 00:30 +0200
    [PATCH V5 net-next 5/8] net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 00:30 +0200
    [PATCH V5 net-next 8/8] net: hns3: Add HNS3 driver to kernel build framework & MAINTAINERS Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 00:30 +0200
    [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 00:30 +0200
      Re: [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3  framework Leon Romanovsky <leon@kernel.org> - 2017-07-30 12:00 +0200
        RE: [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3  framework Salil Mehta <salil.mehta@huawei.com> - 2017-07-31 11:10 +0200
    [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 00:30 +0200
      Re: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3  Ethernet driver for hip08 SoC Andrew Lunn <andrew@lunn.ch> - 2017-07-29 01:30 +0200
        RE: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3  Ethernet driver for hip08 SoC Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 02:00 +0200
      Re: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3  Ethernet driver for hip08 SoC Andrew Lunn <andrew@lunn.ch> - 2017-07-29 01:30 +0200
        RE: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3  Ethernet driver for hip08 SoC Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 02:00 +0200
    [PATCH V5 net-next 3/8] net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support Salil Mehta <salil.mehta@huawei.com> - 2017-07-29 00:40 +0200

#1699129 — [PATCH V5 net-next 0/8] Hisilicon Network Subsystem 3 Ethernet Driver

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 00:30 +0200
Subject[PATCH V5 net-next 0/8] Hisilicon Network Subsystem 3 Ethernet Driver
Message-ID<u8lVD-1pM-3@gated-at.bofh.it>
This patch-set contains the support of the HNS3 (Hisilicon Network Subsystem 3)
Ethernet driver for hip08 family of SoCs and future upcoming SoCs.

Hisilicon's new hip08 SoCs have integrated ethernet based on PCI Express and
hence there was a need of new driver over the previous HNS driver which is 
already part of the Linux mainline. This new driver is NOT backward
compatible with HNS.

This current driver is meant to control the Physical Function and there would
soon be a support of a separate driver for Virtual Function once this base PF
driver has been accepted. Also, this driver is the ongoing development work and
HNS3 Ethernet driver would be incrementally enhanced with more new features.

High Level Architecture:

        [ Ethtool ]
	   ^  |
           |  | 
     [Ethernet Client]  [ODP/UIO Client] . . . [ RoCE Client ]     
                         |                            |
                   [ HNAE Device ]                    |
                         |                            |
    ---------------------------------------------     |
                         |                            |
     [ HNAE3 Framework (Register/unregister) ]        |
                         |                            |
    ---------------------------------------------     |
                         |                            |
                   [ HCLGE Layer]                     |
         ________________|_________________           |
        |                |                 |          |
    [ MDIO ]    [ Scheduler/Shaper ]  [ Debugfs* ]    |
        |                |                 |          |
        |________________|_________________|          |     
                         |                            |
             [ IMP command Interface ]                |
    ---------------------------------------------     |
              HIP08  H A R D W A R E                  *


Current patch-set broadly adds the support of the following PF functionality:
 1. Basic Rx and Tx functionality 
 2. TSO support
 3. Ethtool support
 4. * Debugfs support -> this patch for now has been taken off.
 5. HNAE framework and hardware compatability layer
 6. Scheduler and Shaper support in transmit function
 7. MDIO support

Change Log:
V4->V5: Addressed below concerns:
        * Florian Fanelli: Miscellaneous comments on ethtool & enet layer
        * Stephen Hamminger: comment of Netdev stats in ethool layer
        * Leon Romanvosky: Comments on Driver Version String, naming & Kconfig
        * Rochard Cochran: Redundant function prototype 
V3->V4: Addressed below comments:
        * Andrew Lunn: Various comments on MDIO, ethtool, ENET driver etc,
        * Stephen Hemminger: change access and updation to 64 but statistics
        * Bo You: some spelling mistakes and checkpatch.pl errors.
V2->V3: Addressed comments
        * Yuval Mintz: Removal of redundant userprio-to-tc code
        * Stephen Hemminger: Ethtool & interuupt enable
        * Andrew Lunn: On C45/C22 PHy support, HNAE, ethtool
        * Florian Fainelli: C45/C22 and phy_connect/attach
        * Intel kbuild errors
V1->V2: Addressed some comments by kbuild, Yuval MIntz, Andrew Lunn &
        Florian Fainelli in the following patches:
        * Add support of HNS3 Ethernet Driver for hip08 SoC
        * Add MDIO support to HNS3 Ethernet driver for hip08 SoC
        * Add support of debugfs interface to HNS3 driver

Salil Mehta (8):
  net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC
  net: hns3: Add support of the HNAE3 framework
  net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support
  net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support
  net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver
  net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
  net: hns3: Add Ethtool support to HNS3 driver
  net: hns3: Add HNS3 driver to kernel build framework & MAINTAINERS

 MAINTAINERS                                        |    8 +
 drivers/net/ethernet/hisilicon/Kconfig             |   27 +
 drivers/net/ethernet/hisilicon/Makefile            |    1 +
 drivers/net/ethernet/hisilicon/hns3/Makefile       |    7 +
 drivers/net/ethernet/hisilicon/hns3/hnae3.c        |  319 ++
 drivers/net/ethernet/hisilicon/hns3/hnae3.h        |  444 ++
 .../net/ethernet/hisilicon/hns3/hns3pf/Makefile    |   11 +
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c |  365 ++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h |  741 ++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 4266 ++++++++++++++++++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h    |  530 +++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c    |  209 +
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c  | 1015 +++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h  |  106 +
 .../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 2838 +++++++++++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h |  595 +++
 .../ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c  |  487 +++
 17 files changed, 11969 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/Makefile
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.h
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c

-- 
2.7.4

[toc] | [next] | [standalone]


#1699130 — [PATCH V5 net-next 5/8] net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 00:30 +0200
Subject[PATCH V5 net-next 5/8] net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver
Message-ID<u8lVE-1pM-9@gated-at.bofh.it>
In reply to#1699129
THis patch adds the support of the Scheduling and Shaping
functionalities during the transmit leg. This also adds the
support of Pause at MAC level. (Pause at per-priority level
shall be added later along with the DCB feature).

Hardware as such consists of two types of cofiguration of 6 level
schedulers. Algorithms varies according to the level and type
of scheduler being used. Current patch is used to initialize
the mapping, algorithms(like SP, DWRR etc) and shaper(CIR, PIR etc)
being used.

Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
---
Patch V5: Addressed comments by
   1. Richard Cochran
      https://lkml.org/lkml/2017/7/23/13
Patch V2,V4: No Change
Patch V1: Initial Submit
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c  | 1015 ++++++++++++++++++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h  |  106 ++
 2 files changed, 1121 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
new file mode 100644
index 0000000..88d4d24
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/etherdevice.h>
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hclge_tm.h"
+
+enum hclge_shaper_level {
+	HCLGE_SHAPER_LVL_PRI	= 0,
+	HCLGE_SHAPER_LVL_PG	= 1,
+	HCLGE_SHAPER_LVL_PORT	= 2,
+	HCLGE_SHAPER_LVL_QSET	= 3,
+	HCLGE_SHAPER_LVL_CNT	= 4,
+	HCLGE_SHAPER_LVL_VF	= 0,
+	HCLGE_SHAPER_LVL_PF	= 1,
+};
+
+#define HCLGE_SHAPER_BS_U_DEF	1
+#define HCLGE_SHAPER_BS_S_DEF	4
+
+#define HCLGE_ETHER_MAX_RATE	100000
+
+/* hclge_shaper_para_calc: calculate ir parameter for the shaper
+ * @ir: Rate to be config, its unit is Mbps
+ * @shaper_level: the shaper level. eg: port, pg, priority, queueset
+ * @ir_b: IR_B parameter of IR shaper
+ * @ir_u: IR_U parameter of IR shaper
+ * @ir_s: IR_S parameter of IR shaper
+ *
+ * the formula:
+ *
+ *		IR_b * (2 ^ IR_u) * 8
+ * IR(Mbps) = -------------------------  *  CLOCK(1000Mbps)
+ *		Tick * (2 ^ IR_s)
+ *
+ * @return: 0: calculate sucessful, negative: fail
+ */
+static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
+				  u8 *ir_b, u8 *ir_u, u8 *ir_s)
+{
+	const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
+		6 * 256,        /* Prioriy level */
+		6 * 32,         /* Prioriy group level */
+		6 * 8,          /* Port level */
+		6 * 256         /* Qset level */
+	};
+	u8 ir_u_calc = 0, ir_s_calc = 0;
+	u32 ir_calc;
+	u32 tick;
+
+	/* Calc tick */
+	if (shaper_level >= HCLGE_SHAPER_LVL_CNT)
+		return -ENOMEM;
+
+	tick = tick_array[shaper_level];
+
+	/**
+	 * Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0
+	 * the formula is changed to:
+	 *		126 * 1 * 8
+	 * ir_calc = ---------------- * 1000
+	 *		tick * 1
+	 */
+	ir_calc = (1008000 + (tick >> 1) - 1) / tick;
+
+	if (ir_calc == ir) {
+		*ir_b = 126;
+		*ir_u = 0;
+		*ir_s = 0;
+
+		return 0;
+	} else if (ir_calc > ir) {
+		/* Increasing the denominator to select ir_s value */
+		while (ir_calc > ir) {
+			ir_s_calc++;
+			ir_calc = 1008000 / (tick * (1 << ir_s_calc));
+		}
+
+		if (ir_calc == ir)
+			*ir_b = 126;
+		else
+			*ir_b = (ir * tick * (1 << ir_s_calc) + 4000) / 8000;
+	} else {
+		/* Increasing the numerator to select ir_u value */
+		u32 numerator;
+
+		while (ir_calc < ir) {
+			ir_u_calc++;
+			numerator = 1008000 * (1 << ir_u_calc);
+			ir_calc = (numerator + (tick >> 1)) / tick;
+		}
+
+		if (ir_calc == ir) {
+			*ir_b = 126;
+		} else {
+			u32 denominator = (8000 * (1 << --ir_u_calc));
+			*ir_b = (ir * tick + (denominator >> 1)) / denominator;
+		}
+	}
+
+	*ir_u = ir_u_calc;
+	*ir_s = ir_s_calc;
+
+	return 0;
+}
+
+static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
+{
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PAUSE_EN, false);
+
+	desc.data[0] = cpu_to_le32((tx ? HCLGE_TX_MAC_PAUSE_EN_MSK : 0) |
+		(rx ? HCLGE_RX_MAC_PAUSE_EN_MSK : 0));
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id)
+{
+	u8 tc;
+
+	for (tc = 0; tc < hdev->tm_info.num_tc; tc++)
+		if (hdev->tm_info.tc_info[tc].up == pri_id)
+			break;
+
+	if (tc >= hdev->tm_info.num_tc)
+		return -ENOMEM;
+
+	/**
+	 * the register for priority has four bytes, the first bytes includes
+	 *  priority0 and priority1, the higher 4bit stands for priority1
+	 *  while the lower 4bit stands for priority0, as below:
+	 * first byte:	| pri_1 | pri_0 |
+	 * second byte:	| pri_3 | pri_2 |
+	 * third byte:	| pri_5 | pri_4 |
+	 * fourth byte:	| pri_7 | pri_6 |
+	 */
+	pri[pri_id >> 1] |= tc << ((pri_id & 1) * 4);
+
+	return 0;
+}
+
+static int hclge_up_to_tc_map(struct hclge_dev *hdev)
+{
+	struct hclge_desc desc;
+	u8 *pri = (u8 *)desc.data;
+	u8 pri_id;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, false);
+
+	for (pri_id = 0; pri_id < hdev->tm_info.num_tc; pri_id++) {
+		ret = hclge_fill_pri_array(hdev, pri, pri_id);
+		if (ret)
+			return ret;
+	}
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev,
+				      u8 pg_id, u8 pri_bit_map)
+{
+	struct hclge_pg_to_pri_link_cmd *map;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_TO_PRI_LINK, false);
+
+	map = (struct hclge_pg_to_pri_link_cmd *)desc.data;
+
+	map->pg_id = cpu_to_le16(pg_id);
+	map->pri_bit_map = pri_bit_map;
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev,
+				      u16 qs_id, u8 pri)
+{
+	struct hclge_qs_to_pri_link_cmd *map;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_TO_PRI_LINK, false);
+
+	map = (struct hclge_qs_to_pri_link_cmd *)desc.data;
+
+	map->qs_id = cpu_to_le16(qs_id);
+	map->priority = pri;
+	map->link_vld = HCLGE_TM_QS_PRI_LINK_VLD_MSK;
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_q_to_qs_map_cfg(struct hclge_dev *hdev,
+				    u8 q_id, u16 qs_id)
+{
+	struct hclge_nq_to_qs_link_cmd *map;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NQ_TO_QS_LINK, false);
+
+	map = (struct hclge_nq_to_qs_link_cmd *)desc.data;
+
+	map->nq_id = cpu_to_le16(q_id);
+	map->qset_id = cpu_to_le16(qs_id | HCLGE_TM_Q_QS_LINK_VLD_MSK);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_gp_weight_cfg(struct hclge_dev *hdev, u8 pg_id,
+				  u8 dwrr)
+{
+	struct hclge_pg_weight_cmd *weight;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_WEIGHT, false);
+
+	weight = (struct hclge_pg_weight_cmd *)desc.data;
+
+	weight->pg_id = pg_id;
+	weight->dwrr = dwrr;
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pri_weight_cfg(struct hclge_dev *hdev, u8 pri_id,
+				   u8 dwrr)
+{
+	struct hclge_priority_weight_cmd *weight;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_WEIGHT, false);
+
+	weight = (struct hclge_priority_weight_cmd *)desc.data;
+
+	weight->pri_id = pri_id;
+	weight->dwrr = dwrr;
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_weight_cfg(struct hclge_dev *hdev, u16 qs_id,
+				  u8 dwrr)
+{
+	struct hclge_qs_weight_cmd *weight;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_WEIGHT, false);
+
+	weight = (struct hclge_qs_weight_cmd *)desc.data;
+
+	weight->qs_id = cpu_to_le16(qs_id);
+	weight->dwrr = dwrr;
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
+				    enum hclge_shap_bucket bucket, u8 pg_id,
+				    u8 ir_b, u8 ir_u, u8 ir_s, u8 bs_b, u8 bs_s)
+{
+	struct hclge_pg_shapping_cmd *shap_cfg_cmd;
+	enum hclge_opcode_type opcode;
+	struct hclge_desc desc;
+
+	opcode = bucket ? HCLGE_OPC_TM_PG_P_SHAPPING :
+		HCLGE_OPC_TM_PG_C_SHAPPING;
+	hclge_cmd_setup_basic_desc(&desc, opcode, false);
+
+	shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
+
+	shap_cfg_cmd->pg_id = pg_id;
+
+	hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_B, ir_b);
+	hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_U, ir_u);
+	hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_S, ir_s);
+	hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, BS_B, bs_b);
+	hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, BS_S, bs_s);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
+				     enum hclge_shap_bucket bucket, u8 pri_id,
+				     u8 ir_b, u8 ir_u, u8 ir_s,
+				     u8 bs_b, u8 bs_s)
+{
+	struct hclge_pri_shapping_cmd *shap_cfg_cmd;
+	enum hclge_opcode_type opcode;
+	struct hclge_desc desc;
+
+	opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING :
+		HCLGE_OPC_TM_PRI_C_SHAPPING;
+
+	hclge_cmd_setup_basic_desc(&desc, opcode, false);
+
+	shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
+
+	shap_cfg_cmd->pri_id = pri_id;
+
+	hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_B, ir_b);
+	hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_U, ir_u);
+	hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_S, ir_s);
+	hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, BS_B, bs_b);
+	hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, BS_S, bs_s);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pg_schd_mode_cfg(struct hclge_dev *hdev, u8 pg_id)
+{
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, false);
+
+	if (hdev->tm_info.pg_info[pg_id].pg_sch_mode == HCLGE_SCH_MODE_DWRR)
+		desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
+	else
+		desc.data[1] = 0;
+
+	desc.data[0] = cpu_to_le32(pg_id);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id)
+{
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, false);
+
+	if (hdev->tm_info.tc_info[pri_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR)
+		desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
+	else
+		desc.data[1] = 0;
+
+	desc.data[0] = cpu_to_le32(pri_id);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id)
+{
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false);
+
+	if (hdev->tm_info.tc_info[qs_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR)
+		desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
+	else
+		desc.data[1] = 0;
+
+	desc.data[0] = cpu_to_le32(qs_id);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static int hclge_tm_qs_bp_cfg(struct hclge_dev *hdev, u8 tc)
+{
+	struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd;
+	struct hclge_desc desc;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_BP_TO_QSET_MAPPING,
+				   false);
+
+	bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data;
+
+	bp_to_qs_map_cmd->tc_id = tc;
+
+	/* Qset and tc is one by one mapping */
+	bp_to_qs_map_cmd->qs_bit_map = cpu_to_le32(1 << tc);
+
+	return hclge_cmd_send(&hdev->hw, &desc, 1);
+}
+
+static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
+{
+	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+	struct hclge_dev *hdev = vport->back;
+	u8 i;
+
+	kinfo = &vport->nic.kinfo;
+	vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
+	kinfo->num_tc =
+		min_t(u16, kinfo->num_tqps, hdev->tm_info.num_tc);
+	kinfo->rss_size
+		= min_t(u16, hdev->rss_size_max,
+			kinfo->num_tqps / kinfo->num_tc);
+	vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id;
+	vport->dwrr = 100;  /* 100 percent as init */
+
+	for (i = 0; i < kinfo->num_tc; i++) {
+		if (hdev->hw_tc_map & BIT(i)) {
+			kinfo->tc_info[i].enable = true;
+			kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
+			kinfo->tc_info[i].tqp_count = kinfo->rss_size;
+			kinfo->tc_info[i].tc = i;
+			kinfo->tc_info[i].up = hdev->tm_info.tc_info[i].up;
+		} else {
+			/* Set to default queue if TC is disable */
+			kinfo->tc_info[i].enable = false;
+			kinfo->tc_info[i].tqp_offset = 0;
+			kinfo->tc_info[i].tqp_count = 1;
+			kinfo->tc_info[i].tc = 0;
+			kinfo->tc_info[i].up = 0;
+		}
+	}
+}
+
+static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
+{
+	struct hclge_vport *vport = hdev->vport;
+	u32 i;
+
+	for (i = 0; i < hdev->num_alloc_vport; i++) {
+		hclge_tm_vport_tc_info_update(vport);
+
+		vport++;
+	}
+}
+
+static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
+{
+	u8 i;
+
+	for (i = 0; i < hdev->tm_info.num_tc; i++) {
+		hdev->tm_info.tc_info[i].tc_id = i;
+		hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR;
+		hdev->tm_info.tc_info[i].up = i;
+		hdev->tm_info.tc_info[i].pgid = 0;
+		hdev->tm_info.tc_info[i].bw_limit =
+			hdev->tm_info.pg_info[0].bw_limit;
+	}
+
+	hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
+}
+
+static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
+{
+	u8 i;
+
+	for (i = 0; i < hdev->tm_info.num_pg; i++) {
+		int k;
+
+		hdev->tm_info.pg_dwrr[i] = i ? 0 : 100;
+
+		hdev->tm_info.pg_info[i].pg_id = i;
+		hdev->tm_info.pg_info[i].pg_sch_mode = HCLGE_SCH_MODE_DWRR;
+
+		hdev->tm_info.pg_info[i].bw_limit = HCLGE_ETHER_MAX_RATE;
+
+		if (i != 0)
+			continue;
+
+		hdev->tm_info.pg_info[i].tc_bit_map = hdev->hw_tc_map;
+		for (k = 0; k < hdev->tm_info.num_tc; k++)
+			hdev->tm_info.pg_info[i].tc_dwrr[k] = 100;
+	}
+}
+
+static int hclge_tm_schd_info_init(struct hclge_dev *hdev)
+{
+	if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
+	    (hdev->tm_info.num_pg != 1))
+		return -EINVAL;
+
+	hclge_tm_pg_info_init(hdev);
+
+	hclge_tm_tc_info_init(hdev);
+
+	hclge_tm_vport_info_update(hdev);
+
+	hdev->tm_info.fc_mode = HCLGE_FC_NONE;
+	hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
+
+	return 0;
+}
+
+static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev)
+{
+	int ret;
+	u32 i;
+
+	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
+		return 0;
+
+	for (i = 0; i < hdev->tm_info.num_pg; i++) {
+		/* Cfg mapping */
+		ret = hclge_tm_pg_to_pri_map_cfg(
+			hdev, i, hdev->tm_info.pg_info[i].tc_bit_map);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pg_shaper_cfg(struct hclge_dev *hdev)
+{
+	u8 ir_u, ir_b, ir_s;
+	int ret;
+	u32 i;
+
+	/* Cfg pg schd */
+	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
+		return 0;
+
+	/* Pg to pri */
+	for (i = 0; i < hdev->tm_info.num_pg; i++) {
+		/* Calc shaper para */
+		ret = hclge_shaper_para_calc(
+					hdev->tm_info.pg_info[i].bw_limit,
+					HCLGE_SHAPER_LVL_PG,
+					&ir_b, &ir_u, &ir_s);
+		if (ret)
+			return ret;
+
+		ret = hclge_tm_pg_shapping_cfg(hdev,
+					       HCLGE_TM_SHAP_C_BUCKET, i,
+					       0, 0, 0, HCLGE_SHAPER_BS_U_DEF,
+					       HCLGE_SHAPER_BS_S_DEF);
+		if (ret)
+			return ret;
+
+		ret = hclge_tm_pg_shapping_cfg(hdev,
+					       HCLGE_TM_SHAP_P_BUCKET, i,
+					       ir_b, ir_u, ir_s,
+					       HCLGE_SHAPER_BS_U_DEF,
+					       HCLGE_SHAPER_BS_S_DEF);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pg_dwrr_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+	u32 i;
+
+	/* cfg pg schd */
+	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
+		return 0;
+
+	/* pg to prio */
+	for (i = 0; i < hdev->tm_info.num_pg; i++) {
+		/* Cfg dwrr */
+		ret = hclge_tm_gp_weight_cfg(hdev, i,
+					     hdev->tm_info.pg_dwrr[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev,
+				   struct hclge_vport *vport)
+{
+	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+	struct hnae3_queue **tqp = kinfo->tqp;
+	struct hnae3_tc_info *v_tc_info;
+	u32 i, j;
+	int ret;
+
+	for (i = 0; i < kinfo->num_tc; i++) {
+		v_tc_info = &kinfo->tc_info[i];
+		for (j = 0; j < v_tc_info->tqp_count; j++) {
+			struct hnae3_queue *q = tqp[v_tc_info->tqp_offset + j];
+
+			ret = hclge_tm_q_to_qs_map_cfg(hdev,
+						       hclge_get_queue_id(q),
+						       vport->qs_offset + i);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_vport *vport = hdev->vport;
+	int ret;
+	u32 i;
+
+	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+		/* Cfg qs -> pri mapping, one by one mapping */
+		for (i = 0; i < hdev->tm_info.num_tc; i++) {
+			ret = hclge_tm_qs_to_pri_map_cfg(hdev, i, i);
+			if (ret)
+				return ret;
+		}
+	} else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) {
+		int k;
+		/* Cfg qs -> pri mapping,  qs = tc, pri = vf, 8 qs -> 1 pri */
+		for (k = 0; k < hdev->num_alloc_vport; k++)
+			for (i = 0; i < HNAE3_MAX_TC; i++) {
+				ret = hclge_tm_qs_to_pri_map_cfg(
+					hdev, vport[k].qs_offset + i, k);
+				if (ret)
+					return ret;
+			}
+	} else {
+		return -EINVAL;
+	}
+
+	/* Cfg q -> qs mapping */
+	for (i = 0; i < hdev->num_alloc_vport; i++) {
+		ret = hclge_vport_q_to_qs_map(hdev, vport);
+		if (ret)
+			return ret;
+
+		vport++;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_tc_base_shaper_cfg(struct hclge_dev *hdev)
+{
+	u8 ir_u, ir_b, ir_s;
+	int ret;
+	u32 i;
+
+	for (i = 0; i < hdev->tm_info.num_tc; i++) {
+		ret = hclge_shaper_para_calc(
+					hdev->tm_info.tc_info[i].bw_limit,
+					HCLGE_SHAPER_LVL_PRI,
+					&ir_b, &ir_u, &ir_s);
+		if (ret)
+			return ret;
+
+		ret = hclge_tm_pri_shapping_cfg(
+			hdev, HCLGE_TM_SHAP_C_BUCKET, i,
+			0, 0, 0, HCLGE_SHAPER_BS_U_DEF,
+			HCLGE_SHAPER_BS_S_DEF);
+		if (ret)
+			return ret;
+
+		ret = hclge_tm_pri_shapping_cfg(
+			hdev, HCLGE_TM_SHAP_P_BUCKET, i,
+			ir_b, ir_u, ir_s, HCLGE_SHAPER_BS_U_DEF,
+			HCLGE_SHAPER_BS_S_DEF);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_vnet_base_shaper_pri_cfg(struct hclge_vport *vport)
+{
+	struct hclge_dev *hdev = vport->back;
+	u8 ir_u, ir_b, ir_s;
+	int ret;
+
+	ret = hclge_shaper_para_calc(vport->bw_limit, HCLGE_SHAPER_LVL_VF,
+				     &ir_b, &ir_u, &ir_s);
+	if (ret)
+		return ret;
+
+	ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET,
+					vport->vport_id,
+					0, 0, 0, HCLGE_SHAPER_BS_U_DEF,
+					HCLGE_SHAPER_BS_S_DEF);
+	if (ret)
+		return ret;
+
+	ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET,
+					vport->vport_id,
+					ir_b, ir_u, ir_s,
+					HCLGE_SHAPER_BS_U_DEF,
+					HCLGE_SHAPER_BS_S_DEF);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport)
+{
+	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+	struct hclge_dev *hdev = vport->back;
+	struct hnae3_tc_info *v_tc_info;
+	u8 ir_u, ir_b, ir_s;
+	u32 i;
+	int ret;
+
+	for (i = 0; i < kinfo->num_tc; i++) {
+		v_tc_info = &kinfo->tc_info[i];
+		ret = hclge_shaper_para_calc(
+					hdev->tm_info.tc_info[i].bw_limit,
+					HCLGE_SHAPER_LVL_QSET,
+					&ir_b, &ir_u, &ir_s);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_vnet_base_shaper_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_vport *vport = hdev->vport;
+	int ret;
+	u32 i;
+
+	/* Need config vport shaper */
+	for (i = 0; i < hdev->num_alloc_vport; i++) {
+		ret = hclge_tm_pri_vnet_base_shaper_pri_cfg(vport);
+		if (ret)
+			return ret;
+
+		ret = hclge_tm_pri_vnet_base_shaper_qs_cfg(vport);
+		if (ret)
+			return ret;
+
+		vport++;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+
+	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+		ret = hclge_tm_pri_tc_base_shaper_cfg(hdev);
+		if (ret)
+			return ret;
+	} else {
+		ret = hclge_tm_pri_vnet_base_shaper_cfg(hdev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_pg_info *pg_info;
+	u8 dwrr;
+	int ret;
+	u32 i;
+
+	for (i = 0; i < hdev->tm_info.num_tc; i++) {
+		pg_info =
+			&hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
+		dwrr = pg_info->tc_dwrr[i];
+
+		ret = hclge_tm_pri_weight_cfg(hdev, i, dwrr);
+		if (ret)
+			return ret;
+
+		ret = hclge_tm_qs_weight_cfg(hdev, i, dwrr);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport)
+{
+	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+	struct hclge_dev *hdev = vport->back;
+	int ret;
+	u8 i;
+
+	/* Vf dwrr */
+	ret = hclge_tm_pri_weight_cfg(hdev, vport->vport_id, vport->dwrr);
+	if (ret)
+		return ret;
+
+	/* Qset dwrr */
+	for (i = 0; i < kinfo->num_tc; i++) {
+		ret = hclge_tm_qs_weight_cfg(
+			hdev, vport->qs_offset + i,
+			hdev->tm_info.pg_info[0].tc_dwrr[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_vnet_base_dwrr_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_vport *vport = hdev->vport;
+	int ret;
+	u32 i;
+
+	for (i = 0; i < hdev->num_alloc_vport; i++) {
+		ret = hclge_tm_pri_vnet_base_dwrr_pri_cfg(vport);
+		if (ret)
+			return ret;
+
+		vport++;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+
+	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+		ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev);
+		if (ret)
+			return ret;
+	} else {
+		ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_map_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+
+	ret = hclge_tm_pg_to_pri_map(hdev);
+	if (ret)
+		return ret;
+
+	return hclge_tm_pri_q_qs_cfg(hdev);
+}
+
+static int hclge_tm_shaper_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+
+	ret = hclge_tm_pg_shaper_cfg(hdev);
+	if (ret)
+		return ret;
+
+	return hclge_tm_pri_shaper_cfg(hdev);
+}
+
+int hclge_tm_dwrr_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+
+	ret = hclge_tm_pg_dwrr_cfg(hdev);
+	if (ret)
+		return ret;
+
+	return hclge_tm_pri_dwrr_cfg(hdev);
+}
+
+static int hclge_tm_lvl2_schd_mode_cfg(struct hclge_dev *hdev)
+{
+	int ret;
+	u8 i;
+
+	/* Only being config on TC-Based scheduler mode */
+	if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE)
+		return 0;
+
+	for (i = 0; i < hdev->tm_info.num_pg; i++) {
+		ret = hclge_tm_pg_schd_mode_cfg(hdev, i);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport)
+{
+	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+	struct hclge_dev *hdev = vport->back;
+	int ret;
+	u8 i;
+
+	ret = hclge_tm_pri_schd_mode_cfg(hdev, vport->vport_id);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < kinfo->num_tc; i++) {
+		ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
+{
+	struct hclge_vport *vport = hdev->vport;
+	int ret;
+	u8 i;
+
+	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
+		for (i = 0; i < hdev->tm_info.num_tc; i++) {
+			ret = hclge_tm_pri_schd_mode_cfg(hdev, i);
+			if (ret)
+				return ret;
+
+			ret = hclge_tm_qs_schd_mode_cfg(hdev, i);
+			if (ret)
+				return ret;
+		}
+	} else {
+		for (i = 0; i < hdev->num_alloc_vport; i++) {
+			ret = hclge_tm_schd_mode_vnet_base_cfg(vport);
+			if (ret)
+				return ret;
+
+			vport++;
+		}
+	}
+
+	return 0;
+}
+
+static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
+{
+	int ret;
+
+	ret = hclge_tm_lvl2_schd_mode_cfg(hdev);
+	if (ret)
+		return ret;
+
+	return hclge_tm_lvl34_schd_mode_cfg(hdev);
+}
+
+static int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
+{
+	int ret;
+
+	/* Cfg tm mapping  */
+	ret = hclge_tm_map_cfg(hdev);
+	if (ret)
+		return ret;
+
+	/* Cfg tm shaper */
+	ret = hclge_tm_shaper_cfg(hdev);
+	if (ret)
+		return ret;
+
+	/* Cfg dwrr */
+	ret = hclge_tm_dwrr_cfg(hdev);
+	if (ret)
+		return ret;
+
+	/* Cfg schd mode for each level schd */
+	return hclge_tm_schd_mode_hw(hdev);
+}
+
+int hclge_pause_setup_hw(struct hclge_dev *hdev)
+{
+	bool en = hdev->tm_info.fc_mode != HCLGE_FC_PFC;
+	int ret;
+	u8 i;
+
+	ret = hclge_mac_pause_en_cfg(hdev, en, en);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < hdev->tm_info.num_tc; i++) {
+		ret = hclge_tm_qs_bp_cfg(hdev, i);
+		if (ret)
+			return ret;
+	}
+
+	return hclge_up_to_tc_map(hdev);
+}
+
+int hclge_tm_init_hw(struct hclge_dev *hdev)
+{
+	int ret;
+
+	if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
+	    (hdev->tx_sch_mode != HCLGE_FLAG_VNET_BASE_SCH_MODE))
+		return -ENOTSUPP;
+
+	ret = hclge_tm_schd_setup_hw(hdev);
+	if (ret)
+		return ret;
+
+	ret = hclge_pause_setup_hw(hdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int hclge_tm_schd_init(struct hclge_dev *hdev)
+{
+	int ret = hclge_tm_schd_info_init(hdev);
+
+	if (ret)
+		return ret;
+
+	return hclge_tm_init_hw(hdev);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
new file mode 100644
index 0000000..ebc907a
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __HCLGE_TX_SCHD_H__
+#define __HCLGE_TX_SCHD_H__
+
+#include <linux/types.h>
+
+/* MAC Pause */
+#define HCLGE_TX_MAC_PAUSE_EN_MSK	BIT(0)
+#define HCLGE_RX_MAC_PAUSE_EN_MSK	BIT(1)
+
+#define HCLGE_TM_PORT_BASE_MODE_MSK	BIT(0)
+
+/* SP or DWRR */
+#define HCLGE_TM_TX_SCHD_DWRR_MSK	BIT(0)
+#define HCLGE_TM_TX_SCHD_SP_MSK		(0xFE)
+
+struct hclge_pg_to_pri_link_cmd {
+	u8 pg_id;
+	u8 rsvd1[3];
+	u8 pri_bit_map;
+};
+
+struct hclge_qs_to_pri_link_cmd {
+	__le16 qs_id;
+	__le16 rsvd;
+	u8 priority;
+#define HCLGE_TM_QS_PRI_LINK_VLD_MSK	BIT(0)
+	u8 link_vld;
+};
+
+struct hclge_nq_to_qs_link_cmd {
+	__le16 nq_id;
+	__le16 rsvd;
+#define HCLGE_TM_Q_QS_LINK_VLD_MSK	BIT(10)
+	__le16 qset_id;
+};
+
+struct hclge_pg_weight_cmd {
+	u8 pg_id;
+	u8 dwrr;
+};
+
+struct hclge_priority_weight_cmd {
+	u8 pri_id;
+	u8 dwrr;
+};
+
+struct hclge_qs_weight_cmd {
+	__le16 qs_id;
+	u8 dwrr;
+};
+
+#define HCLGE_TM_SHAP_IR_B_MSK  GENMASK(7, 0)
+#define HCLGE_TM_SHAP_IR_B_LSH	0
+#define HCLGE_TM_SHAP_IR_U_MSK  GENMASK(11, 8)
+#define HCLGE_TM_SHAP_IR_U_LSH	8
+#define HCLGE_TM_SHAP_IR_S_MSK  GENMASK(15, 12)
+#define HCLGE_TM_SHAP_IR_S_LSH	12
+#define HCLGE_TM_SHAP_BS_B_MSK  GENMASK(20, 16)
+#define HCLGE_TM_SHAP_BS_B_LSH	16
+#define HCLGE_TM_SHAP_BS_S_MSK  GENMASK(25, 21)
+#define HCLGE_TM_SHAP_BS_S_LSH	21
+
+enum hclge_shap_bucket {
+	HCLGE_TM_SHAP_C_BUCKET = 0,
+	HCLGE_TM_SHAP_P_BUCKET,
+};
+
+struct hclge_pri_shapping_cmd {
+	u8 pri_id;
+	u8 rsvd[3];
+	__le32 pri_shapping_para;
+};
+
+struct hclge_pg_shapping_cmd {
+	u8 pg_id;
+	u8 rsvd[3];
+	__le32 pg_shapping_para;
+};
+
+struct hclge_bp_to_qs_map_cmd {
+	u8 tc_id;
+	u8 rsvd[2];
+	u8 qs_group_id;
+	__le32 qs_bit_map;
+	u32 rsvd1;
+};
+
+#define hclge_tm_set_feild(dest, string, val) \
+			hnae_set_field((dest), (HCLGE_TM_SHAP_##string##_MSK), \
+				       (HCLGE_TM_SHAP_##string##_LSH), val)
+#define hclge_tm_get_feild(src, string) \
+			hnae_get_field((src), (HCLGE_TM_SHAP_##string##_MSK), \
+				       (HCLGE_TM_SHAP_##string##_LSH))
+
+int hclge_tm_schd_init(struct hclge_dev *hdev);
+int hclge_pause_setup_hw(struct hclge_dev *hdev);
+#endif
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1699131 — [PATCH V5 net-next 8/8] net: hns3: Add HNS3 driver to kernel build framework & MAINTAINERS

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 00:30 +0200
Subject[PATCH V5 net-next 8/8] net: hns3: Add HNS3 driver to kernel build framework & MAINTAINERS
Message-ID<u8lVE-1pM-15@gated-at.bofh.it>
In reply to#1699129
This patch updates the MAINTAINERS file with HNS3 Ethernet driver
maintainers names and other details. This also introduces the new
Makefiles required to build the HNS3 Ethernet driver and updates
the existing Kconfig file in the hisilicon folder.

Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
Patch V5: Addressed below concerns:
 1. Leon Romanovsky
    https://lkml.org/lkml/2017/7/23/66
Patch V4: No change over V3
Patch V3: Addressed below errors:
 1. Intel kbuild: https://lkml.org/lkml/2017/6/14/313
 2. Intel Kbuild: https://lkml.org/lkml/2017/6/14/636
Patch V2: No change
Patch V1: Initial Submit
---
 MAINTAINERS                                        |  8 +++++++
 drivers/net/ethernet/hisilicon/Kconfig             | 27 ++++++++++++++++++++++
 drivers/net/ethernet/hisilicon/Makefile            |  1 +
 drivers/net/ethernet/hisilicon/hns3/Makefile       |  7 ++++++
 .../net/ethernet/hisilicon/hns3/hns3pf/Makefile    | 11 +++++++++
 5 files changed, 54 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/Makefile
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile

diff --git a/MAINTAINERS b/MAINTAINERS
index 297e610..a22d5b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6197,6 +6197,14 @@ S:	Maintained
 F:	drivers/net/ethernet/hisilicon/
 F:	Documentation/devicetree/bindings/net/hisilicon*.txt
 
+HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
+M:	Yisen Zhuang <yisen.zhuang@huawei.com>
+M:	Salil Mehta <salil.mehta@huawei.com>
+L:	netdev@vger.kernel.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/net/ethernet/hisilicon/hns3/
+
 HISILICON ROCE DRIVER
 M:	Lijun Ou <oulijun@huawei.com>
 M:	Wei Hu(Xavier) <xavier.huwei@huawei.com>
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index d11287e..91c7bdb 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -76,4 +76,31 @@ config HNS_ENET
 	  This selects the general ethernet driver for HNS.  This module make
 	  use of any HNS AE driver, such as HNS_DSAF
 
+config HNS3
+	tristate "Hisilicon Network Subsystem Support HNS3 (Framework)"
+    depends on PCI
+	---help---
+	  This selects the framework support for Hisilicon Network Subsystem 3.
+	  This layer facilitates clients like ENET, RoCE and user-space ethernet
+	  drivers(like ODP)to register with HNAE devices and their associated
+	  operations.
+
+config HNS3_HCLGE
+	tristate "Hisilicon HNS3 HCLGE Acceleration Engine & Compatibility Layer Support"
+    depends on PCI_MSI
+	depends on HNS3
+	---help---
+	  This selects the HNS3_HCLGE network acceleration engine & its hardware
+	  compatibility layer. The engine would be used in Hisilicon hip08 family of
+	  SoCs and further upcoming SoCs.
+
+config HNS3_ENET
+	tristate "Hisilicon HNS3 Ethernet Device Support"
+    depends on 64BIT && PCI
+	depends on HNS3 && HNS3_HCLGE
+	---help---
+	  This selects the Ethernet Driver for Hisilicon Network Subsystem 3 for hip08
+	  family of SoCs. This module depends upon HNAE3 driver to access the HNAE3
+	  devices and their associated operations.
+
 endif # NET_VENDOR_HISILICON
diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile
index 8661695..3828c43 100644
--- a/drivers/net/ethernet/hisilicon/Makefile
+++ b/drivers/net/ethernet/hisilicon/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o
 obj-$(CONFIG_HIP04_ETH) += hip04_eth.o
 obj-$(CONFIG_HNS_MDIO) += hns_mdio.o
 obj-$(CONFIG_HNS) += hns/
+obj-$(CONFIG_HNS3) += hns3/
 obj-$(CONFIG_HISI_FEMAC) += hisi_femac.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
new file mode 100644
index 0000000..a9349e1
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the HISILICON network device drivers.
+#
+
+obj-$(CONFIG_HNS3) += hns3pf/
+
+obj-$(CONFIG_HNS3) += hnae3.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
new file mode 100644
index 0000000..162e8a42
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the HISILICON network device drivers.
+#
+
+ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
+
+obj-$(CONFIG_HNS3_HCLGE) += hclge.o
+hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o
+
+obj-$(CONFIG_HNS3_ENET) += hns3.o
+hns3-objs = hns3_enet.o hns3_ethtool.o
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1699132 — [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 00:30 +0200
Subject[PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework
Message-ID<u8lVE-1pM-11@gated-at.bofh.it>
In reply to#1699129
This patch adds the support of the HNAE3 (Hisilicon Network
Acceleration Engine 3) framework support to the HNS3 driver.

Framework facilitates clients like ENET(HNS3 Ethernet Driver), RoCE
and user-space Ethernet drivers (like ODP etc.) to register with HNAE3
devices and their associated operations.

Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
---
Patch V5: Addressed following comments
  1. Leon Romanovsky:
     https://lkml.org/lkml/2017/7/23/67
Patch V4: Addressed following comments
  1. Andrew Lunn:
     https://lkml.org/lkml/2017/6/17/233
     https://lkml.org/lkml/2017/6/18/105
  2. Bo Yu:
     https://lkml.org/lkml/2017/6/18/112
  3. Stephen Hamminger:
     https://lkml.org/lkml/2017/6/19/778
Patch V3: Addressed below comments
  1. Andrew Lunn:
     https://lkml.org/lkml/2017/6/13/1025
Patch V2: No change
Patch V1: Initial Submit
---
 drivers/net/ethernet/hisilicon/hns3/hnae3.c | 319 ++++++++++++++++++++
 drivers/net/ethernet/hisilicon/hns3/hnae3.h | 444 ++++++++++++++++++++++++++++
 2 files changed, 763 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
new file mode 100644
index 0000000..d28b69d
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2016-2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "hnae3.h"
+
+static LIST_HEAD(hnae3_ae_algo_list);
+static LIST_HEAD(hnae3_client_list);
+static LIST_HEAD(hnae3_ae_dev_list);
+
+/* we are keeping things simple and using single lock for all the
+ * list. This is a non-critical code so other updations, if happen
+ * in parallel, can wait.
+ */
+static DEFINE_MUTEX(hnae3_common_lock);
+
+static bool hnae3_client_match(enum hnae3_client_type client_type,
+			       enum hnae3_dev_type dev_type)
+{
+	if (dev_type == HNAE3_DEV_KNIC) {
+		switch (client_type) {
+		case HNAE3_CLIENT_KNIC:
+		case HNAE3_CLIENT_ROCE:
+			return true;
+		default:
+			return false;
+		}
+	} else if (dev_type == HNAE3_DEV_UNIC) {
+		switch (client_type) {
+		case HNAE3_CLIENT_UNIC:
+			return true;
+		default:
+			return false;
+		}
+	} else {
+		return false;
+	}
+}
+
+static int hnae3_match_n_instantiate(struct hnae3_client *client,
+				     struct hnae3_ae_dev *ae_dev,
+				     bool is_reg, bool *matched)
+{
+	int ret;
+
+	*matched = false;
+
+	/* check if this client matches the type of ae_dev */
+	if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
+	      hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
+		return 0;
+	}
+	/* there is a match of client and dev */
+	*matched = true;
+
+	if (!(ae_dev->ops && ae_dev->ops->init_client_instance &&
+	      ae_dev->ops->uninit_client_instance)) {
+		dev_err(&ae_dev->pdev->dev,
+			"ae_dev or client init/uninit ops are null\n");
+		return -EOPNOTSUPP;
+	}
+
+	/* now, (un-)instantiate client by calling lower layer */
+	if (is_reg) {
+		ret = ae_dev->ops->init_client_instance(client, ae_dev);
+		if (ret)
+			dev_err(&ae_dev->pdev->dev,
+				"fail to instantiate client\n");
+		return ret;
+	}
+
+	ae_dev->ops->uninit_client_instance(client, ae_dev);
+	return 0;
+}
+
+int hnae3_register_client(struct hnae3_client *client)
+{
+	struct hnae3_client *client_tmp;
+	struct hnae3_ae_dev *ae_dev;
+	bool matched;
+	int ret = 0;
+
+	mutex_lock(&hnae3_common_lock);
+	/* one system should only have one client for every type */
+	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
+		if (client_tmp->type == client->type)
+			goto exit;
+	}
+
+	list_add_tail(&client->node, &hnae3_client_list);
+
+	/* initialize the client on every matched port */
+	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
+		/* if the client could not be initialized on current port, for
+		 * any error reasons, move on to next available port
+		 */
+		ret = hnae3_match_n_instantiate(client, ae_dev, true, &matched);
+		if (ret)
+			dev_err(&ae_dev->pdev->dev,
+				"match and instantiation failed for port\n");
+	}
+
+exit:
+	mutex_unlock(&hnae3_common_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(hnae3_register_client);
+
+void hnae3_unregister_client(struct hnae3_client *client)
+{
+	struct hnae3_ae_dev *ae_dev;
+	bool matched;
+
+	mutex_lock(&hnae3_common_lock);
+	/* un-initialize the client on every matched port */
+	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
+		hnae3_match_n_instantiate(client, ae_dev, false, &matched);
+	}
+
+	list_del(&client->node);
+	mutex_unlock(&hnae3_common_lock);
+}
+EXPORT_SYMBOL(hnae3_unregister_client);
+
+/* hnae_ae_register - register a AE engine to hnae framework
+ * @hdev: the hnae ae engine device
+ * @owner:  the module who provides this dev
+ * NOTE: the duplicated name will not be checked
+ */
+int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
+{
+	const struct pci_device_id *id;
+	struct hnae3_ae_dev *ae_dev;
+	struct hnae3_client *client;
+	bool matched;
+	int ret = 0;
+
+	mutex_lock(&hnae3_common_lock);
+
+	list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
+
+	/* Check if this algo/ops matches the list of ae_devs */
+	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
+		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
+		if (!id)
+			continue;
+
+		/* ae_dev init should set flag */
+		ae_dev->ops = ae_algo->ops;
+		ret = ae_algo->ops->init_ae_dev(ae_dev);
+		if (ret) {
+			dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
+			continue;
+		}
+
+		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
+
+		/* check the client list for the match with this ae_dev type and
+		 * initialize the figure out client instance
+		 */
+		list_for_each_entry(client, &hnae3_client_list, node) {
+			ret = hnae3_match_n_instantiate(client, ae_dev, true,
+							&matched);
+			if (ret)
+				dev_err(&ae_dev->pdev->dev,
+					"match and instantiation failed\n");
+			if (matched)
+				break;
+		}
+	}
+
+	mutex_unlock(&hnae3_common_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(hnae3_register_ae_algo);
+
+/* hnae_ae_unregister - unregisters a HNAE AE engine
+ * @cdev: the device to unregister
+ */
+void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
+{
+	const struct pci_device_id *id;
+	struct hnae3_ae_dev *ae_dev;
+	struct hnae3_client *client;
+	bool matched;
+
+	mutex_lock(&hnae3_common_lock);
+	/* Check if there are matched ae_dev */
+	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
+		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
+		if (!id)
+			continue;
+
+		/* check the client list for the match with this ae_dev type and
+		 * un-initialize the figure out client instance
+		 */
+		list_for_each_entry(client, &hnae3_client_list, node) {
+			hnae3_match_n_instantiate(client, ae_dev, false,
+						  &matched);
+			if (matched)
+				break;
+		}
+
+		ae_algo->ops->uninit_ae_dev(ae_dev);
+		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
+	}
+
+	list_del(&ae_algo->node);
+	mutex_unlock(&hnae3_common_lock);
+}
+EXPORT_SYMBOL(hnae3_unregister_ae_algo);
+
+/* hnae_ae_register - register a AE engine to hnae framework
+ * @hdev: the hnae ae engine device
+ * @owner:  the module who provides this dev
+ * NOTE: the duplicated name will not be checked
+ */
+int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
+{
+	const struct pci_device_id *id;
+	struct hnae3_ae_algo *ae_algo;
+	struct hnae3_client *client;
+	bool matched;
+	int ret = 0;
+
+	mutex_lock(&hnae3_common_lock);
+	list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
+
+	/* Check if there are matched ae_algo */
+	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
+		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
+		if (!id)
+			continue;
+
+		ae_dev->ops = ae_algo->ops;
+
+		if (!ae_dev->ops) {
+			dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
+			goto out_err;
+		}
+
+		/* ae_dev init should set flag */
+		ret = ae_dev->ops->init_ae_dev(ae_dev);
+		if (ret) {
+			dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
+			goto out_err;
+		}
+
+		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
+		break;
+	}
+
+	/* check the client list for the match with this ae_dev type and
+	 * initialize the figure out client instance
+	 */
+	list_for_each_entry(client, &hnae3_client_list, node) {
+		ret = hnae3_match_n_instantiate(client, ae_dev, true,
+						&matched);
+		if (ret)
+			dev_err(&ae_dev->pdev->dev,
+				"match and instantiation failed\n");
+		if (matched)
+			break;
+	}
+
+out_err:
+	mutex_unlock(&hnae3_common_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(hnae3_register_ae_dev);
+
+/* hnae_ae_unregister - unregisters a HNAE AE engine
+ * @cdev: the device to unregister
+ */
+void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
+{
+	const struct pci_device_id *id;
+	struct hnae3_ae_algo *ae_algo;
+	struct hnae3_client *client;
+	bool matched;
+
+	mutex_lock(&hnae3_common_lock);
+	/* Check if there are matched ae_algo */
+	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
+		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
+		if (!id)
+			continue;
+
+		list_for_each_entry(client, &hnae3_client_list, node) {
+			hnae3_match_n_instantiate(client, ae_dev, false,
+						  &matched);
+			if (matched)
+				break;
+		}
+
+		ae_algo->ops->uninit_ae_dev(ae_dev);
+		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
+	}
+
+	list_del(&ae_dev->node);
+	mutex_unlock(&hnae3_common_lock);
+}
+EXPORT_SYMBOL(hnae3_unregister_ae_dev);
+
+MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
new file mode 100644
index 0000000..c2f6411
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2016-2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __HNAE_H
+#define __HNAE_H
+
+/* Names used in this framework:
+ *      ae handle (handle):
+ *        a set of queues provided by AE
+ *      ring buffer queue (rbq):
+ *        the channel between upper layer and the AE, can do tx and rx
+ *      ring:
+ *        a tx or rx channel within a rbq
+ *      ring description (desc):
+ *        an element in the ring with packet information
+ *      buffer:
+ *        a memory region referred by desc with the full packet payload
+ *
+ * "num" means a static number set as a parameter, "count" mean a dynamic
+ *   number set while running
+ * "cb" means control block
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+/* Device IDs */
+#define HNAE3_DEV_ID_GE				0xA220
+#define HNAE3_DEV_ID_25GE			0xA221
+#define HNAE3_DEV_ID_25GE_RDMA			0xA222
+#define HNAE3_DEV_ID_25GE_RDMA_MACSEC		0xA223
+#define HNAE3_DEV_ID_50GE_RDMA			0xA224
+#define HNAE3_DEV_ID_50GE_RDMA_MACSEC		0xA225
+#define HNAE3_DEV_ID_100G_RDMA_MACSEC		0xA226
+#define HNAE3_DEV_ID_100G_VF			0xA22E
+#define HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF	0xA22F
+
+#define HNAE3_CLASS_NAME_SIZE 16
+
+#define HNAE3_DEV_INITED_B			0x0
+#define HNAE_DEV_SUPPORT_ROCE_B			0x1
+
+#define ring_ptr_move_fw(ring, p) \
+	((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
+#define ring_ptr_move_bw(ring, p) \
+	((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
+
+enum hns_desc_type {
+	DESC_TYPE_SKB,
+	DESC_TYPE_PAGE,
+};
+
+struct hnae3_handle;
+
+struct hnae3_queue {
+	void __iomem *io_base;
+	struct hnae3_ae_algo *ae_algo;
+	struct hnae3_handle *handle;
+	int tqp_index;	/* index in a handle */
+	u32 buf_size;	/* size for hnae_desc->addr, preset by AE */
+	u16 desc_num;	/* total number of desc */
+};
+
+/*hnae3 loop mode*/
+enum hnae3_loop {
+	HNAE3_MAC_INTER_LOOP_MAC,
+	HNAE3_MAC_INTER_LOOP_SERDES,
+	HNAE3_MAC_INTER_LOOP_PHY,
+	HNAE3_MAC_LOOP_NONE,
+};
+
+enum hnae3_client_type {
+	HNAE3_CLIENT_KNIC,
+	HNAE3_CLIENT_UNIC,
+	HNAE3_CLIENT_ROCE,
+};
+
+enum hnae3_dev_type {
+	HNAE3_DEV_KNIC,
+	HNAE3_DEV_UNIC,
+};
+
+/* mac media type */
+enum hnae3_media_type {
+	HNAE3_MEDIA_TYPE_UNKNOWN,
+	HNAE3_MEDIA_TYPE_FIBER,
+	HNAE3_MEDIA_TYPE_COPPER,
+	HNAE3_MEDIA_TYPE_BACKPLANE,
+};
+
+struct hnae3_vector_info {
+	u8 __iomem *io_addr;
+	int vector;
+};
+
+#define HNAE3_RING_TYPE_B 0
+#define HNAE3_RING_TYPE_TX 0
+#define HNAE3_RING_TYPE_RX 1
+
+struct hnae3_ring_chain_node {
+	struct hnae3_ring_chain_node *next;
+	u32 tqp_index;
+	u32 flag;
+};
+
+#define HNAE3_IS_TX_RING(node) \
+	(((node)->flag & (1 << HNAE3_RING_TYPE_B)) == HNAE3_RING_TYPE_TX)
+
+struct hnae3_client_ops {
+	int (*init_instance)(struct hnae3_handle *handle);
+	void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
+	void (*link_status_change)(struct hnae3_handle *handle, bool state);
+};
+
+#define HNAE3_CLIENT_NAME_LENGTH 16
+struct hnae3_client {
+	char name[HNAE3_CLIENT_NAME_LENGTH];
+	u16 version;
+	unsigned long state;
+	enum hnae3_client_type type;
+	const struct hnae3_client_ops *ops;
+	struct list_head node;
+};
+
+struct hnae3_ae_dev {
+	struct pci_dev *pdev;
+	const struct hnae3_ae_ops *ops;
+	struct list_head node;
+	u32 flag;
+	enum hnae3_dev_type dev_type;
+	void *priv;
+};
+
+/* This struct defines the operation on the handle.
+ *
+ * init_ae_dev(): (mandatory)
+ *   Get PF configure from pci_dev and initialize PF hardware
+ * uninit_ae_dev()
+ *   Disable PF device and release PF resource
+ * register_client
+ *   Register client to ae_dev
+ * unregister_client()
+ *   Unregister client from ae_dev
+ * start()
+ *   Enable the hardware
+ * stop()
+ *   Disable the hardware
+ * get_status()
+ *   Get the carrier state of the back channel of the handle, 1 for ok, 0 for
+ *   non-ok
+ * get_ksettings_an_result()
+ *   Get negotiation status,speed and duplex
+ * update_speed_duplex_h()
+ *   Update hardware speed and duplex
+ * get_media_type()
+ *   Get media type of MAC
+ * adjust_link()
+ *   Adjust link status
+ * set_loopback()
+ *   Set loopback
+ * set_promisc_mode
+ *   Set promisc mode
+ * set_mtu()
+ *   set mtu
+ * get_pauseparam()
+ *   get tx and rx of pause frame use
+ * set_pauseparam()
+ *   set tx and rx of pause frame use
+ * set_autoneg()
+ *   set auto autonegotiation of pause frame use
+ * get_autoneg()
+ *   get auto autonegotiation of pause frame use
+ * get_coalesce_usecs()
+ *   get usecs to delay a TX interrupt after a packet is sent
+ * get_rx_max_coalesced_frames()
+ *   get Maximum number of packets to be sent before a TX interrupt.
+ * set_coalesce_usecs()
+ *   set usecs to delay a TX interrupt after a packet is sent
+ * set_coalesce_frames()
+ *   set Maximum number of packets to be sent before a TX interrupt.
+ * get_mac_addr()
+ *   get mac address
+ * set_mac_addr()
+ *   set mac address
+ * add_uc_addr
+ *   Add unicast addr to mac table
+ * rm_uc_addr
+ *   Remove unicast addr from mac table
+ * set_mc_addr()
+ *   Set multicast address
+ * add_mc_addr
+ *   Add multicast address to mac table
+ * rm_mc_addr
+ *   Remove multicast address from mac table
+ * update_stats()
+ *   Update Old network device statistics
+ * get_ethtool_stats()
+ *   Get ethtool network device statistics
+ * get_strings()
+ *   Get a set of strings that describe the requested objects
+ * get_sset_count()
+ *   Get number of strings that @get_strings will write
+ * update_led_status()
+ *   Update the led status
+ * set_led_id()
+ *   Set led id
+ * get_regs()
+ *   Get regs dump
+ * get_regs_len()
+ *   Get the len of the regs dump
+ * get_rss_key_size()
+ *   Get rss key size
+ * get_rss_indir_size()
+ *   Get rss indirection table size
+ * get_rss()
+ *   Get rss table
+ * set_rss()
+ *   Set rss table
+ * get_tc_size()
+ *   Get tc size of handle
+ * get_vector()
+ *   Get vector number and vector information
+ * map_ring_to_vector()
+ *   Map rings to vector
+ * unmap_ring_from_vector()
+ *   Unmap rings from vector
+ * add_tunnel_udp()
+ *   Add tunnel information to hardware
+ * del_tunnel_udp()
+ *   Delete tunnel information from hardware
+ * reset_queue()
+ *   Reset queue
+ * get_fw_version()
+ *   Get firmware version
+ * get_mdix_mode()
+ *   Get media typr of phy
+ * set_vlan_filter()
+ *   Set vlan filter config of Ports
+ * set_vf_vlan_filter()
+ *   Set vlan filter config of vf
+ */
+struct hnae3_ae_ops {
+	int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
+	void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);
+
+	int (*init_client_instance)(struct hnae3_client *client,
+				    struct hnae3_ae_dev *ae_dev);
+	void (*uninit_client_instance)(struct hnae3_client *client,
+				       struct hnae3_ae_dev *ae_dev);
+	int (*start)(struct hnae3_handle *handle);
+	void (*stop)(struct hnae3_handle *handle);
+	int (*get_status)(struct hnae3_handle *handle);
+	void (*get_ksettings_an_result)(struct hnae3_handle *handle,
+					u8 *auto_neg, u32 *speed, u8 *duplex);
+
+	int (*update_speed_duplex_h)(struct hnae3_handle *handle);
+	int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int speed,
+				   u8 duplex);
+
+	void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type);
+	void (*adjust_link)(struct hnae3_handle *handle, int speed, int duplex);
+	int (*set_loopback)(struct hnae3_handle *handle,
+			    enum hnae3_loop loop_mode, bool en);
+
+	void (*set_promisc_mode)(struct hnae3_handle *handle, u32 en);
+	int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
+
+	void (*get_pauseparam)(struct hnae3_handle *handle,
+			       u32 *auto_neg, u32 *rx_en, u32 *tx_en);
+	int (*set_pauseparam)(struct hnae3_handle *handle,
+			      u32 auto_neg, u32 rx_en, u32 tx_en);
+
+	int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
+	int (*get_autoneg)(struct hnae3_handle *handle);
+
+	void (*get_coalesce_usecs)(struct hnae3_handle *handle,
+				   u32 *tx_usecs, u32 *rx_usecs);
+	void (*get_rx_max_coalesced_frames)(struct hnae3_handle *handle,
+					    u32 *tx_frames, u32 *rx_frames);
+	int (*set_coalesce_usecs)(struct hnae3_handle *handle, u32 timeout);
+	int (*set_coalesce_frames)(struct hnae3_handle *handle,
+				   u32 coalesce_frames);
+	void (*get_coalesce_range)(struct hnae3_handle *handle,
+				   u32 *tx_frames_low, u32 *rx_frames_low,
+				   u32 *tx_frames_high, u32 *rx_frames_high,
+				   u32 *tx_usecs_low, u32 *rx_usecs_low,
+				   u32 *tx_usecs_high, u32 *rx_usecs_high);
+
+	void (*get_mac_addr)(struct hnae3_handle *handle, u8 *p);
+	int (*set_mac_addr)(struct hnae3_handle *handle, void *p);
+	int (*add_uc_addr)(struct hnae3_handle *handle,
+			   const unsigned char *addr);
+	int (*rm_uc_addr)(struct hnae3_handle *handle,
+			  const unsigned char *addr);
+	int (*set_mc_addr)(struct hnae3_handle *handle, void *addr);
+	int (*add_mc_addr)(struct hnae3_handle *handle,
+			   const unsigned char *addr);
+	int (*rm_mc_addr)(struct hnae3_handle *handle,
+			  const unsigned char *addr);
+
+	void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
+	void (*update_stats)(struct hnae3_handle *handle,
+			     struct net_device_stats *net_stats);
+	void (*get_stats)(struct hnae3_handle *handle, u64 *data);
+
+	void (*get_strings)(struct hnae3_handle *handle,
+			    u32 stringset, u8 *data);
+	int (*get_sset_count)(struct hnae3_handle *handle, int stringset);
+
+	void (*get_regs)(struct hnae3_handle *handle, void *data);
+	int (*get_regs_len)(struct hnae3_handle *handle);
+
+	u32 (*get_rss_key_size)(struct hnae3_handle *handle);
+	u32 (*get_rss_indir_size)(struct hnae3_handle *handle);
+	int (*get_rss)(struct hnae3_handle *handle, u32 *indir, u8 *key,
+		       u8 *hfunc);
+	int (*set_rss)(struct hnae3_handle *handle, const u32 *indir,
+		       const u8 *key, const u8 hfunc);
+
+	int (*get_tc_size)(struct hnae3_handle *handle);
+
+	int (*get_vector)(struct hnae3_handle *handle, u16 vector_num,
+			  struct hnae3_vector_info *vector_info);
+	int (*map_ring_to_vector)(struct hnae3_handle *handle,
+				  int vector_num,
+				  struct hnae3_ring_chain_node *vr_chain);
+	int (*unmap_ring_from_vector)(struct hnae3_handle *handle,
+				      int vector_num,
+				      struct hnae3_ring_chain_node *vr_chain);
+
+	int (*add_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
+	int (*del_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
+
+	void (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
+	u32 (*get_fw_version)(struct hnae3_handle *handle);
+	void (*get_mdix_mode)(struct hnae3_handle *handle,
+			      u8 *tp_mdix_ctrl, u8 *tp_mdix);
+
+	int (*set_vlan_filter)(struct hnae3_handle *handle, __be16 proto,
+			       u16 vlan_id, bool is_kill);
+	int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
+				  u16 vlan, u8 qos, __be16 proto);
+};
+
+struct hnae3_ae_algo {
+	const struct hnae3_ae_ops *ops;
+	struct list_head node;
+	char name[HNAE3_CLASS_NAME_SIZE];
+	const struct pci_device_id *pdev_id_table;
+};
+
+#define HNAE3_INT_NAME_LEN        (IFNAMSIZ + 16)
+#define HNAE3_ITR_COUNTDOWN_START 100
+
+struct hnae3_tc_info {
+	u16	tqp_offset;	/* TQP offset from base TQP */
+	u16	tqp_count;	/* Total TQPs */
+	u8	up;		/* user priority */
+	u8	tc;		/* TC index */
+	bool	enable;		/* If this TC is enable or not */
+};
+
+#define HNAE3_MAX_TC		8
+struct hnae3_knic_private_info {
+	struct net_device *netdev; /* Set by KNIC client when init instance */
+	u16 rss_size;		   /* Allocated RSS queues */
+	u16 rx_buf_len;
+	u16 num_desc;
+
+	u8 num_tc;		   /* Total number of enabled TCs */
+	struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW TC */
+
+	u16 num_tqps;		  /* total number of TQPs in this handle */
+	struct hnae3_queue **tqp;  /* array base of all TQPs in this instance */
+};
+
+struct hnae3_roce_private_info {
+	struct net_device *netdev;
+	void __iomem *roce_io_base;
+	int base_vector;
+	int num_vectors;
+};
+
+struct hnae3_unic_private_info {
+	struct net_device *netdev;
+	u16 rx_buf_len;
+	u16 num_desc;
+	u16 num_tqps;	/* total number of tqps in this handle */
+	struct hnae3_queue **tqp;  /* array base of all TQPs of this instance */
+};
+
+#define HNAE3_SUPPORT_MAC_LOOPBACK    1
+#define HNAE3_SUPPORT_PHY_LOOPBACK    2
+#define HNAE3_SUPPORT_SERDES_LOOPBACK 4
+
+struct hnae3_handle {
+	struct hnae3_client *client;
+	struct pci_dev *pdev;
+	void *priv;
+	struct hnae3_ae_algo *ae_algo;  /* the class who provides this handle */
+	u64 flags; /* Indicate the capabilities for this handle*/
+
+	union {
+		struct net_device *netdev; /* first member */
+		struct hnae3_knic_private_info kinfo;
+		struct hnae3_unic_private_info uinfo;
+		struct hnae3_roce_private_info rinfo;
+	};
+
+	u32 numa_node_mask;	/* for multi-chip support */
+};
+
+#define hnae_set_field(origin, mask, shift, val) \
+	do { \
+		(origin) &= (~(mask)); \
+		(origin) |= ((val) << (shift)) & (mask); \
+	} while (0)
+#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift))
+
+#define hnae_set_bit(origin, shift, val) \
+	hnae_set_field((origin), (0x1 << (shift)), (shift), (val))
+#define hnae_get_bit(origin, shift) \
+	hnae_get_field((origin), (0x1 << (shift)), (shift))
+
+int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
+void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
+
+void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
+int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo);
+
+void hnae3_unregister_client(struct hnae3_client *client);
+int hnae3_register_client(struct hnae3_client *client);
+#endif
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1699493 — Re: [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework

FromLeon Romanovsky <leon@kernel.org>
Date2017-07-30 12:00 +0200
SubjectRe: [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework
Message-ID<u8TaW-752-9@gated-at.bofh.it>
In reply to#1699132

[Multipart message — attachments visible in raw view] — view raw

On Fri, Jul 28, 2017 at 11:26:46PM +0100, Salil Mehta wrote:
> This patch adds the support of the HNAE3 (Hisilicon Network
> Acceleration Engine 3) framework support to the HNS3 driver.
>
> Framework facilitates clients like ENET(HNS3 Ethernet Driver), RoCE
> and user-space Ethernet drivers (like ODP etc.) to register with HNAE3
> devices and their associated operations.
>
> Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
> Signed-off-by: lipeng <lipeng321@huawei.com>
> Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
> Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
> ---
> Patch V5: Addressed following comments
>   1. Leon Romanovsky:
>      https://lkml.org/lkml/2017/7/23/67
> Patch V4: Addressed following comments
>   1. Andrew Lunn:
>      https://lkml.org/lkml/2017/6/17/233
>      https://lkml.org/lkml/2017/6/18/105
>   2. Bo Yu:
>      https://lkml.org/lkml/2017/6/18/112
>   3. Stephen Hamminger:
>      https://lkml.org/lkml/2017/6/19/778
> Patch V3: Addressed below comments
>   1. Andrew Lunn:
>      https://lkml.org/lkml/2017/6/13/1025
> Patch V2: No change
> Patch V1: Initial Submit
> ---
>  drivers/net/ethernet/hisilicon/hns3/hnae3.c | 319 ++++++++++++++++++++
>  drivers/net/ethernet/hisilicon/hns3/hnae3.h | 444 ++++++++++++++++++++++++++++
>  2 files changed, 763 insertions(+)
>  create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.c
>  create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.h
>
> diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> new file mode 100644
> index 0000000..d28b69d
> --- /dev/null
> +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> @@ -0,0 +1,319 @@
> +/*
> + * Copyright (c) 2016-2017 Hisilicon Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +#include "hnae3.h"
> +
> +static LIST_HEAD(hnae3_ae_algo_list);
> +static LIST_HEAD(hnae3_client_list);
> +static LIST_HEAD(hnae3_ae_dev_list);
> +
> +/* we are keeping things simple and using single lock for all the
> + * list. This is a non-critical code so other updations, if happen
> + * in parallel, can wait.
> + */
> +static DEFINE_MUTEX(hnae3_common_lock);
> +
> +static bool hnae3_client_match(enum hnae3_client_type client_type,
> +			       enum hnae3_dev_type dev_type)
> +{
> +	if (dev_type == HNAE3_DEV_KNIC) {
> +		switch (client_type) {
> +		case HNAE3_CLIENT_KNIC:
> +		case HNAE3_CLIENT_ROCE:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	} else if (dev_type == HNAE3_DEV_UNIC) {
> +		switch (client_type) {
> +		case HNAE3_CLIENT_UNIC:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	} else {
> +		return false;
> +	}
> +}

Slightly compact version:

static bool hnae3_client_match(enum hnae3_client_type client_type,
			       enum hnae3_dev_type dev_type)
{
	if (dev_type == HNAE3_DEV_KNIC &&
	    client_type == HNAE3_CLIENT_KNIC || client_type == HNAE3_CLIENT_ROCE)
		return true;
	if (dev_type == HNAE3_DEV_UNIC && client_type == HNAE3_CLIENT_UNIC)
		return true;
	return false;
}


> +
> +static int hnae3_match_n_instantiate(struct hnae3_client *client,
> +				     struct hnae3_ae_dev *ae_dev,
> +				     bool is_reg, bool *matched)
> +{
> +	int ret;
> +
> +	*matched = false;
> +
> +	/* check if this client matches the type of ae_dev */
> +	if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
> +	      hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
> +		return 0;
> +	}
> +	/* there is a match of client and dev */
> +	*matched = true;
> +
> +	if (!(ae_dev->ops && ae_dev->ops->init_client_instance &&
> +	      ae_dev->ops->uninit_client_instance)) {
> +		dev_err(&ae_dev->pdev->dev,
> +			"ae_dev or client init/uninit ops are null\n");
> +		return -EOPNOTSUPP;
> +	}

You should check it during registration phase, IMHO in other places it is
safe to assume that you have init/uninit functions.

> +
> +	/* now, (un-)instantiate client by calling lower layer */
> +	if (is_reg) {
> +		ret = ae_dev->ops->init_client_instance(client, ae_dev);
> +		if (ret)
> +			dev_err(&ae_dev->pdev->dev,
> +				"fail to instantiate client\n");
> +		return ret;
> +	}
> +
> +	ae_dev->ops->uninit_client_instance(client, ae_dev);
> +	return 0;
> +}
> +
> +int hnae3_register_client(struct hnae3_client *client)
> +{
> +	struct hnae3_client *client_tmp;
> +	struct hnae3_ae_dev *ae_dev;
> +	bool matched;
> +	int ret = 0;
> +
> +	mutex_lock(&hnae3_common_lock);
> +	/* one system should only have one client for every type */
> +	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
> +		if (client_tmp->type == client->type)
> +			goto exit;
> +	}
> +
> +	list_add_tail(&client->node, &hnae3_client_list);
> +
> +	/* initialize the client on every matched port */
> +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> +		/* if the client could not be initialized on current port, for
> +		 * any error reasons, move on to next available port
> +		 */
> +		ret = hnae3_match_n_instantiate(client, ae_dev, true, &matched);
> +		if (ret)
> +			dev_err(&ae_dev->pdev->dev,
> +				"match and instantiation failed for port\n");
> +	}
> +
> +exit:
> +	mutex_unlock(&hnae3_common_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(hnae3_register_client);
> +
> +void hnae3_unregister_client(struct hnae3_client *client)
> +{
> +	struct hnae3_ae_dev *ae_dev;
> +	bool matched;
> +
> +	mutex_lock(&hnae3_common_lock);
> +	/* un-initialize the client on every matched port */
> +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> +		hnae3_match_n_instantiate(client, ae_dev, false, &matched);
> +	}
> +
> +	list_del(&client->node);
> +	mutex_unlock(&hnae3_common_lock);
> +}
> +EXPORT_SYMBOL(hnae3_unregister_client);
> +
> +/* hnae_ae_register - register a AE engine to hnae framework
> + * @hdev: the hnae ae engine device
> + * @owner:  the module who provides this dev
> + * NOTE: the duplicated name will not be checked
> + */
> +int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
> +{
> +	const struct pci_device_id *id;
> +	struct hnae3_ae_dev *ae_dev;
> +	struct hnae3_client *client;
> +	bool matched;
> +	int ret = 0;
> +
> +	mutex_lock(&hnae3_common_lock);
> +
> +	list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
> +
> +	/* Check if this algo/ops matches the list of ae_devs */
> +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> +		if (!id)
> +			continue;
> +
> +		/* ae_dev init should set flag */
> +		ae_dev->ops = ae_algo->ops;
> +		ret = ae_algo->ops->init_ae_dev(ae_dev);
> +		if (ret) {
> +			dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
> +			continue;
> +		}
> +
> +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
> +
> +		/* check the client list for the match with this ae_dev type and
> +		 * initialize the figure out client instance
> +		 */
> +		list_for_each_entry(client, &hnae3_client_list, node) {
> +			ret = hnae3_match_n_instantiate(client, ae_dev, true,
> +							&matched);
> +			if (ret)
> +				dev_err(&ae_dev->pdev->dev,
> +					"match and instantiation failed\n");
> +			if (matched)
> +				break;
> +		}
> +	}
> +
> +	mutex_unlock(&hnae3_common_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(hnae3_register_ae_algo);
> +
> +/* hnae_ae_unregister - unregisters a HNAE AE engine
> + * @cdev: the device to unregister
> + */
> +void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
> +{
> +	const struct pci_device_id *id;
> +	struct hnae3_ae_dev *ae_dev;
> +	struct hnae3_client *client;
> +	bool matched;
> +
> +	mutex_lock(&hnae3_common_lock);
> +	/* Check if there are matched ae_dev */
> +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> +		if (!id)
> +			continue;
> +
> +		/* check the client list for the match with this ae_dev type and
> +		 * un-initialize the figure out client instance
> +		 */
> +		list_for_each_entry(client, &hnae3_client_list, node) {
> +			hnae3_match_n_instantiate(client, ae_dev, false,
> +						  &matched);
> +			if (matched)
> +				break;
> +		}
> +
> +		ae_algo->ops->uninit_ae_dev(ae_dev);
> +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
> +	}
> +
> +	list_del(&ae_algo->node);
> +	mutex_unlock(&hnae3_common_lock);
> +}
> +EXPORT_SYMBOL(hnae3_unregister_ae_algo);
> +
> +/* hnae_ae_register - register a AE engine to hnae framework
> + * @hdev: the hnae ae engine device
> + * @owner:  the module who provides this dev
> + * NOTE: the duplicated name will not be checked
> + */
> +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
> +{
> +	const struct pci_device_id *id;
> +	struct hnae3_ae_algo *ae_algo;
> +	struct hnae3_client *client;
> +	bool matched;
> +	int ret = 0;
> +
> +	mutex_lock(&hnae3_common_lock);
> +	list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
> +
> +	/* Check if there are matched ae_algo */
> +	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
> +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> +		if (!id)
> +			continue;
> +
> +		ae_dev->ops = ae_algo->ops;
> +
> +		if (!ae_dev->ops) {
> +			dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
> +			goto out_err;
> +		}
> +
> +		/* ae_dev init should set flag */
> +		ret = ae_dev->ops->init_ae_dev(ae_dev);
> +		if (ret) {
> +			dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
> +			goto out_err;
> +		}
> +
> +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
> +		break;
> +	}
> +
> +	/* check the client list for the match with this ae_dev type and
> +	 * initialize the figure out client instance
> +	 */
> +	list_for_each_entry(client, &hnae3_client_list, node) {
> +		ret = hnae3_match_n_instantiate(client, ae_dev, true,
> +						&matched);
> +		if (ret)
> +			dev_err(&ae_dev->pdev->dev,
> +				"match and instantiation failed\n");
> +		if (matched)
> +			break;
> +	}
> +
> +out_err:
> +	mutex_unlock(&hnae3_common_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(hnae3_register_ae_dev);
> +
> +/* hnae_ae_unregister - unregisters a HNAE AE engine
> + * @cdev: the device to unregister
> + */
> +void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
> +{
> +	const struct pci_device_id *id;
> +	struct hnae3_ae_algo *ae_algo;
> +	struct hnae3_client *client;
> +	bool matched;
> +
> +	mutex_lock(&hnae3_common_lock);
> +	/* Check if there are matched ae_algo */
> +	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
> +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> +		if (!id)
> +			continue;
> +
> +		list_for_each_entry(client, &hnae3_client_list, node) {
> +			hnae3_match_n_instantiate(client, ae_dev, false,
> +						  &matched);
> +			if (matched)
> +				break;
> +		}
> +
> +		ae_algo->ops->uninit_ae_dev(ae_dev);
> +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
> +	}
> +
> +	list_del(&ae_dev->node);
> +	mutex_unlock(&hnae3_common_lock);
> +}
> +EXPORT_SYMBOL(hnae3_unregister_ae_dev);
> +
> +MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
> diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> new file mode 100644
> index 0000000..c2f6411
> --- /dev/null
> +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> @@ -0,0 +1,444 @@
> +/*
> + * Copyright (c) 2016-2017 Hisilicon Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __HNAE_H
> +#define __HNAE_H
> +
> +/* Names used in this framework:
> + *      ae handle (handle):
> + *        a set of queues provided by AE
> + *      ring buffer queue (rbq):
> + *        the channel between upper layer and the AE, can do tx and rx
> + *      ring:
> + *        a tx or rx channel within a rbq
> + *      ring description (desc):
> + *        an element in the ring with packet information
> + *      buffer:
> + *        a memory region referred by desc with the full packet payload
> + *
> + * "num" means a static number set as a parameter, "count" mean a dynamic
> + *   number set while running
> + * "cb" means control block
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/pci.h>
> +#include <linux/types.h>
> +
> +/* Device IDs */
> +#define HNAE3_DEV_ID_GE				0xA220
> +#define HNAE3_DEV_ID_25GE			0xA221
> +#define HNAE3_DEV_ID_25GE_RDMA			0xA222
> +#define HNAE3_DEV_ID_25GE_RDMA_MACSEC		0xA223
> +#define HNAE3_DEV_ID_50GE_RDMA			0xA224
> +#define HNAE3_DEV_ID_50GE_RDMA_MACSEC		0xA225
> +#define HNAE3_DEV_ID_100G_RDMA_MACSEC		0xA226
> +#define HNAE3_DEV_ID_100G_VF			0xA22E
> +#define HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF	0xA22F
> +
> +#define HNAE3_CLASS_NAME_SIZE 16
> +
> +#define HNAE3_DEV_INITED_B			0x0
> +#define HNAE_DEV_SUPPORT_ROCE_B			0x1
> +
> +#define ring_ptr_move_fw(ring, p) \
> +	((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
> +#define ring_ptr_move_bw(ring, p) \
> +	((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
> +
> +enum hns_desc_type {
> +	DESC_TYPE_SKB,
> +	DESC_TYPE_PAGE,
> +};
> +
> +struct hnae3_handle;
> +
> +struct hnae3_queue {
> +	void __iomem *io_base;
> +	struct hnae3_ae_algo *ae_algo;
> +	struct hnae3_handle *handle;
> +	int tqp_index;	/* index in a handle */
> +	u32 buf_size;	/* size for hnae_desc->addr, preset by AE */
> +	u16 desc_num;	/* total number of desc */
> +};
> +
> +/*hnae3 loop mode*/
> +enum hnae3_loop {
> +	HNAE3_MAC_INTER_LOOP_MAC,
> +	HNAE3_MAC_INTER_LOOP_SERDES,
> +	HNAE3_MAC_INTER_LOOP_PHY,
> +	HNAE3_MAC_LOOP_NONE,
> +};
> +
> +enum hnae3_client_type {
> +	HNAE3_CLIENT_KNIC,
> +	HNAE3_CLIENT_UNIC,
> +	HNAE3_CLIENT_ROCE,
> +};
> +
> +enum hnae3_dev_type {
> +	HNAE3_DEV_KNIC,
> +	HNAE3_DEV_UNIC,
> +};
> +
> +/* mac media type */
> +enum hnae3_media_type {
> +	HNAE3_MEDIA_TYPE_UNKNOWN,
> +	HNAE3_MEDIA_TYPE_FIBER,
> +	HNAE3_MEDIA_TYPE_COPPER,
> +	HNAE3_MEDIA_TYPE_BACKPLANE,
> +};
> +
> +struct hnae3_vector_info {
> +	u8 __iomem *io_addr;
> +	int vector;
> +};
> +
> +#define HNAE3_RING_TYPE_B 0
> +#define HNAE3_RING_TYPE_TX 0
> +#define HNAE3_RING_TYPE_RX 1
> +
> +struct hnae3_ring_chain_node {
> +	struct hnae3_ring_chain_node *next;
> +	u32 tqp_index;
> +	u32 flag;
> +};
> +
> +#define HNAE3_IS_TX_RING(node) \
> +	(((node)->flag & (1 << HNAE3_RING_TYPE_B)) == HNAE3_RING_TYPE_TX)
> +
> +struct hnae3_client_ops {
> +	int (*init_instance)(struct hnae3_handle *handle);
> +	void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
> +	void (*link_status_change)(struct hnae3_handle *handle, bool state);
> +};
> +
> +#define HNAE3_CLIENT_NAME_LENGTH 16
> +struct hnae3_client {
> +	char name[HNAE3_CLIENT_NAME_LENGTH];
> +	u16 version;
> +	unsigned long state;
> +	enum hnae3_client_type type;
> +	const struct hnae3_client_ops *ops;
> +	struct list_head node;
> +};
> +
> +struct hnae3_ae_dev {
> +	struct pci_dev *pdev;
> +	const struct hnae3_ae_ops *ops;
> +	struct list_head node;
> +	u32 flag;
> +	enum hnae3_dev_type dev_type;
> +	void *priv;
> +};
> +
> +/* This struct defines the operation on the handle.
> + *
> + * init_ae_dev(): (mandatory)
> + *   Get PF configure from pci_dev and initialize PF hardware
> + * uninit_ae_dev()
> + *   Disable PF device and release PF resource
> + * register_client
> + *   Register client to ae_dev
> + * unregister_client()
> + *   Unregister client from ae_dev
> + * start()
> + *   Enable the hardware
> + * stop()
> + *   Disable the hardware
> + * get_status()
> + *   Get the carrier state of the back channel of the handle, 1 for ok, 0 for
> + *   non-ok
> + * get_ksettings_an_result()
> + *   Get negotiation status,speed and duplex
> + * update_speed_duplex_h()
> + *   Update hardware speed and duplex
> + * get_media_type()
> + *   Get media type of MAC
> + * adjust_link()
> + *   Adjust link status
> + * set_loopback()
> + *   Set loopback
> + * set_promisc_mode
> + *   Set promisc mode
> + * set_mtu()
> + *   set mtu
> + * get_pauseparam()
> + *   get tx and rx of pause frame use
> + * set_pauseparam()
> + *   set tx and rx of pause frame use
> + * set_autoneg()
> + *   set auto autonegotiation of pause frame use
> + * get_autoneg()
> + *   get auto autonegotiation of pause frame use
> + * get_coalesce_usecs()
> + *   get usecs to delay a TX interrupt after a packet is sent
> + * get_rx_max_coalesced_frames()
> + *   get Maximum number of packets to be sent before a TX interrupt.
> + * set_coalesce_usecs()
> + *   set usecs to delay a TX interrupt after a packet is sent
> + * set_coalesce_frames()
> + *   set Maximum number of packets to be sent before a TX interrupt.
> + * get_mac_addr()
> + *   get mac address
> + * set_mac_addr()
> + *   set mac address
> + * add_uc_addr
> + *   Add unicast addr to mac table
> + * rm_uc_addr
> + *   Remove unicast addr from mac table
> + * set_mc_addr()
> + *   Set multicast address
> + * add_mc_addr
> + *   Add multicast address to mac table
> + * rm_mc_addr
> + *   Remove multicast address from mac table
> + * update_stats()
> + *   Update Old network device statistics
> + * get_ethtool_stats()
> + *   Get ethtool network device statistics
> + * get_strings()
> + *   Get a set of strings that describe the requested objects
> + * get_sset_count()
> + *   Get number of strings that @get_strings will write
> + * update_led_status()
> + *   Update the led status
> + * set_led_id()
> + *   Set led id
> + * get_regs()
> + *   Get regs dump
> + * get_regs_len()
> + *   Get the len of the regs dump
> + * get_rss_key_size()
> + *   Get rss key size
> + * get_rss_indir_size()
> + *   Get rss indirection table size
> + * get_rss()
> + *   Get rss table
> + * set_rss()
> + *   Set rss table
> + * get_tc_size()
> + *   Get tc size of handle
> + * get_vector()
> + *   Get vector number and vector information
> + * map_ring_to_vector()
> + *   Map rings to vector
> + * unmap_ring_from_vector()
> + *   Unmap rings from vector
> + * add_tunnel_udp()
> + *   Add tunnel information to hardware
> + * del_tunnel_udp()
> + *   Delete tunnel information from hardware
> + * reset_queue()
> + *   Reset queue
> + * get_fw_version()
> + *   Get firmware version
> + * get_mdix_mode()
> + *   Get media typr of phy
> + * set_vlan_filter()
> + *   Set vlan filter config of Ports
> + * set_vf_vlan_filter()
> + *   Set vlan filter config of vf
> + */
> +struct hnae3_ae_ops {
> +	int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
> +	void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);
> +
> +	int (*init_client_instance)(struct hnae3_client *client,
> +				    struct hnae3_ae_dev *ae_dev);
> +	void (*uninit_client_instance)(struct hnae3_client *client,
> +				       struct hnae3_ae_dev *ae_dev);
> +	int (*start)(struct hnae3_handle *handle);
> +	void (*stop)(struct hnae3_handle *handle);
> +	int (*get_status)(struct hnae3_handle *handle);
> +	void (*get_ksettings_an_result)(struct hnae3_handle *handle,
> +					u8 *auto_neg, u32 *speed, u8 *duplex);
> +
> +	int (*update_speed_duplex_h)(struct hnae3_handle *handle);
> +	int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int speed,
> +				   u8 duplex);
> +
> +	void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type);
> +	void (*adjust_link)(struct hnae3_handle *handle, int speed, int duplex);
> +	int (*set_loopback)(struct hnae3_handle *handle,
> +			    enum hnae3_loop loop_mode, bool en);
> +
> +	void (*set_promisc_mode)(struct hnae3_handle *handle, u32 en);
> +	int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
> +
> +	void (*get_pauseparam)(struct hnae3_handle *handle,
> +			       u32 *auto_neg, u32 *rx_en, u32 *tx_en);
> +	int (*set_pauseparam)(struct hnae3_handle *handle,
> +			      u32 auto_neg, u32 rx_en, u32 tx_en);
> +
> +	int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
> +	int (*get_autoneg)(struct hnae3_handle *handle);
> +
> +	void (*get_coalesce_usecs)(struct hnae3_handle *handle,
> +				   u32 *tx_usecs, u32 *rx_usecs);
> +	void (*get_rx_max_coalesced_frames)(struct hnae3_handle *handle,
> +					    u32 *tx_frames, u32 *rx_frames);
> +	int (*set_coalesce_usecs)(struct hnae3_handle *handle, u32 timeout);
> +	int (*set_coalesce_frames)(struct hnae3_handle *handle,
> +				   u32 coalesce_frames);
> +	void (*get_coalesce_range)(struct hnae3_handle *handle,
> +				   u32 *tx_frames_low, u32 *rx_frames_low,
> +				   u32 *tx_frames_high, u32 *rx_frames_high,
> +				   u32 *tx_usecs_low, u32 *rx_usecs_low,
> +				   u32 *tx_usecs_high, u32 *rx_usecs_high);
> +
> +	void (*get_mac_addr)(struct hnae3_handle *handle, u8 *p);
> +	int (*set_mac_addr)(struct hnae3_handle *handle, void *p);
> +	int (*add_uc_addr)(struct hnae3_handle *handle,
> +			   const unsigned char *addr);
> +	int (*rm_uc_addr)(struct hnae3_handle *handle,
> +			  const unsigned char *addr);
> +	int (*set_mc_addr)(struct hnae3_handle *handle, void *addr);
> +	int (*add_mc_addr)(struct hnae3_handle *handle,
> +			   const unsigned char *addr);
> +	int (*rm_mc_addr)(struct hnae3_handle *handle,
> +			  const unsigned char *addr);
> +
> +	void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
> +	void (*update_stats)(struct hnae3_handle *handle,
> +			     struct net_device_stats *net_stats);
> +	void (*get_stats)(struct hnae3_handle *handle, u64 *data);
> +
> +	void (*get_strings)(struct hnae3_handle *handle,
> +			    u32 stringset, u8 *data);
> +	int (*get_sset_count)(struct hnae3_handle *handle, int stringset);
> +
> +	void (*get_regs)(struct hnae3_handle *handle, void *data);
> +	int (*get_regs_len)(struct hnae3_handle *handle);
> +
> +	u32 (*get_rss_key_size)(struct hnae3_handle *handle);
> +	u32 (*get_rss_indir_size)(struct hnae3_handle *handle);
> +	int (*get_rss)(struct hnae3_handle *handle, u32 *indir, u8 *key,
> +		       u8 *hfunc);
> +	int (*set_rss)(struct hnae3_handle *handle, const u32 *indir,
> +		       const u8 *key, const u8 hfunc);
> +
> +	int (*get_tc_size)(struct hnae3_handle *handle);
> +
> +	int (*get_vector)(struct hnae3_handle *handle, u16 vector_num,
> +			  struct hnae3_vector_info *vector_info);
> +	int (*map_ring_to_vector)(struct hnae3_handle *handle,
> +				  int vector_num,
> +				  struct hnae3_ring_chain_node *vr_chain);
> +	int (*unmap_ring_from_vector)(struct hnae3_handle *handle,
> +				      int vector_num,
> +				      struct hnae3_ring_chain_node *vr_chain);
> +
> +	int (*add_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
> +	int (*del_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
> +
> +	void (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
> +	u32 (*get_fw_version)(struct hnae3_handle *handle);
> +	void (*get_mdix_mode)(struct hnae3_handle *handle,
> +			      u8 *tp_mdix_ctrl, u8 *tp_mdix);
> +
> +	int (*set_vlan_filter)(struct hnae3_handle *handle, __be16 proto,
> +			       u16 vlan_id, bool is_kill);
> +	int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
> +				  u16 vlan, u8 qos, __be16 proto);
> +};
> +
> +struct hnae3_ae_algo {
> +	const struct hnae3_ae_ops *ops;
> +	struct list_head node;
> +	char name[HNAE3_CLASS_NAME_SIZE];
> +	const struct pci_device_id *pdev_id_table;
> +};
> +
> +#define HNAE3_INT_NAME_LEN        (IFNAMSIZ + 16)
> +#define HNAE3_ITR_COUNTDOWN_START 100
> +
> +struct hnae3_tc_info {
> +	u16	tqp_offset;	/* TQP offset from base TQP */
> +	u16	tqp_count;	/* Total TQPs */
> +	u8	up;		/* user priority */
> +	u8	tc;		/* TC index */
> +	bool	enable;		/* If this TC is enable or not */
> +};
> +
> +#define HNAE3_MAX_TC		8
> +struct hnae3_knic_private_info {
> +	struct net_device *netdev; /* Set by KNIC client when init instance */
> +	u16 rss_size;		   /* Allocated RSS queues */
> +	u16 rx_buf_len;
> +	u16 num_desc;
> +
> +	u8 num_tc;		   /* Total number of enabled TCs */
> +	struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW TC */
> +
> +	u16 num_tqps;		  /* total number of TQPs in this handle */
> +	struct hnae3_queue **tqp;  /* array base of all TQPs in this instance */
> +};
> +
> +struct hnae3_roce_private_info {
> +	struct net_device *netdev;
> +	void __iomem *roce_io_base;
> +	int base_vector;
> +	int num_vectors;
> +};
> +
> +struct hnae3_unic_private_info {
> +	struct net_device *netdev;
> +	u16 rx_buf_len;
> +	u16 num_desc;
> +	u16 num_tqps;	/* total number of tqps in this handle */
> +	struct hnae3_queue **tqp;  /* array base of all TQPs of this instance */
> +};
> +
> +#define HNAE3_SUPPORT_MAC_LOOPBACK    1
> +#define HNAE3_SUPPORT_PHY_LOOPBACK    2
> +#define HNAE3_SUPPORT_SERDES_LOOPBACK 4
> +
> +struct hnae3_handle {
> +	struct hnae3_client *client;
> +	struct pci_dev *pdev;
> +	void *priv;
> +	struct hnae3_ae_algo *ae_algo;  /* the class who provides this handle */
> +	u64 flags; /* Indicate the capabilities for this handle*/
> +
> +	union {
> +		struct net_device *netdev; /* first member */
> +		struct hnae3_knic_private_info kinfo;
> +		struct hnae3_unic_private_info uinfo;
> +		struct hnae3_roce_private_info rinfo;
> +	};
> +
> +	u32 numa_node_mask;	/* for multi-chip support */
> +};
> +
> +#define hnae_set_field(origin, mask, shift, val) \
> +	do { \
> +		(origin) &= (~(mask)); \
> +		(origin) |= ((val) << (shift)) & (mask); \
> +	} while (0)
> +#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift))
> +
> +#define hnae_set_bit(origin, shift, val) \
> +	hnae_set_field((origin), (0x1 << (shift)), (shift), (val))
> +#define hnae_get_bit(origin, shift) \
> +	hnae_get_field((origin), (0x1 << (shift)), (shift))
> +
> +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
> +void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
> +
> +void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
> +int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo);
> +
> +void hnae3_unregister_client(struct hnae3_client *client);
> +int hnae3_register_client(struct hnae3_client *client);
> +#endif
> --
> 2.7.4
>
>

[toc] | [prev] | [next] | [standalone]


#1699841 — RE: [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-31 11:10 +0200
SubjectRE: [PATCH V5 net-next 2/8] net: hns3: Add support of the HNAE3 framework
Message-ID<u9eS6-4nS-13@gated-at.bofh.it>
In reply to#1699493
Hi Leon,

> -----Original Message-----
> From: linux-rdma-owner@vger.kernel.org [mailto:linux-rdma-
> owner@vger.kernel.org] On Behalf Of Leon Romanovsky
> Sent: Sunday, July 30, 2017 10:59 AM
> To: Salil Mehta
> Cc: davem@davemloft.net; Zhuangyuzeng (Yisen); huangdaode; lipeng (Y);
> mehta.salil.lnk@gmail.com; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Linuxarm
> Subject: Re: [PATCH V5 net-next 2/8] net: hns3: Add support of the
> HNAE3 framework
> 
> On Fri, Jul 28, 2017 at 11:26:46PM +0100, Salil Mehta wrote:
> > This patch adds the support of the HNAE3 (Hisilicon Network
> > Acceleration Engine 3) framework support to the HNS3 driver.
> >
> > Framework facilitates clients like ENET(HNS3 Ethernet Driver), RoCE
> > and user-space Ethernet drivers (like ODP etc.) to register with
> HNAE3
> > devices and their associated operations.
> >
> > Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
> > Signed-off-by: lipeng <lipeng321@huawei.com>
> > Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
> > Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
> > ---
> > Patch V5: Addressed following comments
> >   1. Leon Romanovsky:
> >      https://lkml.org/lkml/2017/7/23/67
> > Patch V4: Addressed following comments
> >   1. Andrew Lunn:
> >      https://lkml.org/lkml/2017/6/17/233
> >      https://lkml.org/lkml/2017/6/18/105
> >   2. Bo Yu:
> >      https://lkml.org/lkml/2017/6/18/112
> >   3. Stephen Hamminger:
> >      https://lkml.org/lkml/2017/6/19/778
> > Patch V3: Addressed below comments
> >   1. Andrew Lunn:
> >      https://lkml.org/lkml/2017/6/13/1025
> > Patch V2: No change
> > Patch V1: Initial Submit
> > ---
> >  drivers/net/ethernet/hisilicon/hns3/hnae3.c | 319
> ++++++++++++++++++++
> >  drivers/net/ethernet/hisilicon/hns3/hnae3.h | 444
> ++++++++++++++++++++++++++++
> >  2 files changed, 763 insertions(+)
> >  create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.c
> >  create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.h
> >
> > diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> > new file mode 100644
> > index 0000000..d28b69d
> > --- /dev/null
> > +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> > @@ -0,0 +1,319 @@
> > +/*
> > + * Copyright (c) 2016-2017 Hisilicon Limited.
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License as published
> by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/list.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +
> > +#include "hnae3.h"
> > +
> > +static LIST_HEAD(hnae3_ae_algo_list);
> > +static LIST_HEAD(hnae3_client_list);
> > +static LIST_HEAD(hnae3_ae_dev_list);
> > +
> > +/* we are keeping things simple and using single lock for all the
> > + * list. This is a non-critical code so other updations, if happen
> > + * in parallel, can wait.
> > + */
> > +static DEFINE_MUTEX(hnae3_common_lock);
> > +
> > +static bool hnae3_client_match(enum hnae3_client_type client_type,
> > +			       enum hnae3_dev_type dev_type)
> > +{
> > +	if (dev_type == HNAE3_DEV_KNIC) {
> > +		switch (client_type) {
> > +		case HNAE3_CLIENT_KNIC:
> > +		case HNAE3_CLIENT_ROCE:
> > +			return true;
> > +		default:
> > +			return false;
> > +		}
> > +	} else if (dev_type == HNAE3_DEV_UNIC) {
> > +		switch (client_type) {
> > +		case HNAE3_CLIENT_UNIC:
> > +			return true;
> > +		default:
> > +			return false;
> > +		}
> > +	} else {
> > +		return false;
> > +	}
> > +}
> 
> Slightly compact version:
> 
> static bool hnae3_client_match(enum hnae3_client_type client_type,
> 			       enum hnae3_dev_type dev_type)
> {
> 	if (dev_type == HNAE3_DEV_KNIC &&
> 	    client_type == HNAE3_CLIENT_KNIC || client_type ==
> HNAE3_CLIENT_ROCE)
> 		return true;
> 	if (dev_type == HNAE3_DEV_UNIC && client_type ==
> HNAE3_CLIENT_UNIC)
> 		return true;
> 	return false;
> }
Ok will change but I have felt usually with switch code looks more readable.

Thanks
> 
> 
> > +
> > +static int hnae3_match_n_instantiate(struct hnae3_client *client,
> > +				     struct hnae3_ae_dev *ae_dev,
> > +				     bool is_reg, bool *matched)
> > +{
> > +	int ret;
> > +
> > +	*matched = false;
> > +
> > +	/* check if this client matches the type of ae_dev */
> > +	if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
> > +	      hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
> > +		return 0;
> > +	}
> > +	/* there is a match of client and dev */
> > +	*matched = true;
> > +
> > +	if (!(ae_dev->ops && ae_dev->ops->init_client_instance &&
> > +	      ae_dev->ops->uninit_client_instance)) {
> > +		dev_err(&ae_dev->pdev->dev,
> > +			"ae_dev or client init/uninit ops are null\n");
> > +		return -EOPNOTSUPP;
> > +	}
> 
> You should check it during registration phase, IMHO in other places it
> is
> safe to assume that you have init/uninit functions.
Yes, makes sense. Will change this.

Thanks
> 
> > +
> > +	/* now, (un-)instantiate client by calling lower layer */
> > +	if (is_reg) {
> > +		ret = ae_dev->ops->init_client_instance(client, ae_dev);
> > +		if (ret)
> > +			dev_err(&ae_dev->pdev->dev,
> > +				"fail to instantiate client\n");
> > +		return ret;
> > +	}
> > +
> > +	ae_dev->ops->uninit_client_instance(client, ae_dev);
> > +	return 0;
> > +}
> > +
> > +int hnae3_register_client(struct hnae3_client *client)
> > +{
> > +	struct hnae3_client *client_tmp;
> > +	struct hnae3_ae_dev *ae_dev;
> > +	bool matched;
> > +	int ret = 0;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* one system should only have one client for every type */
> > +	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
> > +		if (client_tmp->type == client->type)
> > +			goto exit;
> > +	}
> > +
> > +	list_add_tail(&client->node, &hnae3_client_list);
> > +
> > +	/* initialize the client on every matched port */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		/* if the client could not be initialized on current port,
> for
> > +		 * any error reasons, move on to next available port
> > +		 */
> > +		ret = hnae3_match_n_instantiate(client, ae_dev, true,
> &matched);
> > +		if (ret)
> > +			dev_err(&ae_dev->pdev->dev,
> > +				"match and instantiation failed for port\n");
> > +	}
> > +
> > +exit:
> > +	mutex_unlock(&hnae3_common_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(hnae3_register_client);
> > +
> > +void hnae3_unregister_client(struct hnae3_client *client)
> > +{
> > +	struct hnae3_ae_dev *ae_dev;
> > +	bool matched;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* un-initialize the client on every matched port */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		hnae3_match_n_instantiate(client, ae_dev, false, &matched);
> > +	}
> > +
> > +	list_del(&client->node);
> > +	mutex_unlock(&hnae3_common_lock);
> > +}
> > +EXPORT_SYMBOL(hnae3_unregister_client);
> > +
> > +/* hnae_ae_register - register a AE engine to hnae framework
> > + * @hdev: the hnae ae engine device
> > + * @owner:  the module who provides this dev
> > + * NOTE: the duplicated name will not be checked
> > + */
> > +int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_dev *ae_dev;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +	int ret = 0;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +
> > +	list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
> > +
> > +	/* Check if this algo/ops matches the list of ae_devs */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		/* ae_dev init should set flag */
> > +		ae_dev->ops = ae_algo->ops;
> > +		ret = ae_algo->ops->init_ae_dev(ae_dev);
> > +		if (ret) {
> > +			dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
> > +			continue;
> > +		}
> > +
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
> > +
> > +		/* check the client list for the match with this ae_dev
> type and
> > +		 * initialize the figure out client instance
> > +		 */
> > +		list_for_each_entry(client, &hnae3_client_list, node) {
> > +			ret = hnae3_match_n_instantiate(client, ae_dev, true,
> > +							&matched);
> > +			if (ret)
> > +				dev_err(&ae_dev->pdev->dev,
> > +					"match and instantiation failed\n");
> > +			if (matched)
> > +				break;
> > +		}
> > +	}
> > +
> > +	mutex_unlock(&hnae3_common_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(hnae3_register_ae_algo);
> > +
> > +/* hnae_ae_unregister - unregisters a HNAE AE engine
> > + * @cdev: the device to unregister
> > + */
> > +void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_dev *ae_dev;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* Check if there are matched ae_dev */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		/* check the client list for the match with this ae_dev
> type and
> > +		 * un-initialize the figure out client instance
> > +		 */
> > +		list_for_each_entry(client, &hnae3_client_list, node) {
> > +			hnae3_match_n_instantiate(client, ae_dev, false,
> > +						  &matched);
> > +			if (matched)
> > +				break;
> > +		}
> > +
> > +		ae_algo->ops->uninit_ae_dev(ae_dev);
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
> > +	}
> > +
> > +	list_del(&ae_algo->node);
> > +	mutex_unlock(&hnae3_common_lock);
> > +}
> > +EXPORT_SYMBOL(hnae3_unregister_ae_algo);
> > +
> > +/* hnae_ae_register - register a AE engine to hnae framework
> > + * @hdev: the hnae ae engine device
> > + * @owner:  the module who provides this dev
> > + * NOTE: the duplicated name will not be checked
> > + */
> > +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_algo *ae_algo;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +	int ret = 0;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
> > +
> > +	/* Check if there are matched ae_algo */
> > +	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		ae_dev->ops = ae_algo->ops;
> > +
> > +		if (!ae_dev->ops) {
> > +			dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
> > +			goto out_err;
> > +		}
> > +
> > +		/* ae_dev init should set flag */
> > +		ret = ae_dev->ops->init_ae_dev(ae_dev);
> > +		if (ret) {
> > +			dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
> > +			goto out_err;
> > +		}
> > +
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
> > +		break;
> > +	}
> > +
> > +	/* check the client list for the match with this ae_dev type and
> > +	 * initialize the figure out client instance
> > +	 */
> > +	list_for_each_entry(client, &hnae3_client_list, node) {
> > +		ret = hnae3_match_n_instantiate(client, ae_dev, true,
> > +						&matched);
> > +		if (ret)
> > +			dev_err(&ae_dev->pdev->dev,
> > +				"match and instantiation failed\n");
> > +		if (matched)
> > +			break;
> > +	}
> > +
> > +out_err:
> > +	mutex_unlock(&hnae3_common_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(hnae3_register_ae_dev);
> > +
> > +/* hnae_ae_unregister - unregisters a HNAE AE engine
> > + * @cdev: the device to unregister
> > + */
> > +void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_algo *ae_algo;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* Check if there are matched ae_algo */
> > +	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		list_for_each_entry(client, &hnae3_client_list, node) {
> > +			hnae3_match_n_instantiate(client, ae_dev, false,
> > +						  &matched);
> > +			if (matched)
> > +				break;
> > +		}
> > +
> > +		ae_algo->ops->uninit_ae_dev(ae_dev);
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
> > +	}
> > +
> > +	list_del(&ae_dev->node);
> > +	mutex_unlock(&hnae3_common_lock);
> > +}
> > +EXPORT_SYMBOL(hnae3_unregister_ae_dev);
> > +
> > +MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
> > +MODULE_LICENSE("GPL");
> > +MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine)
> Framework");
> > diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> > new file mode 100644
> > index 0000000..c2f6411
> > --- /dev/null
> > +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> > @@ -0,0 +1,444 @@
> > +/*
> > + * Copyright (c) 2016-2017 Hisilicon Limited.
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License as published
> by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __HNAE_H
> > +#define __HNAE_H
> > +
> > +/* Names used in this framework:
> > + *      ae handle (handle):
> > + *        a set of queues provided by AE
> > + *      ring buffer queue (rbq):
> > + *        the channel between upper layer and the AE, can do tx and
> rx
> > + *      ring:
> > + *        a tx or rx channel within a rbq
> > + *      ring description (desc):
> > + *        an element in the ring with packet information
> > + *      buffer:
> > + *        a memory region referred by desc with the full packet
> payload
> > + *
> > + * "num" means a static number set as a parameter, "count" mean a
> dynamic
> > + *   number set while running
> > + * "cb" means control block
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/delay.h>
> > +#include <linux/device.h>
> > +#include <linux/module.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/pci.h>
> > +#include <linux/types.h>
> > +
> > +/* Device IDs */
> > +#define HNAE3_DEV_ID_GE				0xA220
> > +#define HNAE3_DEV_ID_25GE			0xA221
> > +#define HNAE3_DEV_ID_25GE_RDMA			0xA222
> > +#define HNAE3_DEV_ID_25GE_RDMA_MACSEC		0xA223
> > +#define HNAE3_DEV_ID_50GE_RDMA			0xA224
> > +#define HNAE3_DEV_ID_50GE_RDMA_MACSEC		0xA225
> > +#define HNAE3_DEV_ID_100G_RDMA_MACSEC		0xA226
> > +#define HNAE3_DEV_ID_100G_VF			0xA22E
> > +#define HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF	0xA22F
> > +
> > +#define HNAE3_CLASS_NAME_SIZE 16
> > +
> > +#define HNAE3_DEV_INITED_B			0x0
> > +#define HNAE_DEV_SUPPORT_ROCE_B			0x1
> > +
> > +#define ring_ptr_move_fw(ring, p) \
> > +	((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
> > +#define ring_ptr_move_bw(ring, p) \
> > +	((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)-
> >desc_num)
> > +
> > +enum hns_desc_type {
> > +	DESC_TYPE_SKB,
> > +	DESC_TYPE_PAGE,
> > +};
> > +
> > +struct hnae3_handle;
> > +
> > +struct hnae3_queue {
> > +	void __iomem *io_base;
> > +	struct hnae3_ae_algo *ae_algo;
> > +	struct hnae3_handle *handle;
> > +	int tqp_index;	/* index in a handle */
> > +	u32 buf_size;	/* size for hnae_desc->addr, preset by AE */
> > +	u16 desc_num;	/* total number of desc */
> > +};
> > +
> > +/*hnae3 loop mode*/
> > +enum hnae3_loop {
> > +	HNAE3_MAC_INTER_LOOP_MAC,
> > +	HNAE3_MAC_INTER_LOOP_SERDES,
> > +	HNAE3_MAC_INTER_LOOP_PHY,
> > +	HNAE3_MAC_LOOP_NONE,
> > +};
> > +
> > +enum hnae3_client_type {
> > +	HNAE3_CLIENT_KNIC,
> > +	HNAE3_CLIENT_UNIC,
> > +	HNAE3_CLIENT_ROCE,
> > +};
> > +
> > +enum hnae3_dev_type {
> > +	HNAE3_DEV_KNIC,
> > +	HNAE3_DEV_UNIC,
> > +};
> > +
> > +/* mac media type */
> > +enum hnae3_media_type {
> > +	HNAE3_MEDIA_TYPE_UNKNOWN,
> > +	HNAE3_MEDIA_TYPE_FIBER,
> > +	HNAE3_MEDIA_TYPE_COPPER,
> > +	HNAE3_MEDIA_TYPE_BACKPLANE,
> > +};
> > +
> > +struct hnae3_vector_info {
> > +	u8 __iomem *io_addr;
> > +	int vector;
> > +};
> > +
> > +#define HNAE3_RING_TYPE_B 0
> > +#define HNAE3_RING_TYPE_TX 0
> > +#define HNAE3_RING_TYPE_RX 1
> > +
> > +struct hnae3_ring_chain_node {
> > +	struct hnae3_ring_chain_node *next;
> > +	u32 tqp_index;
> > +	u32 flag;
> > +};
> > +
> > +#define HNAE3_IS_TX_RING(node) \
> > +	(((node)->flag & (1 << HNAE3_RING_TYPE_B)) == HNAE3_RING_TYPE_TX)
> > +
> > +struct hnae3_client_ops {
> > +	int (*init_instance)(struct hnae3_handle *handle);
> > +	void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
> > +	void (*link_status_change)(struct hnae3_handle *handle, bool
> state);
> > +};
> > +
> > +#define HNAE3_CLIENT_NAME_LENGTH 16
> > +struct hnae3_client {
> > +	char name[HNAE3_CLIENT_NAME_LENGTH];
> > +	u16 version;
> > +	unsigned long state;
> > +	enum hnae3_client_type type;
> > +	const struct hnae3_client_ops *ops;
> > +	struct list_head node;
> > +};
> > +
> > +struct hnae3_ae_dev {
> > +	struct pci_dev *pdev;
> > +	const struct hnae3_ae_ops *ops;
> > +	struct list_head node;
> > +	u32 flag;
> > +	enum hnae3_dev_type dev_type;
> > +	void *priv;
> > +};
> > +
> > +/* This struct defines the operation on the handle.
> > + *
> > + * init_ae_dev(): (mandatory)
> > + *   Get PF configure from pci_dev and initialize PF hardware
> > + * uninit_ae_dev()
> > + *   Disable PF device and release PF resource
> > + * register_client
> > + *   Register client to ae_dev
> > + * unregister_client()
> > + *   Unregister client from ae_dev
> > + * start()
> > + *   Enable the hardware
> > + * stop()
> > + *   Disable the hardware
> > + * get_status()
> > + *   Get the carrier state of the back channel of the handle, 1 for
> ok, 0 for
> > + *   non-ok
> > + * get_ksettings_an_result()
> > + *   Get negotiation status,speed and duplex
> > + * update_speed_duplex_h()
> > + *   Update hardware speed and duplex
> > + * get_media_type()
> > + *   Get media type of MAC
> > + * adjust_link()
> > + *   Adjust link status
> > + * set_loopback()
> > + *   Set loopback
> > + * set_promisc_mode
> > + *   Set promisc mode
> > + * set_mtu()
> > + *   set mtu
> > + * get_pauseparam()
> > + *   get tx and rx of pause frame use
> > + * set_pauseparam()
> > + *   set tx and rx of pause frame use
> > + * set_autoneg()
> > + *   set auto autonegotiation of pause frame use
> > + * get_autoneg()
> > + *   get auto autonegotiation of pause frame use
> > + * get_coalesce_usecs()
> > + *   get usecs to delay a TX interrupt after a packet is sent
> > + * get_rx_max_coalesced_frames()
> > + *   get Maximum number of packets to be sent before a TX interrupt.
> > + * set_coalesce_usecs()
> > + *   set usecs to delay a TX interrupt after a packet is sent
> > + * set_coalesce_frames()
> > + *   set Maximum number of packets to be sent before a TX interrupt.
> > + * get_mac_addr()
> > + *   get mac address
> > + * set_mac_addr()
> > + *   set mac address
> > + * add_uc_addr
> > + *   Add unicast addr to mac table
> > + * rm_uc_addr
> > + *   Remove unicast addr from mac table
> > + * set_mc_addr()
> > + *   Set multicast address
> > + * add_mc_addr
> > + *   Add multicast address to mac table
> > + * rm_mc_addr
> > + *   Remove multicast address from mac table
> > + * update_stats()
> > + *   Update Old network device statistics
> > + * get_ethtool_stats()
> > + *   Get ethtool network device statistics
> > + * get_strings()
> > + *   Get a set of strings that describe the requested objects
> > + * get_sset_count()
> > + *   Get number of strings that @get_strings will write
> > + * update_led_status()
> > + *   Update the led status
> > + * set_led_id()
> > + *   Set led id
> > + * get_regs()
> > + *   Get regs dump
> > + * get_regs_len()
> > + *   Get the len of the regs dump
> > + * get_rss_key_size()
> > + *   Get rss key size
> > + * get_rss_indir_size()
> > + *   Get rss indirection table size
> > + * get_rss()
> > + *   Get rss table
> > + * set_rss()
> > + *   Set rss table
> > + * get_tc_size()
> > + *   Get tc size of handle
> > + * get_vector()
> > + *   Get vector number and vector information
> > + * map_ring_to_vector()
> > + *   Map rings to vector
> > + * unmap_ring_from_vector()
> > + *   Unmap rings from vector
> > + * add_tunnel_udp()
> > + *   Add tunnel information to hardware
> > + * del_tunnel_udp()
> > + *   Delete tunnel information from hardware
> > + * reset_queue()
> > + *   Reset queue
> > + * get_fw_version()
> > + *   Get firmware version
> > + * get_mdix_mode()
> > + *   Get media typr of phy
> > + * set_vlan_filter()
> > + *   Set vlan filter config of Ports
> > + * set_vf_vlan_filter()
> > + *   Set vlan filter config of vf
> > + */
> > +struct hnae3_ae_ops {
> > +	int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
> > +	void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);
> > +
> > +	int (*init_client_instance)(struct hnae3_client *client,
> > +				    struct hnae3_ae_dev *ae_dev);
> > +	void (*uninit_client_instance)(struct hnae3_client *client,
> > +				       struct hnae3_ae_dev *ae_dev);
> > +	int (*start)(struct hnae3_handle *handle);
> > +	void (*stop)(struct hnae3_handle *handle);
> > +	int (*get_status)(struct hnae3_handle *handle);
> > +	void (*get_ksettings_an_result)(struct hnae3_handle *handle,
> > +					u8 *auto_neg, u32 *speed, u8 *duplex);
> > +
> > +	int (*update_speed_duplex_h)(struct hnae3_handle *handle);
> > +	int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int
> speed,
> > +				   u8 duplex);
> > +
> > +	void (*get_media_type)(struct hnae3_handle *handle, u8
> *media_type);
> > +	void (*adjust_link)(struct hnae3_handle *handle, int speed, int
> duplex);
> > +	int (*set_loopback)(struct hnae3_handle *handle,
> > +			    enum hnae3_loop loop_mode, bool en);
> > +
> > +	void (*set_promisc_mode)(struct hnae3_handle *handle, u32 en);
> > +	int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
> > +
> > +	void (*get_pauseparam)(struct hnae3_handle *handle,
> > +			       u32 *auto_neg, u32 *rx_en, u32 *tx_en);
> > +	int (*set_pauseparam)(struct hnae3_handle *handle,
> > +			      u32 auto_neg, u32 rx_en, u32 tx_en);
> > +
> > +	int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
> > +	int (*get_autoneg)(struct hnae3_handle *handle);
> > +
> > +	void (*get_coalesce_usecs)(struct hnae3_handle *handle,
> > +				   u32 *tx_usecs, u32 *rx_usecs);
> > +	void (*get_rx_max_coalesced_frames)(struct hnae3_handle *handle,
> > +					    u32 *tx_frames, u32 *rx_frames);
> > +	int (*set_coalesce_usecs)(struct hnae3_handle *handle, u32
> timeout);
> > +	int (*set_coalesce_frames)(struct hnae3_handle *handle,
> > +				   u32 coalesce_frames);
> > +	void (*get_coalesce_range)(struct hnae3_handle *handle,
> > +				   u32 *tx_frames_low, u32 *rx_frames_low,
> > +				   u32 *tx_frames_high, u32 *rx_frames_high,
> > +				   u32 *tx_usecs_low, u32 *rx_usecs_low,
> > +				   u32 *tx_usecs_high, u32 *rx_usecs_high);
> > +
> > +	void (*get_mac_addr)(struct hnae3_handle *handle, u8 *p);
> > +	int (*set_mac_addr)(struct hnae3_handle *handle, void *p);
> > +	int (*add_uc_addr)(struct hnae3_handle *handle,
> > +			   const unsigned char *addr);
> > +	int (*rm_uc_addr)(struct hnae3_handle *handle,
> > +			  const unsigned char *addr);
> > +	int (*set_mc_addr)(struct hnae3_handle *handle, void *addr);
> > +	int (*add_mc_addr)(struct hnae3_handle *handle,
> > +			   const unsigned char *addr);
> > +	int (*rm_mc_addr)(struct hnae3_handle *handle,
> > +			  const unsigned char *addr);
> > +
> > +	void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
> > +	void (*update_stats)(struct hnae3_handle *handle,
> > +			     struct net_device_stats *net_stats);
> > +	void (*get_stats)(struct hnae3_handle *handle, u64 *data);
> > +
> > +	void (*get_strings)(struct hnae3_handle *handle,
> > +			    u32 stringset, u8 *data);
> > +	int (*get_sset_count)(struct hnae3_handle *handle, int
> stringset);
> > +
> > +	void (*get_regs)(struct hnae3_handle *handle, void *data);
> > +	int (*get_regs_len)(struct hnae3_handle *handle);
> > +
> > +	u32 (*get_rss_key_size)(struct hnae3_handle *handle);
> > +	u32 (*get_rss_indir_size)(struct hnae3_handle *handle);
> > +	int (*get_rss)(struct hnae3_handle *handle, u32 *indir, u8 *key,
> > +		       u8 *hfunc);
> > +	int (*set_rss)(struct hnae3_handle *handle, const u32 *indir,
> > +		       const u8 *key, const u8 hfunc);
> > +
> > +	int (*get_tc_size)(struct hnae3_handle *handle);
> > +
> > +	int (*get_vector)(struct hnae3_handle *handle, u16 vector_num,
> > +			  struct hnae3_vector_info *vector_info);
> > +	int (*map_ring_to_vector)(struct hnae3_handle *handle,
> > +				  int vector_num,
> > +				  struct hnae3_ring_chain_node *vr_chain);
> > +	int (*unmap_ring_from_vector)(struct hnae3_handle *handle,
> > +				      int vector_num,
> > +				      struct hnae3_ring_chain_node *vr_chain);
> > +
> > +	int (*add_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
> > +	int (*del_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
> > +
> > +	void (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
> > +	u32 (*get_fw_version)(struct hnae3_handle *handle);
> > +	void (*get_mdix_mode)(struct hnae3_handle *handle,
> > +			      u8 *tp_mdix_ctrl, u8 *tp_mdix);
> > +
> > +	int (*set_vlan_filter)(struct hnae3_handle *handle, __be16 proto,
> > +			       u16 vlan_id, bool is_kill);
> > +	int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
> > +				  u16 vlan, u8 qos, __be16 proto);
> > +};
> > +
> > +struct hnae3_ae_algo {
> > +	const struct hnae3_ae_ops *ops;
> > +	struct list_head node;
> > +	char name[HNAE3_CLASS_NAME_SIZE];
> > +	const struct pci_device_id *pdev_id_table;
> > +};
> > +
> > +#define HNAE3_INT_NAME_LEN        (IFNAMSIZ + 16)
> > +#define HNAE3_ITR_COUNTDOWN_START 100
> > +
> > +struct hnae3_tc_info {
> > +	u16	tqp_offset;	/* TQP offset from base TQP */
> > +	u16	tqp_count;	/* Total TQPs */
> > +	u8	up;		/* user priority */
> > +	u8	tc;		/* TC index */
> > +	bool	enable;		/* If this TC is enable or not */
> > +};
> > +
> > +#define HNAE3_MAX_TC		8
> > +struct hnae3_knic_private_info {
> > +	struct net_device *netdev; /* Set by KNIC client when init
> instance */
> > +	u16 rss_size;		   /* Allocated RSS queues */
> > +	u16 rx_buf_len;
> > +	u16 num_desc;
> > +
> > +	u8 num_tc;		   /* Total number of enabled TCs */
> > +	struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW
> TC */
> > +
> > +	u16 num_tqps;		  /* total number of TQPs in this handle
> */
> > +	struct hnae3_queue **tqp;  /* array base of all TQPs in this
> instance */
> > +};
> > +
> > +struct hnae3_roce_private_info {
> > +	struct net_device *netdev;
> > +	void __iomem *roce_io_base;
> > +	int base_vector;
> > +	int num_vectors;
> > +};
> > +
> > +struct hnae3_unic_private_info {
> > +	struct net_device *netdev;
> > +	u16 rx_buf_len;
> > +	u16 num_desc;
> > +	u16 num_tqps;	/* total number of tqps in this handle */
> > +	struct hnae3_queue **tqp;  /* array base of all TQPs of this
> instance */
> > +};
> > +
> > +#define HNAE3_SUPPORT_MAC_LOOPBACK    1
> > +#define HNAE3_SUPPORT_PHY_LOOPBACK    2
> > +#define HNAE3_SUPPORT_SERDES_LOOPBACK 4
> > +
> > +struct hnae3_handle {
> > +	struct hnae3_client *client;
> > +	struct pci_dev *pdev;
> > +	void *priv;
> > +	struct hnae3_ae_algo *ae_algo;  /* the class who provides this
> handle */
> > +	u64 flags; /* Indicate the capabilities for this handle*/
> > +
> > +	union {
> > +		struct net_device *netdev; /* first member */
> > +		struct hnae3_knic_private_info kinfo;
> > +		struct hnae3_unic_private_info uinfo;
> > +		struct hnae3_roce_private_info rinfo;
> > +	};
> > +
> > +	u32 numa_node_mask;	/* for multi-chip support */
> > +};
> > +
> > +#define hnae_set_field(origin, mask, shift, val) \
> > +	do { \
> > +		(origin) &= (~(mask)); \
> > +		(origin) |= ((val) << (shift)) & (mask); \
> > +	} while (0)
> > +#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >>
> (shift))
> > +
> > +#define hnae_set_bit(origin, shift, val) \
> > +	hnae_set_field((origin), (0x1 << (shift)), (shift), (val))
> > +#define hnae_get_bit(origin, shift) \
> > +	hnae_get_field((origin), (0x1 << (shift)), (shift))
> > +
> > +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
> > +void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
> > +
> > +void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
> > +int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo);
> > +
> > +void hnae3_unregister_client(struct hnae3_client *client);
> > +int hnae3_register_client(struct hnae3_client *client);
> > +#endif
> > --
> > 2.7.4
> >
> >

[toc] | [prev] | [next] | [standalone]


#1699133 — [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 00:30 +0200
Subject[PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
Message-ID<u8lVE-1pM-19@gated-at.bofh.it>
In reply to#1699129
This patch adds the support of MDIO bus interface for HNS3 driver.
Code provides various interfaces to start and stop the PHY layer
and to read and write the MDIO bus or PHY.

Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
---
Patch V5: Addressed following comments:
 1. Florian Fainelli
    https://lkml.org/lkml/2017/7/23/91
Patch V4: Addressed following comments:
 1. Andrew Lunn
    https://lkml.org/lkml/2017/6/17/208
Patch V3: Addressed Below comments:
 1. Florian Fainelli
    https://lkml.org/lkml/2017/6/13/963
 2. Andrew Lunn
    https://lkml.org/lkml/2017/6/13/1039
Patch V2: Addressed below comments:
 1. Florian Fainelli
    https://lkml.org/lkml/2017/6/10/130
 2. Andrew Lunn
    https://lkml.org/lkml/2017/6/10/168
Patch V1: Initial Submit
---
 .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c    | 209 +++++++++++++++++++++
 1 file changed, 209 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
new file mode 100644
index 0000000..677a48c
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+
+enum hclge_mdio_c22_op_seq {
+	HCLGE_MDIO_C22_WRITE = 1,
+	HCLGE_MDIO_C22_READ = 2
+};
+
+#define HCLGE_MDIO_CTRL_START_B		0
+#define HCLGE_MDIO_CTRL_ST_S		1
+#define HCLGE_MDIO_CTRL_ST_M		(0x3 << HCLGE_MDIO_CTRL_ST_S)
+#define HCLGE_MDIO_CTRL_OP_S		3
+#define HCLGE_MDIO_CTRL_OP_M		(0x3 << HCLGE_MDIO_CTRL_OP_S)
+
+#define HCLGE_MDIO_PHYID_S		0
+#define HCLGE_MDIO_PHYID_M		(0x1f << HCLGE_MDIO_PHYID_S)
+
+#define HCLGE_MDIO_PHYREG_S		0
+#define HCLGE_MDIO_PHYREG_M		(0x1f << HCLGE_MDIO_PHYREG_S)
+
+#define HCLGE_MDIO_STA_B		0
+
+struct hclge_mdio_cfg_cmd {
+	u8 ctrl_bit;
+	u8 phyid;
+	u8 phyad;
+	u8 rsvd;
+	__le16 reserve;
+	__le16 data_wr;
+	__le16 data_rd;
+	__le16 sta;
+};
+
+static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum,
+			    u16 data)
+{
+	struct hclge_mdio_cfg_cmd *mdio_cmd;
+	struct hclge_dev *hdev = bus->priv;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false);
+
+	mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
+
+	hnae_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
+		       HCLGE_MDIO_PHYID_S, phyid);
+	hnae_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
+		       HCLGE_MDIO_PHYREG_S, regnum);
+
+	hnae_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
+	hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
+		       HCLGE_MDIO_CTRL_ST_S, 1);
+	hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
+		       HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_WRITE);
+
+	mdio_cmd->data_wr = cpu_to_le16(data);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"mdio write fail when sending cmd, status is %d.\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
+{
+	struct hclge_mdio_cfg_cmd *mdio_cmd;
+	struct hclge_dev *hdev = bus->priv;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true);
+
+	mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
+
+	hnae_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
+		       HCLGE_MDIO_PHYID_S, phyid);
+	hnae_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
+		       HCLGE_MDIO_PHYREG_S, regnum);
+
+	hnae_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
+	hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
+		       HCLGE_MDIO_CTRL_ST_S, 1);
+	hnae_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
+		       HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_READ);
+
+	/* Read out phy data */
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"mdio read fail when get data, status is %d.\n",
+			ret);
+		return ret;
+	}
+
+	if (hnae_get_bit(le16_to_cpu(mdio_cmd->sta), HCLGE_MDIO_STA_B)) {
+		dev_err(&hdev->pdev->dev, "mdio read data error\n");
+		return -EIO;
+	}
+
+	return le16_to_cpu(mdio_cmd->data_rd);
+}
+
+int hclge_mac_mdio_config(struct hclge_dev *hdev)
+{
+	struct hclge_mac *mac = &hdev->hw.mac;
+	struct phy_device *phydev;
+	struct mii_bus *mdio_bus;
+	int ret;
+
+	if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR)
+		return 0;
+
+	mdio_bus = devm_mdiobus_alloc(&hdev->pdev->dev);
+	if (!mdio_bus)
+		return -ENOMEM;
+
+	mdio_bus->name = "hisilicon MII bus";
+	mdio_bus->read = hclge_mdio_read;
+	mdio_bus->write = hclge_mdio_write;
+	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii",
+		 dev_name(&hdev->pdev->dev));
+
+	mdio_bus->parent = &hdev->pdev->dev;
+	mdio_bus->priv = hdev;
+	mdio_bus->phy_mask = ~(1 << mac->phy_addr);
+	ret = mdiobus_register(mdio_bus);
+	if (ret) {
+		dev_err(mdio_bus->parent,
+			"Failed to register MDIO bus ret = %#x\n", ret);
+		return ret;
+	}
+
+	phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
+	if (!phydev || IS_ERR(phydev)) {
+		dev_err(mdio_bus->parent, "Failed to get phy device\n");
+		mdiobus_unregister(mdio_bus);
+		return -EIO;
+	}
+
+	mac->phydev = phydev;
+	mac->mdio_bus = mdio_bus;
+
+	return 0;
+}
+
+static void hclge_mac_adjust_link(struct net_device *netdev)
+{
+	struct hnae3_handle *h = *((void **)netdev_priv(netdev));
+	struct hclge_vport *vport = hclge_get_vport(h);
+	struct hclge_dev *hdev = vport->back;
+	int duplex, speed;
+	int ret;
+
+	speed = netdev->phydev->speed;
+	duplex = netdev->phydev->duplex;
+
+	ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
+	if (ret)
+		dev_err(&hdev->pdev->dev, "adjust link fail.\n");
+}
+
+int hclge_mac_start_phy(struct hclge_dev *hdev)
+{
+	struct net_device *netdev = hdev->vport[0].nic.netdev;
+	struct phy_device *phydev = hdev->hw.mac.phydev;
+	int ret;
+
+	if (!phydev)
+		return 0;
+
+	ret = phy_connect_direct(netdev, phydev,
+				 hclge_mac_adjust_link,
+				 PHY_INTERFACE_MODE_SGMII);
+	if (ret) {
+		pr_info("phy_connect_direct err");
+		return ret;
+	}
+
+	phy_start(phydev);
+
+	return 0;
+}
+
+void hclge_mac_stop_phy(struct hclge_dev *hdev)
+{
+	struct net_device *netdev = hdev->vport[0].nic.netdev;
+	struct phy_device *phydev = netdev->phydev;
+
+	phy_stop(phydev);
+	phy_disconnect(phydev);
+}
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1699156 — Re: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC

FromAndrew Lunn <andrew@lunn.ch>
Date2017-07-29 01:30 +0200
SubjectRe: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
Message-ID<u8mRH-24E-9@gated-at.bofh.it>
In reply to#1699133
> +static void hclge_mac_adjust_link(struct net_device *netdev)
> +{
> +	struct hnae3_handle *h = *((void **)netdev_priv(netdev));
> +	struct hclge_vport *vport = hclge_get_vport(h);
> +	struct hclge_dev *hdev = vport->back;
> +	int duplex, speed;
> +	int ret;
> +
> +	speed = netdev->phydev->speed;
> +	duplex = netdev->phydev->duplex;
> +
> +	ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
> +	if (ret)
> +		dev_err(&hdev->pdev->dev, "adjust link fail.\n");

Here and hclge_mac_start_phy() you have a netdev, so you should be
using netdev_err()

> +}
> +
> +int hclge_mac_start_phy(struct hclge_dev *hdev)
> +{
> +	struct net_device *netdev = hdev->vport[0].nic.netdev;
> +	struct phy_device *phydev = hdev->hw.mac.phydev;
> +	int ret;
> +
> +	if (!phydev)
> +		return 0;
> +
> +	ret = phy_connect_direct(netdev, phydev,
> +				 hclge_mac_adjust_link,
> +				 PHY_INTERFACE_MODE_SGMII);
> +	if (ret) {
> +		pr_info("phy_connect_direct err");
> +		return ret;

netdev_err(). checkpatch probably gave you a warning about this?

> +	}
> +
> +	phy_start(phydev);
> +
> +	return 0;
> +}
> +
> +void hclge_mac_stop_phy(struct hclge_dev *hdev)
> +{
> +	struct net_device *netdev = hdev->vport[0].nic.netdev;
> +	struct phy_device *phydev = netdev->phydev;
> +
> +	phy_stop(phydev);
> +	phy_disconnect(phydev);
> +}

In hclge_mac_start_phy() you check for !phydev. Here you
unconditionally use phydev. Seems inconsistent.

	Andrew

[toc] | [prev] | [next] | [standalone]


#1699175 — RE: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 02:00 +0200
SubjectRE: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
Message-ID<u8nkK-2hg-17@gated-at.bofh.it>
In reply to#1699156
Hi Andrew,

> -----Original Message-----
> From: Andrew Lunn [mailto:andrew@lunn.ch]
> Sent: Saturday, July 29, 2017 12:24 AM
> To: Salil Mehta
> Cc: davem@davemloft.net; Zhuangyuzeng (Yisen); huangdaode; lipeng (Y);
> mehta.salil.lnk@gmail.com; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Linuxarm
> Subject: Re: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to
> HNS3 Ethernet driver for hip08 SoC
> 
> > +static void hclge_mac_adjust_link(struct net_device *netdev)
> > +{
> > +	struct hnae3_handle *h = *((void **)netdev_priv(netdev));
> > +	struct hclge_vport *vport = hclge_get_vport(h);
> > +	struct hclge_dev *hdev = vport->back;
> > +	int duplex, speed;
> > +	int ret;
> > +
> > +	speed = netdev->phydev->speed;
> > +	duplex = netdev->phydev->duplex;
> > +
> > +	ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
> > +	if (ret)
> > +		dev_err(&hdev->pdev->dev, "adjust link fail.\n");
> 
> Here and hclge_mac_start_phy() you have a netdev, so you should be
> using netdev_err()
Ok sure. Will replace in next patch.

> 
> > +}
> > +
> > +int hclge_mac_start_phy(struct hclge_dev *hdev)
> > +{
> > +	struct net_device *netdev = hdev->vport[0].nic.netdev;
> > +	struct phy_device *phydev = hdev->hw.mac.phydev;
> > +	int ret;
> > +
> > +	if (!phydev)
> > +		return 0;
> > +
> > +	ret = phy_connect_direct(netdev, phydev,
> > +				 hclge_mac_adjust_link,
> > +				 PHY_INTERFACE_MODE_SGMII);
> > +	if (ret) {
> > +		pr_info("phy_connect_direct err");
> > +		return ret;
> 
> netdev_err(). checkpatch probably gave you a warning about this?
No, it did not.

> 
> > +	}
> > +
> > +	phy_start(phydev);
> > +
> > +	return 0;
> > +}
> > +
> > +void hclge_mac_stop_phy(struct hclge_dev *hdev)
> > +{
> > +	struct net_device *netdev = hdev->vport[0].nic.netdev;
> > +	struct phy_device *phydev = netdev->phydev;
> > +
> > +	phy_stop(phydev);
> > +	phy_disconnect(phydev);
> > +}
> 
> In hclge_mac_start_phy() you check for !phydev. Here you
> unconditionally use phydev. Seems inconsistent.
Yes, I think NULL check for phy should be present here as well.

> 
> 	Andrew

[toc] | [prev] | [next] | [standalone]


#1699159 — Re: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC

FromAndrew Lunn <andrew@lunn.ch>
Date2017-07-29 01:30 +0200
SubjectRe: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
Message-ID<u8mRH-24E-13@gated-at.bofh.it>
In reply to#1699133
> +int hclge_mac_mdio_config(struct hclge_dev *hdev)
> +{
..

> +}
> +
> +int hclge_mac_start_phy(struct hclge_dev *hdev)
> +{

> +}
> +
> +void hclge_mac_stop_phy(struct hclge_dev *hdev)
> +{
> +}
> -- 

These are not static functions. So i would expect them to be in a
header file somewhere....

       Andrew

[toc] | [prev] | [next] | [standalone]


#1699171 — RE: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 02:00 +0200
SubjectRE: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC
Message-ID<u8nkJ-2hg-7@gated-at.bofh.it>
In reply to#1699159
Hi Andrew,

> -----Original Message-----
> From: linux-rdma-owner@vger.kernel.org [mailto:linux-rdma-
> owner@vger.kernel.org] On Behalf Of Andrew Lunn
> Sent: Saturday, July 29, 2017 12:29 AM
> To: Salil Mehta
> Cc: davem@davemloft.net; Zhuangyuzeng (Yisen); huangdaode; lipeng (Y);
> mehta.salil.lnk@gmail.com; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Linuxarm
> Subject: Re: [PATCH V5 net-next 6/8] net: hns3: Add MDIO support to
> HNS3 Ethernet driver for hip08 SoC
> 
> > +int hclge_mac_mdio_config(struct hclge_dev *hdev)
> > +{
> ..
> 
> > +}
> > +
> > +int hclge_mac_start_phy(struct hclge_dev *hdev)
> > +{
> 
> > +}
> > +
> > +void hclge_mac_stop_phy(struct hclge_dev *hdev)
> > +{
> > +}
> > --
> 
> These are not static functions. So i would expect them to be in a
> header file somewhere....
Sure.

> 
>        Andrew
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[toc] | [prev] | [next] | [standalone]


#1699143 — [PATCH V5 net-next 3/8] net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support

FromSalil Mehta <salil.mehta@huawei.com>
Date2017-07-29 00:40 +0200
Subject[PATCH V5 net-next 3/8] net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support
Message-ID<u8m5k-1tQ-33@gated-at.bofh.it>
In reply to#1699129
This patch adds the support of IMP (Integrated Management Processor)
command interface to the HNS3 driver.

Each PF/VF has support of CQP(Command Queue Pair) ring interface.
Each CQP consis of send queue CSQ and receive queue CRQ.
There are various commands a PF/VF may support, like for Flow Table
manipulation, Device management, Packet buffer allocation, Forwarding,
VLANs config, Tunneling/Overlays etc.

This patch contains code to initialize the command queue, manage the
command queue descriptors and Rx/Tx protocol with the command processor
in the form of various commands/results and acknowledgements.

Signed-off-by: Daode Huang <huangdaode@hisilicon.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: Yisen Zhuang <yisen.zhuang@huawei.com>
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 365 ++++++++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 741 +++++++++++++++++++++
 2 files changed, 1106 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
new file mode 100644
index 0000000..1e06f91
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/dma-direction.h>
+#include "hclge_cmd.h"
+#include "hnae3.h"
+#include "hclge_main.h"
+
+#define hclge_is_csq(ring) ((ring)->flag & HCLGE_TYPE_CSQ)
+#define hclge_ring_to_dma_dir(ring) (hclge_is_csq(ring) ? \
+	DMA_TO_DEVICE : DMA_FROM_DEVICE)
+#define cmq_ring_to_dev(ring)   (&(ring)->dev->pdev->dev)
+
+static int hclge_ring_space(struct hclge_cmq_ring *ring)
+{
+	int ntu = ring->next_to_use;
+	int ntc = ring->next_to_clean;
+	int used = (ntu - ntc + ring->desc_num) % ring->desc_num;
+
+	return ring->desc_num - used - 1;
+}
+
+static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
+{
+	int size  = ring->desc_num * sizeof(struct hclge_desc);
+
+	ring->desc = kzalloc(size, GFP_KERNEL);
+	if (!ring->desc)
+		return -ENOMEM;
+
+	ring->desc_dma_addr = dma_map_single(cmq_ring_to_dev(ring), ring->desc,
+					     size, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(cmq_ring_to_dev(ring), ring->desc_dma_addr)) {
+		ring->desc_dma_addr = 0;
+		kfree(ring->desc);
+		ring->desc = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void hclge_free_cmd_desc(struct hclge_cmq_ring *ring)
+{
+	dma_unmap_single(cmq_ring_to_dev(ring), ring->desc_dma_addr,
+			 ring->desc_num * sizeof(ring->desc[0]),
+			 DMA_BIDIRECTIONAL);
+
+	ring->desc_dma_addr = 0;
+	kfree(ring->desc);
+	ring->desc = NULL;
+}
+
+static int hclge_init_cmd_queue(struct hclge_dev *hdev, int ring_type)
+{
+	struct hclge_hw *hw = &hdev->hw;
+	struct hclge_cmq_ring *ring =
+		(ring_type == HCLGE_TYPE_CSQ) ? &hw->cmq.csq : &hw->cmq.crq;
+	int ret;
+
+	ring->flag = ring_type;
+	ring->dev = hdev;
+
+	ret = hclge_alloc_cmd_desc(ring);
+	if (ret) {
+		dev_err(&hdev->pdev->dev, "descriptor %s alloc error %d\n",
+			(ring_type == HCLGE_TYPE_CSQ) ? "CSQ" : "CRQ", ret);
+		return ret;
+	}
+
+	ring->next_to_clean = 0;
+	ring->next_to_use = 0;
+
+	return 0;
+}
+
+void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read)
+{
+	desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
+	if (is_read)
+		desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
+	else
+		desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
+}
+
+void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
+				enum hclge_opcode_type opcode, bool is_read)
+{
+	memset((void *)desc, 0, sizeof(struct hclge_desc));
+	desc->opcode = cpu_to_le16(opcode);
+	desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
+
+	if (is_read)
+		desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
+	else
+		desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
+}
+
+static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
+{
+	dma_addr_t dma = ring->desc_dma_addr;
+	struct hclge_dev *hdev = ring->dev;
+	struct hclge_hw *hw = &hdev->hw;
+
+	if (ring->flag == HCLGE_TYPE_CSQ) {
+		hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG,
+				(u32)dma);
+		hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG,
+				(u32)((dma >> 31) >> 1));
+		hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG,
+				(ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S) |
+				HCLGE_NIC_CMQ_ENABLE);
+		hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0);
+		hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0);
+	} else {
+		hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_L_REG,
+				(u32)dma);
+		hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG,
+				(u32)((dma >> 31) >> 1));
+		hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG,
+				(ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S) |
+				HCLGE_NIC_CMQ_ENABLE);
+		hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
+		hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0);
+	}
+}
+
+static void hclge_cmd_init_regs(struct hclge_hw *hw)
+{
+	hclge_cmd_config_regs(&hw->cmq.csq);
+	hclge_cmd_config_regs(&hw->cmq.crq);
+}
+
+static int hclge_cmd_csq_clean(struct hclge_hw *hw)
+{
+	struct hclge_cmq_ring *csq = &hw->cmq.csq;
+	u16 ntc = csq->next_to_clean;
+	struct hclge_desc *desc;
+	int clean = 0;
+	u32 head;
+
+	desc = &csq->desc[ntc];
+	head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG);
+
+	while (head != ntc) {
+		memset(desc, 0, sizeof(*desc));
+		ntc++;
+		if (ntc == csq->desc_num)
+			ntc = 0;
+		desc = &csq->desc[ntc];
+		clean++;
+	}
+	csq->next_to_clean = ntc;
+
+	return clean;
+}
+
+static int hclge_cmd_csq_done(struct hclge_hw *hw)
+{
+	u32 head = hclge_read_dev(hw, HCLGE_NIC_CSQ_HEAD_REG);
+	return head == hw->cmq.csq.next_to_use;
+}
+
+static bool hclge_is_special_opcode(u16 opcode)
+{
+	u16 spec_opcode[3] = {0x0030, 0x0031, 0x0032};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(spec_opcode); i++) {
+		if (spec_opcode[i] == opcode)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * hclge_cmd_send - send command to command queue
+ * @hw: pointer to the hw struct
+ * @desc: prefilled descriptor for describing the command
+ * @num : the number of descriptors to be sent
+ *
+ * This is the main send command for command queue, it
+ * sends the queue, cleans the queue, etc
+ **/
+int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
+{
+	struct hclge_dev *hdev = (struct hclge_dev *)hw->back;
+	struct hclge_desc *desc_to_use;
+	bool complete = false;
+	u32 timeout = 0;
+	int handle = 0;
+	int retval = 0;
+	u16 opcode, desc_ret;
+	int ntc;
+
+	spin_lock_bh(&hw->cmq.csq.lock);
+
+	if (num > hclge_ring_space(&hw->cmq.csq)) {
+		spin_unlock_bh(&hw->cmq.csq.lock);
+		return -EBUSY;
+	}
+
+	/**
+	 * Record the location of desc in the ring for this time
+	 * which will be use for hardware to write back
+	 */
+	ntc = hw->cmq.csq.next_to_use;
+	opcode = desc[0].opcode;
+	while (handle < num) {
+		desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
+		*desc_to_use = desc[handle];
+		(hw->cmq.csq.next_to_use)++;
+		if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num)
+			hw->cmq.csq.next_to_use = 0;
+		handle++;
+	}
+
+	/* Write to hardware */
+	hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, hw->cmq.csq.next_to_use);
+
+	/**
+	 * If the command is sync, wait for the firmware to write back,
+	 * if multi descriptors to be sent, use the first one to check
+	 */
+	if (HCLGE_SEND_SYNC(desc->flag)) {
+		do {
+			if (hclge_cmd_csq_done(hw))
+				break;
+			udelay(1);
+			timeout++;
+		} while (timeout < hw->cmq.tx_timeout);
+	}
+
+	if (hclge_cmd_csq_done(hw)) {
+		complete = true;
+		handle = 0;
+		while (handle < num) {
+			/* Get the result of hardware write back */
+			desc_to_use = &hw->cmq.csq.desc[ntc];
+			desc[handle] = *desc_to_use;
+			pr_debug("Get cmd desc:\n");
+
+			if (likely(!hclge_is_special_opcode(opcode)))
+				desc_ret = desc[handle].retval;
+			else
+				desc_ret = desc[0].retval;
+
+			if ((enum hclge_cmd_return_status)desc_ret ==
+			    HCLGE_CMD_EXEC_SUCCESS)
+				retval = 0;
+			else
+				retval = -EIO;
+			hw->cmq.last_status = (enum hclge_cmd_status)desc_ret;
+			ntc++;
+			handle++;
+			if (ntc == hw->cmq.csq.desc_num)
+				ntc = 0;
+		}
+	}
+
+	if (!complete)
+		retval = -EAGAIN;
+
+	/* Clean the command send queue */
+	handle = hclge_cmd_csq_clean(hw);
+	if (handle != num) {
+		dev_warn(&hdev->pdev->dev,
+			 "cleaned %d, need to clean %d\n", handle, num);
+	}
+
+	spin_unlock_bh(&hw->cmq.csq.lock);
+
+	return retval;
+}
+
+enum hclge_cmd_status hclge_cmd_query_firmware_version(struct hclge_hw *hw,
+						       u32 *version)
+{
+	struct hclge_query_version *resp;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_FW_VER, 1);
+	resp = (struct hclge_query_version *)desc.data;
+
+	ret = hclge_cmd_send(hw, &desc, 1);
+	if (!ret)
+		*version = le32_to_cpu(resp->firmware);
+
+	return ret;
+}
+
+int hclge_cmd_init(struct hclge_dev *hdev)
+{
+	u32 version;
+	int ret;
+
+	/* Setup the queue entries for use cmd queue */
+	hdev->hw.cmq.csq.desc_num = HCLGE_NIC_CMQ_DESC_NUM;
+	hdev->hw.cmq.crq.desc_num = HCLGE_NIC_CMQ_DESC_NUM;
+
+	/* Setup the lock for command queue */
+	spin_lock_init(&hdev->hw.cmq.csq.lock);
+	spin_lock_init(&hdev->hw.cmq.crq.lock);
+
+	/* Setup Tx write back timeout */
+	hdev->hw.cmq.tx_timeout = HCLGE_CMDQ_TX_TIMEOUT;
+
+	/* Setup queue rings */
+	ret = hclge_init_cmd_queue(hdev, HCLGE_TYPE_CSQ);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"CSQ ring setup error %d\n", ret);
+		return ret;
+	}
+
+	ret = hclge_init_cmd_queue(hdev, HCLGE_TYPE_CRQ);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"CRQ ring setup error %d\n", ret);
+		goto err_csq;
+	}
+
+	hclge_cmd_init_regs(&hdev->hw);
+
+	ret = hclge_cmd_query_firmware_version(&hdev->hw, &version);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"firmware version query failed %d\n", ret);
+		return ret;
+	}
+	hdev->fw_version = version;
+
+	dev_info(&hdev->pdev->dev, "The firware version is %08x\n", version);
+
+	return 0;
+err_csq:
+	hclge_free_cmd_desc(&hdev->hw.cmq.csq);
+	return ret;
+}
+
+static void hclge_destroy_queue(struct hclge_cmq_ring *ring)
+{
+	spin_lock_bh(&ring->lock);
+	hclge_free_cmd_desc(ring);
+	spin_unlock_bh(&ring->lock);
+}
+
+void hclge_destroy_cmd_queue(struct hclge_hw *hw)
+{
+	hclge_destroy_queue(&hw->cmq.csq);
+	hclge_destroy_queue(&hw->cmq.crq);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
new file mode 100644
index 0000000..11a2ae6
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -0,0 +1,741 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __HCLGE_CMD_H
+#define __HCLGE_CMD_H
+#include <linux/types.h>
+#include <linux/io.h>
+
+#define HCLGE_CMDQ_TX_TIMEOUT		1000
+
+struct hclge_dev;
+struct hclge_desc {
+	__le16 opcode;
+
+#define HCLGE_CMDQ_RX_INVLD_B		0
+#define HCLGE_CMDQ_RX_OUTVLD_B		1
+
+	__le16 flag;
+	__le16 retval;
+	__le16 rsv;
+	__le32 data[6];
+};
+
+struct hclge_desc_cb {
+	dma_addr_t dma;
+	void *va;
+	u32 length;
+};
+
+struct hclge_cmq_ring {
+	dma_addr_t desc_dma_addr;
+	struct hclge_desc *desc;
+	struct hclge_desc_cb *desc_cb;
+	struct hclge_dev  *dev;
+	u32 head;
+	u32 tail;
+
+	u16 buf_size;
+	u16 desc_num;
+	int next_to_use;
+	int next_to_clean;
+	u8 flag;
+	spinlock_t lock; /* Command queue lock */
+};
+
+enum hclge_cmd_return_status {
+	HCLGE_CMD_EXEC_SUCCESS	= 0,
+	HCLGE_CMD_NO_AUTH	= 1,
+	HCLGE_CMD_NOT_EXEC	= 2,
+	HCLGE_CMD_QUEUE_FULL	= 3,
+};
+
+enum hclge_cmd_status {
+	HCLGE_STATUS_SUCCESS	= 0,
+	HCLGE_ERR_CSQ_FULL	= -1,
+	HCLGE_ERR_CSQ_TIMEOUT	= -2,
+	HCLGE_ERR_CSQ_ERROR	= -3,
+};
+
+struct hclge_cmq {
+	struct hclge_cmq_ring csq;
+	struct hclge_cmq_ring crq;
+	u16 tx_timeout; /* Tx timeout */
+	enum hclge_cmd_status last_status;
+};
+
+#define HCLGE_CMD_FLAG_IN_VALID_SHIFT	0
+#define HCLGE_CMD_FLAG_OUT_VALID_SHIFT	1
+#define HCLGE_CMD_FLAG_NEXT_SHIFT	2
+#define HCLGE_CMD_FLAG_WR_OR_RD_SHIFT	3
+#define HCLGE_CMD_FLAG_NO_INTR_SHIFT	4
+#define HCLGE_CMD_FLAG_ERR_INTR_SHIFT	5
+
+#define HCLGE_CMD_FLAG_IN	BIT(HCLGE_CMD_FLAG_IN_VALID_SHIFT)
+#define HCLGE_CMD_FLAG_OUT	BIT(HCLGE_CMD_FLAG_OUT_VALID_SHIFT)
+#define HCLGE_CMD_FLAG_NEXT	BIT(HCLGE_CMD_FLAG_NEXT_SHIFT)
+#define HCLGE_CMD_FLAG_WR	BIT(HCLGE_CMD_FLAG_WR_OR_RD_SHIFT)
+#define HCLGE_CMD_FLAG_NO_INTR	BIT(HCLGE_CMD_FLAG_NO_INTR_SHIFT)
+#define HCLGE_CMD_FLAG_ERR_INTR	BIT(HCLGE_CMD_FLAG_ERR_INTR_SHIFT)
+
+enum hclge_opcode_type {
+	/* Generic command */
+	HCLGE_OPC_QUERY_FW_VER		= 0x0001,
+	HCLGE_OPC_CFG_RST_TRIGGER	= 0x0020,
+	HCLGE_OPC_GBL_RST_STATUS	= 0x0021,
+	HCLGE_OPC_QUERY_FUNC_STATUS	= 0x0022,
+	HCLGE_OPC_QUERY_PF_RSRC		= 0x0023,
+	HCLGE_OPC_QUERY_VF_RSRC		= 0x0024,
+	HCLGE_OPC_GET_CFG_PARAM		= 0x0025,
+
+	HCLGE_OPC_STATS_64_BIT		= 0x0030,
+	HCLGE_OPC_STATS_32_BIT		= 0x0031,
+	HCLGE_OPC_STATS_MAC		= 0x0032,
+	/* Device management command */
+
+	/* MAC commond */
+	HCLGE_OPC_CONFIG_MAC_MODE	= 0x0301,
+	HCLGE_OPC_CONFIG_AN_MODE	= 0x0304,
+	HCLGE_OPC_QUERY_AN_RESULT	= 0x0306,
+	HCLGE_OPC_QUERY_LINK_STATUS	= 0x0307,
+	HCLGE_OPC_CONFIG_MAX_FRM_SIZE	= 0x0308,
+	HCLGE_OPC_CONFIG_SPEED_DUP	= 0x0309,
+	/* MACSEC command */
+
+	/* PFC/Pause CMD*/
+	HCLGE_OPC_CFG_MAC_PAUSE_EN      = 0x0701,
+	HCLGE_OPC_CFG_PFC_PAUSE_EN      = 0x0702,
+	HCLGE_OPC_CFG_MAC_PARA          = 0x0703,
+	HCLGE_OPC_CFG_PFC_PARA          = 0x0704,
+	HCLGE_OPC_QUERY_MAC_TX_PKT_CNT  = 0x0705,
+	HCLGE_OPC_QUERY_MAC_RX_PKT_CNT  = 0x0706,
+	HCLGE_OPC_QUERY_PFC_TX_PKT_CNT  = 0x0707,
+	HCLGE_OPC_QUERY_PFC_RX_PKT_CNT  = 0x0708,
+	HCLGE_OPC_PRI_TO_TC_MAPPING     = 0x0709,
+	HCLGE_OPC_QOS_MAP               = 0x070A,
+
+	/* ETS/scheduler commands */
+	HCLGE_OPC_TM_PG_TO_PRI_LINK	= 0x0804,
+	HCLGE_OPC_TM_QS_TO_PRI_LINK     = 0x0805,
+	HCLGE_OPC_TM_NQ_TO_QS_LINK      = 0x0806,
+	HCLGE_OPC_TM_RQ_TO_QS_LINK      = 0x0807,
+	HCLGE_OPC_TM_PORT_WEIGHT        = 0x0808,
+	HCLGE_OPC_TM_PG_WEIGHT          = 0x0809,
+	HCLGE_OPC_TM_QS_WEIGHT          = 0x080A,
+	HCLGE_OPC_TM_PRI_WEIGHT         = 0x080B,
+	HCLGE_OPC_TM_PRI_C_SHAPPING     = 0x080C,
+	HCLGE_OPC_TM_PRI_P_SHAPPING     = 0x080D,
+	HCLGE_OPC_TM_PG_C_SHAPPING      = 0x080E,
+	HCLGE_OPC_TM_PG_P_SHAPPING      = 0x080F,
+	HCLGE_OPC_TM_PORT_SHAPPING      = 0x0810,
+	HCLGE_OPC_TM_PG_SCH_MODE_CFG    = 0x0812,
+	HCLGE_OPC_TM_PRI_SCH_MODE_CFG   = 0x0813,
+	HCLGE_OPC_TM_QS_SCH_MODE_CFG    = 0x0814,
+	HCLGE_OPC_TM_BP_TO_QSET_MAPPING = 0x0815,
+
+	/* Packet buffer allocate command */
+	HCLGE_OPC_TX_BUFF_ALLOC		= 0x0901,
+	HCLGE_OPC_RX_PRIV_BUFF_ALLOC	= 0x0902,
+	HCLGE_OPC_RX_PRIV_WL_ALLOC	= 0x0903,
+	HCLGE_OPC_RX_COM_THRD_ALLOC	= 0x0904,
+	HCLGE_OPC_RX_COM_WL_ALLOC	= 0x0905,
+	HCLGE_OPC_RX_GBL_PKT_CNT	= 0x0906,
+
+	/* PTP command */
+	/* TQP management command */
+	HCLGE_OPC_SET_TQP_MAP		= 0x0A01,
+
+	/* TQP command */
+	HCLGE_OPC_CFG_TX_QUEUE		= 0x0B01,
+	HCLGE_OPC_QUERY_TX_POINTER	= 0x0B02,
+	HCLGE_OPC_QUERY_TX_STATUS	= 0x0B03,
+	HCLGE_OPC_CFG_RX_QUEUE		= 0x0B11,
+	HCLGE_OPC_QUERY_RX_POINTER	= 0x0B12,
+	HCLGE_OPC_QUERY_RX_STATUS	= 0x0B13,
+	HCLGE_OPC_STASH_RX_QUEUE_LRO	= 0x0B16,
+	HCLGE_OPC_CFG_RX_QUEUE_LRO	= 0x0B17,
+	HCLGE_OPC_CFG_COM_TQP_QUEUE	= 0x0B20,
+	HCLGE_OPC_RESET_TQP_QUEUE	= 0x0B22,
+
+	/* TSO cmd */
+	HCLGE_OPC_TSO_GENERIC_CONFIG	= 0x0C01,
+
+	/* RSS cmd */
+	HCLGE_OPC_RSS_GENERIC_CONFIG	= 0x0D01,
+	HCLGE_OPC_RSS_INDIR_TABLE	= 0x0D07,
+	HCLGE_OPC_RSS_TC_MODE		= 0x0D08,
+	HCLGE_OPC_RSS_INPUT_TUPLE	= 0x0D02,
+
+	/* Promisuous mode command */
+	HCLGE_OPC_CFG_PROMISC_MODE	= 0x0E01,
+
+	/* Interrupts cmd */
+	HCLGE_OPC_ADD_RING_TO_VECTOR	= 0x1503,
+	HCLGE_OPC_DEL_RING_TO_VECTOR	= 0x1504,
+
+	/* MAC command */
+	HCLGE_OPC_MAC_VLAN_ADD		    = 0x1000,
+	HCLGE_OPC_MAC_VLAN_REMOVE	    = 0x1001,
+	HCLGE_OPC_MAC_VLAN_TYPE_ID	    = 0x1002,
+	HCLGE_OPC_MAC_VLAN_INSERT	    = 0x1003,
+	HCLGE_OPC_MAC_ETHTYPE_ADD	    = 0x1010,
+	HCLGE_OPC_MAC_ETHTYPE_REMOVE	= 0x1011,
+
+	/* Multicast linear table cmd */
+	HCLGE_OPC_MTA_MAC_MODE_CFG	    = 0x1020,
+	HCLGE_OPC_MTA_MAC_FUNC_CFG	    = 0x1021,
+	HCLGE_OPC_MTA_TBL_ITEM_CFG	    = 0x1022,
+	HCLGE_OPC_MTA_TBL_ITEM_QUERY	= 0x1023,
+
+	/* VLAN command */
+	HCLGE_OPC_VLAN_FILTER_CTRL	    = 0x1100,
+	HCLGE_OPC_VLAN_FILTER_PF_CFG	= 0x1101,
+	HCLGE_OPC_VLAN_FILTER_VF_CFG	= 0x1102,
+
+	/* MDIO command */
+	HCLGE_OPC_MDIO_CONFIG		= 0x1900,
+
+	/* QCN command */
+	HCLGE_OPC_QCN_MOD_CFG		= 0x1A01,
+	HCLGE_OPC_QCN_GRP_TMPLT_CFG	= 0x1A02,
+	HCLGE_OPC_QCN_SHAPPING_IR_CFG	= 0x1A03,
+	HCLGE_OPC_QCN_SHAPPING_BS_CFG	= 0x1A04,
+	HCLGE_OPC_QCN_QSET_LINK_CFG	= 0x1A05,
+	HCLGE_OPC_QCN_RP_STATUS_GET	= 0x1A06,
+	HCLGE_OPC_QCN_AJUST_INIT	= 0x1A07,
+	HCLGE_OPC_QCN_DFX_CNT_STATUS    = 0x1A08,
+
+	/* Mailbox cmd */
+	HCLGEVF_OPC_MBX_PF_TO_VF	= 0x2000,
+};
+
+#define HCLGE_TQP_REG_OFFSET		0x80000
+#define HCLGE_TQP_REG_SIZE		0x200
+
+#define HCLGE_RCB_INIT_QUERY_TIMEOUT	10
+#define HCLGE_RCB_INIT_FLAG_EN_B	0
+#define HCLGE_RCB_INIT_FLAG_FINI_B	8
+struct hclge_config_rcb_init {
+	__le16 rcb_init_flag;
+	u8 rsv[22];
+};
+
+struct hclge_tqp_map {
+	__le16 tqp_id;	/* Absolute tqp id for in this pf */
+	u8 tqp_vf;	/* VF id */
+#define HCLGE_TQP_MAP_TYPE_PF		0
+#define HCLGE_TQP_MAP_TYPE_VF		1
+#define HCLGE_TQP_MAP_TYPE_B		0
+#define HCLGE_TQP_MAP_EN_B		1
+	u8 tqp_flag;	/* Indicate it's pf or vf tqp */
+	__le16 tqp_vid; /* Virtual id in this pf/vf */
+	u8 rsv[18];
+};
+
+#define HCLGE_VECTOR_ELEMENTS_PER_CMD	11
+
+enum hclge_int_type {
+	HCLGE_INT_TX,
+	HCLGE_INT_RX,
+	HCLGE_INT_EVENT,
+};
+
+struct hclge_ctrl_vector_chain {
+	u8 int_vector_id;
+	u8 int_cause_num;
+#define HCLGE_INT_TYPE_S	0
+#define HCLGE_INT_TYPE_M	0x3
+#define HCLGE_TQP_ID_S		2
+#define HCLGE_TQP_ID_M		(0x3fff << HCLGE_TQP_ID_S)
+	__le16 tqp_type_and_id[HCLGE_VECTOR_ELEMENTS_PER_CMD];
+};
+
+#define HCLGE_TC_NUM		8
+#define HCLGE_TC0_PRI_BUF_EN_B	15 /* Bit 15 indicate enable or not */
+#define HCLGE_BUF_UNIT_S	7  /* Buf size is united by 128 bytes */
+struct hclge_tx_buff_alloc {
+	__le16 tx_pkt_buff[HCLGE_TC_NUM];
+	u8 tx_buff_rsv[8];
+};
+
+struct hclge_rx_priv_buff {
+	__le16 buf_num[HCLGE_TC_NUM];
+	u8 rsv[8];
+};
+
+struct hclge_query_version {
+	__le32 firmware;
+	__le32 firmware_rsv[5];
+};
+
+#define HCLGE_RX_PRIV_EN_B	15
+#define HCLGE_TC_NUM_ONE_DESC	4
+struct hclge_priv_wl {
+	__le16 high;
+	__le16 low;
+};
+
+struct hclge_rx_priv_wl_buf {
+	struct hclge_priv_wl tc_wl[HCLGE_TC_NUM_ONE_DESC];
+};
+
+struct hclge_rx_com_thrd {
+	struct hclge_priv_wl com_thrd[HCLGE_TC_NUM_ONE_DESC];
+};
+
+struct hclge_rx_com_wl {
+	struct hclge_priv_wl com_wl;
+};
+
+struct hclge_waterline {
+	u32 low;
+	u32 high;
+};
+
+struct hclge_tc_thrd {
+	u32 low;
+	u32 high;
+};
+
+struct hclge_priv_buf {
+	struct hclge_waterline wl;	/* Waterline for low and high*/
+	u32 buf_size;	/* TC private buffer size */
+	u32 enable;	/* Enable TC private buffer or not */
+};
+
+#define HCLGE_MAX_TC_NUM	8
+struct hclge_shared_buf {
+	struct hclge_waterline self;
+	struct hclge_tc_thrd tc_thrd[HCLGE_MAX_TC_NUM];
+	u32 buf_size;
+};
+
+#define HCLGE_RX_COM_WL_EN_B	15
+struct hclge_rx_com_wl_buf {
+	__le16 high_wl;
+	__le16 low_wl;
+	u8 rsv[20];
+};
+
+#define HCLGE_RX_PKT_EN_B	15
+struct hclge_rx_pkt_buf {
+	__le16 high_pkt;
+	__le16 low_pkt;
+	u8 rsv[20];
+};
+
+#define HCLGE_PF_STATE_DONE_B	0
+#define HCLGE_PF_STATE_MAIN_B	1
+#define HCLGE_PF_STATE_BOND_B	2
+#define HCLGE_PF_STATE_MAC_N_B	6
+#define HCLGE_PF_MAC_NUM_MASK	0x3
+#define HCLGE_PF_STATE_MAIN	BIT(HCLGE_PF_STATE_MAIN_B)
+#define HCLGE_PF_STATE_DONE	BIT(HCLGE_PF_STATE_DONE_B)
+struct hclge_func_status {
+	__le32  vf_rst_state[4];
+	u8 pf_state;
+	u8 mac_id;
+	u8 rsv1;
+	u8 pf_cnt_in_mac;
+	u8 pf_num;
+	u8 vf_num;
+	u8 rsv[2];
+};
+
+struct hclge_pf_res {
+	__le16 tqp_num;
+	__le16 buf_size;
+	__le16 msixcap_localid_ba_nic;
+	__le16 msixcap_localid_ba_rocee;
+#define HCLGE_PF_VEC_NUM_S		0
+#define HCLGE_PF_VEC_NUM_M		(0xff << HCLGE_PF_VEC_NUM_S)
+	__le16 pf_intr_vector_number;
+	__le16 pf_own_fun_number;
+	__le32 rsv[3];
+};
+
+#define HCLGE_CFG_OFFSET_S	0
+#define HCLGE_CFG_OFFSET_M	0xfffff /* Byte (8-10.3) */
+#define HCLGE_CFG_RD_LEN_S	24
+#define HCLGE_CFG_RD_LEN_M	(0xf << HCLGE_CFG_RD_LEN_S)
+#define HCLGE_CFG_RD_LEN_BYTES	16
+#define HCLGE_CFG_RD_LEN_UNIT	4
+
+#define HCLGE_CFG_VMDQ_S	0
+#define HCLGE_CFG_VMDQ_M	(0xff << HCLGE_CFG_VMDQ_S)
+#define HCLGE_CFG_TC_NUM_S	8
+#define HCLGE_CFG_TC_NUM_M	(0xff << HCLGE_CFG_TC_NUM_S)
+#define HCLGE_CFG_TQP_DESC_N_S	16
+#define HCLGE_CFG_TQP_DESC_N_M	(0xffff << HCLGE_CFG_TQP_DESC_N_S)
+#define HCLGE_CFG_PHY_ADDR_S	0
+#define HCLGE_CFG_PHY_ADDR_M	(0x1f << HCLGE_CFG_PHY_ADDR_S)
+#define HCLGE_CFG_MEDIA_TP_S	8
+#define HCLGE_CFG_MEDIA_TP_M	(0xff << HCLGE_CFG_MEDIA_TP_S)
+#define HCLGE_CFG_RX_BUF_LEN_S	16
+#define HCLGE_CFG_RX_BUF_LEN_M	(0xffff << HCLGE_CFG_RX_BUF_LEN_S)
+#define HCLGE_CFG_MAC_ADDR_H_S	0
+#define HCLGE_CFG_MAC_ADDR_H_M	(0xffff << HCLGE_CFG_MAC_ADDR_H_S)
+#define HCLGE_CFG_DEFAULT_SPEED_S	16
+#define HCLGE_CFG_DEFAULT_SPEED_M	(0xff << HCLGE_CFG_DEFAULT_SPEED_S)
+
+struct hclge_cfg_param {
+	__le32 offset;
+	__le32 rsv;
+	__le32 param[4];
+};
+
+#define HCLGE_MAC_MODE		0x0
+#define HCLGE_DESC_NUM		0x40
+
+#define HCLGE_ALLOC_VALID_B	0
+struct hclge_vf_num {
+	u8 alloc_valid;
+	u8 rsv[23];
+};
+
+#define HCLGE_RSS_DEFAULT_OUTPORT_B	4
+#define HCLGE_RSS_HASH_KEY_OFFSET_B	4
+#define HCLGE_RSS_HASH_KEY_NUM		16
+struct hclge_rss_config {
+	u8 hash_config;
+	u8 rsv[7];
+	u8 hash_key[HCLGE_RSS_HASH_KEY_NUM];
+};
+
+struct hclge_rss_input_tuple {
+	u8 ipv4_tcp_en;
+	u8 ipv4_udp_en;
+	u8 ipv4_sctp_en;
+	u8 ipv4_fragment_en;
+	u8 ipv6_tcp_en;
+	u8 ipv6_udp_en;
+	u8 ipv6_sctp_en;
+	u8 ipv6_fragment_en;
+	u8 rsv[16];
+};
+
+#define HCLGE_RSS_CFG_TBL_SIZE	16
+
+struct hclge_rss_indirection_table {
+	u16 start_table_index;
+	u16 rss_set_bitmap;
+	u8 rsv[4];
+	u8 rss_result[HCLGE_RSS_CFG_TBL_SIZE];
+};
+
+#define HCLGE_RSS_TC_OFFSET_S		0
+#define HCLGE_RSS_TC_OFFSET_M		(0x3ff << HCLGE_RSS_TC_OFFSET_S)
+#define HCLGE_RSS_TC_SIZE_S		12
+#define HCLGE_RSS_TC_SIZE_M		(0x7 << HCLGE_RSS_TC_SIZE_S)
+#define HCLGE_RSS_TC_VALID_B		15
+struct hclge_rss_tc_mode {
+	u16 rss_tc_mode[HCLGE_MAX_TC_NUM];
+	u8 rsv[8];
+};
+
+#define HCLGE_LINK_STS_B	0
+#define HCLGE_LINK_STATUS	BIT(HCLGE_LINK_STS_B)
+struct hclge_link_status {
+	u8 status;
+	u8 rsv[23];
+};
+
+struct hclge_promisc_param {
+	u8 vf_id;
+	u8 enable;
+};
+
+#define HCLGE_PROMISC_EN_B	1
+#define HCLGE_PROMISC_EN_ALL	0x7
+#define HCLGE_PROMISC_EN_UC	0x1
+#define HCLGE_PROMISC_EN_MC	0x2
+#define HCLGE_PROMISC_EN_BC	0x4
+struct hclge_promisc_cfg {
+	u8 flag;
+	u8 vf_id;
+	__le16 rsv0;
+	u8 rsv1[20];
+};
+
+enum hclge_promisc_type {
+	HCLGE_UNICAST	= 1,
+	HCLGE_MULTICAST	= 2,
+	HCLGE_BROADCAST	= 3,
+};
+
+#define HCLGE_MAC_TX_EN_B	6
+#define HCLGE_MAC_RX_EN_B	7
+#define HCLGE_MAC_PAD_TX_B	11
+#define HCLGE_MAC_PAD_RX_B	12
+#define HCLGE_MAC_1588_TX_B	13
+#define HCLGE_MAC_1588_RX_B	14
+#define HCLGE_MAC_APP_LP_B	15
+#define HCLGE_MAC_LINE_LP_B	16
+#define HCLGE_MAC_FCS_TX_B	17
+#define HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B	18
+#define HCLGE_MAC_RX_FCS_STRIP_B	19
+#define HCLGE_MAC_RX_FCS_B	20
+#define HCLGE_MAC_TX_UNDER_MIN_ERR_B		21
+#define HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B	22
+
+struct hclge_config_mac_mode {
+	__le32 txrx_pad_fcs_loop_en;
+	u8 rsv[20];
+};
+
+#define HCLGE_CFG_SPEED_S		0
+#define HCLGE_CFG_SPEED_M		(0x3f << HCLGE_CFG_SPEED_S)
+
+#define HCLGE_CFG_DUPLEX_B		7
+#define HCLGE_CFG_DUPLEX_M		BIT(HCLGE_CFG_DUPLEX_B)
+
+struct hclge_config_mac_speed_dup {
+	u8 speed_dup;
+
+#define HCLGE_CFG_MAC_SPEED_CHANGE_EN_B	0
+	u8 mac_change_fec_en;
+	u8 rsv[22];
+};
+
+#define HCLGE_QUERY_SPEED_S		3
+#define HCLGE_QUERY_AN_B		0
+#define HCLGE_QUERY_DUPLEX_B		2
+
+#define HCLGE_QUERY_SPEED_M		(0x1f << HCLGE_QUERY_SPEED_S)
+#define HCLGE_QUERY_AN_M		BIT(HCLGE_QUERY_AN_B)
+#define HCLGE_QUERY_DUPLEX_M		BIT(HCLGE_QUERY_DUPLEX_B)
+
+struct hclge_query_an_speed_dup {
+	u8 an_syn_dup_speed;
+	u8 pause;
+	u8 rsv[23];
+};
+
+#define HCLGE_RING_ID_MASK		0x3ff
+#define HCLGE_TQP_ENABLE_B		0
+
+#define HCLGE_MAC_CFG_AN_EN_B		0
+#define HCLGE_MAC_CFG_AN_INT_EN_B	1
+#define HCLGE_MAC_CFG_AN_INT_MSK_B	2
+#define HCLGE_MAC_CFG_AN_INT_CLR_B	3
+#define HCLGE_MAC_CFG_AN_RST_B		4
+
+#define HCLGE_MAC_CFG_AN_EN	BIT(HCLGE_MAC_CFG_AN_EN_B)
+
+struct hclge_config_auto_neg {
+	__le32  cfg_an_cmd_flag;
+	u8      rsv[20];
+};
+
+#define HCLGE_MAC_MIN_MTU		64
+#define HCLGE_MAC_MAX_MTU		9728
+#define HCLGE_MAC_UPLINK_PORT		0x100
+
+struct hclge_config_max_frm_size {
+	__le16  max_frm_size;
+	u8      rsv[22];
+};
+
+enum hclge_mac_vlan_tbl_opcode {
+	HCLGE_MAC_VLAN_ADD,	/* Add new or modify mac_vlan */
+	HCLGE_MAC_VLAN_UPDATE,  /* Modify other fields of this table */
+	HCLGE_MAC_VLAN_REMOVE,  /* Remove a entry through mac_vlan key */
+	HCLGE_MAC_VLAN_LKUP,    /* Lookup a entry through mac_vlan key */
+};
+
+#define HCLGE_MAC_VLAN_BIT0_EN_B	0x0
+#define HCLGE_MAC_VLAN_BIT1_EN_B	0x1
+#define HCLGE_MAC_EPORT_SW_EN_B		0xc
+#define HCLGE_MAC_EPORT_TYPE_B		0xb
+#define HCLGE_MAC_EPORT_VFID_S		0x3
+#define HCLGE_MAC_EPORT_VFID_M		(0xff << HCLGE_MAC_EPORT_VFID_S)
+#define HCLGE_MAC_EPORT_PFID_S		0x0
+#define HCLGE_MAC_EPORT_PFID_M		(0x7 << HCLGE_MAC_EPORT_PFID_S)
+struct hclge_mac_vlan_tbl_entry {
+	u8	flags;
+	u8      resp_code;
+	__le16  vlan_tag;
+	__le32  mac_addr_hi32;
+	__le16  mac_addr_lo16;
+	__le16  rsv1;
+	u8      entry_type;
+	u8      mc_mac_en;
+	__le16  egress_port;
+	__le16  egress_queue;
+	u8      rsv2[6];
+};
+
+#define HCLGE_CFG_MTA_MAC_SEL_S		0x0
+#define HCLGE_CFG_MTA_MAC_SEL_M		(0x3 << HCLGE_CFG_MTA_MAC_SEL_S)
+#define HCLGE_CFG_MTA_MAC_EN_B		0x7
+struct hclge_mta_filter_mode {
+	u8	dmac_sel_en; /* Use lowest 2 bit as sel_mode, bit 7 as enable */
+	u8      rsv[23];
+};
+
+#define HCLGE_CFG_FUNC_MTA_ACCEPT_B	0x0
+struct hclge_cfg_func_mta_filter {
+	u8	accept; /* Only used lowest 1 bit */
+	u8      function_id;
+	u8      rsv[22];
+};
+
+#define HCLGE_CFG_MTA_ITEM_ACCEPT_B	0x0
+#define HCLGE_CFG_MTA_ITEM_IDX_S	0x0
+#define HCLGE_CFG_MTA_ITEM_IDX_M	(0xfff << HCLGE_CFG_MTA_ITEM_IDX_S)
+struct hclge_cfg_func_mta_item {
+	u16	item_idx; /* Only used lowest 12 bit */
+	u8      accept;   /* Only used lowest 1 bit */
+	u8      rsv[21];
+};
+
+struct hclge_mac_vlan_add {
+	__le16  flags;
+	__le16  mac_addr_hi16;
+	__le32  mac_addr_lo32;
+	__le32  mac_addr_msk_hi32;
+	__le16  mac_addr_msk_lo16;
+	__le16  vlan_tag;
+	__le16  ingress_port;
+	__le16  egress_port;
+	u8      rsv[4];
+};
+
+#define HNS3_MAC_VLAN_CFG_FLAG_BIT 0
+struct hclge_mac_vlan_remove {
+	__le16  flags;
+	__le16  mac_addr_hi16;
+	__le32  mac_addr_lo32;
+	__le32  mac_addr_msk_hi32;
+	__le16  mac_addr_msk_lo16;
+	__le16  vlan_tag;
+	__le16  ingress_port;
+	__le16  egress_port;
+	u8      rsv[4];
+};
+
+struct hclge_vlan_filter_ctrl {
+	u8 vlan_type;
+	u8 vlan_fe;
+	u8 rsv[22];
+};
+
+struct hclge_vlan_filter_pf_cfg {
+	u8 vlan_offset;
+	u8 vlan_cfg;
+	u8 rsv[2];
+	u8 vlan_offset_bitmap[20];
+};
+
+struct hclge_vlan_filter_vf_cfg {
+	u16 vlan_id;
+	u8  resp_code;
+	u8  rsv;
+	u8  vlan_cfg;
+	u8  rsv1[3];
+	u8  vf_bitmap[16];
+};
+
+struct hclge_cfg_com_tqp_queue {
+	__le16 tqp_id;
+	__le16 stream_id;
+	u8 enable;
+	u8 rsv[19];
+};
+
+struct hclge_cfg_tx_queue_pointer {
+	__le16 tqp_id;
+	__le16 tx_tail;
+	__le16 tx_head;
+	__le16 fbd_num;
+	__le16 ring_offset;
+	u8 rsv[14];
+};
+
+#define HCLGE_TSO_MSS_MIN_S	0
+#define HCLGE_TSO_MSS_MIN_M	(0x3FFF << HCLGE_TSO_MSS_MIN_S)
+
+#define HCLGE_TSO_MSS_MAX_S	16
+#define HCLGE_TSO_MSS_MAX_M	(0x3FFF << HCLGE_TSO_MSS_MAX_S)
+
+struct hclge_cfg_tso_status {
+	__le16 tso_mss_min;
+	__le16 tso_mss_max;
+	u8 rsv[20];
+};
+
+#define HCLGE_TSO_MSS_MIN	256
+#define HCLGE_TSO_MSS_MAX	9668
+
+#define HCLGE_TQP_RESET_B	0
+struct hclge_reset_tqp_queue {
+	__le16 tqp_id;
+	u8 reset_req;
+	u8 ready_to_reset;
+	u8 rsv[20];
+};
+
+#define HCLGE_DEFAULT_TX_BUF		0x4000	 /* 16k  bytes */
+#define HCLGE_TOTAL_PKT_BUF		0x108000 /* 1.03125M bytes */
+#define HCLGE_DEFAULT_DV		0xA000	 /* 40k byte */
+
+#define HCLGE_TYPE_CRQ			0
+#define HCLGE_TYPE_CSQ			1
+#define HCLGE_NIC_CSQ_BASEADDR_L_REG	0x27000
+#define HCLGE_NIC_CSQ_BASEADDR_H_REG	0x27004
+#define HCLGE_NIC_CSQ_DEPTH_REG		0x27008
+#define HCLGE_NIC_CSQ_TAIL_REG		0x27010
+#define HCLGE_NIC_CSQ_HEAD_REG		0x27014
+#define HCLGE_NIC_CRQ_BASEADDR_L_REG	0x27018
+#define HCLGE_NIC_CRQ_BASEADDR_H_REG	0x2701c
+#define HCLGE_NIC_CRQ_DEPTH_REG		0x27020
+#define HCLGE_NIC_CRQ_TAIL_REG		0x27024
+#define HCLGE_NIC_CRQ_HEAD_REG		0x27028
+#define HCLGE_NIC_CMQ_EN_B		16
+#define HCLGE_NIC_CMQ_ENABLE		BIT(HCLGE_NIC_CMQ_EN_B)
+#define HCLGE_NIC_CMQ_DESC_NUM		1024
+#define HCLGE_NIC_CMQ_DESC_NUM_S	3
+
+int hclge_cmd_init(struct hclge_dev *hdev);
+static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
+{
+	writel(value, base + reg);
+}
+
+#define hclge_write_dev(a, reg, value) \
+	hclge_write_reg((a)->io_base, (reg), (value))
+#define hclge_read_dev(a, reg) \
+	hclge_read_reg((a)->io_base, (reg))
+
+static inline u32 hclge_read_reg(u8 __iomem *base, u32 reg)
+{
+	u8 __iomem *reg_addr = READ_ONCE(base);
+
+	return readl(reg_addr + reg);
+}
+
+#define HCLGE_SEND_SYNC(flag) \
+	((flag) & HCLGE_CMD_FLAG_NO_INTR)
+
+struct hclge_hw;
+int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num);
+void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
+				enum hclge_opcode_type opcode, bool is_read);
+
+void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read);
+int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
+			       struct hclge_promisc_param *param);
+
+enum hclge_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw,
+					   struct hclge_desc *desc);
+enum hclge_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw,
+					  struct hclge_desc *desc);
+
+void hclge_destroy_cmd_queue(struct hclge_hw *hw);
+#endif
-- 
2.7.4

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web