Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1699129 > unrolled thread
| Started by | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| First post | 2017-07-29 00:30 +0200 |
| Last post | 2017-07-29 00:40 +0200 |
| Articles | 12 — 3 participants |
Back to article view | Back to linux.kernel
[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
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-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]
| From | Leon Romanovsky <leon@kernel.org> |
|---|---|
| Date | 2017-07-30 12:00 +0200 |
| Subject | Re: [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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-07-31 11:10 +0200 |
| Subject | RE: [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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-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]
| From | Andrew Lunn <andrew@lunn.ch> |
|---|---|
| Date | 2017-07-29 01:30 +0200 |
| Subject | Re: [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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-07-29 02:00 +0200 |
| Subject | RE: [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]
| From | Andrew Lunn <andrew@lunn.ch> |
|---|---|
| Date | 2017-07-29 01:30 +0200 |
| Subject | Re: [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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-07-29 02:00 +0200 |
| Subject | RE: [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]
| From | Salil Mehta <salil.mehta@huawei.com> |
|---|---|
| Date | 2017-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