From 34f08dce1aaa08005809cc4243e8ada45bc32f99 Mon Sep 17 00:00:00 2001
From: Hao Chen <chenhao418@huawei.com>
Date: Thu, 16 Mar 2023 17:14:05 +0800
Subject: [PATCH 195/283] net: hns3: add support to get/set 1d torus param

driver inclusion
category: feature
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EN3D
CVE: NA

----------------------------------------------------------------------

Two network ports on a single chip can be physically connected to form
a 1d torus topology. TCP/UDP and RDMA communication between chip nodes
can be implemented without switches.The patch provide interfaces for
getting/setting 1d torus param.

Signed-off-by: Hao Chen <chenhao418@huawei.com>
Signed-off-by: Tian Jiang <jiangtian6@h-partners.com>
Signed-off-by: Jiantao Xiao <xiaojiantao1@h-partners.com>
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>

 Conflicts:
	drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h
---
 .../hns3/hns3_common/hclge_comm_cmd.h         |   1 +
 .../net/ethernet/hisilicon/hns3/hns3_ext.c    |  19 ++
 .../net/ethernet/hisilicon/hns3/hns3_ext.h    |   4 +
 .../hisilicon/hns3/hns3pf/hclge_ext.c         | 194 ++++++++++++++++++
 .../hisilicon/hns3/hns3pf/hclge_ext.h         |  29 +++
 .../hisilicon/hns3/hns3pf/hclge_main.h        |   1 +
 6 files changed, 248 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
index 05b8252c2522..8f07dc44b30a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
@@ -204,4 +204,5 @@ void hclge_comm_free_cmd_desc(struct hclge_comm_cmq_ring *ring);
 void hclge_comm_cmd_setup_basic_desc(struct hclge_desc *desc,
 				     enum hclge_opcode_type opcode,
 				     bool is_read);
+void hclge_comm_cmd_reuse_desc(struct hclge_desc *desc, bool is_read);
 #endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c
index 08ef05d76b57..1e1b1fb81f17 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c
@@ -186,3 +186,22 @@ int nic_set_notify_pkt_start(struct net_device *ndev)
 				  NULL, 0);
 }
 EXPORT_SYMBOL(nic_set_notify_pkt_start);
+
+int nic_set_torus_param(struct net_device *ndev,
+			struct hnae3_torus_param *param)
+{
+	if (!param || (param->enable != 0 && param->enable != 1))
+		return -EINVAL;
+
+	return nic_invoke_pri_ops(ndev, HNAE3_EXT_OPC_SET_TORUS_PARAM,
+				  param, sizeof(*param));
+}
+EXPORT_SYMBOL(nic_set_torus_param);
+
+int nic_get_torus_param(struct net_device *ndev,
+			struct hnae3_torus_param *param)
+{
+	return nic_invoke_pri_ops(ndev, HNAE3_EXT_OPC_GET_TORUS_PARAM,
+				  param, sizeof(*param));
+}
+EXPORT_SYMBOL(nic_get_torus_param);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h
index ec661b400f20..1a8573efa642 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h
@@ -15,4 +15,8 @@ int nic_set_cpu_affinity(struct net_device *ndev, cpumask_t *affinity_mask);
 int nic_set_notify_pkt_param(struct net_device *ndev,
 			     struct hnae3_notify_pkt_param *param);
 int nic_set_notify_pkt_start(struct net_device *ndev);
+int nic_set_torus_param(struct net_device *ndev,
+			struct hnae3_torus_param *param);
+int nic_get_torus_param(struct net_device *ndev,
+			struct hnae3_torus_param *param);
 #endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c
index ba612b21a8ee..8097f7079760 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c
@@ -17,6 +17,16 @@ static nic_event_fn_t nic_event_call;
  */
 static DEFINE_MUTEX(hclge_nic_event_lock);
 
+void hclge_comm_cmd_reuse_desc(struct hclge_desc *desc, bool is_read)
+{
+	desc->flag = cpu_to_le16(HCLGE_COMM_CMD_FLAG_NO_INTR |
+				 HCLGE_COMM_CMD_FLAG_IN);
+	if (is_read)
+		desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_WR);
+	else
+		desc->flag &= cpu_to_le16(~HCLGE_COMM_CMD_FLAG_WR);
+}
+
 static int hclge_clean_stats64(struct hclge_dev *hdev, void *data,
 			       size_t length)
 {
@@ -117,6 +127,185 @@ static int hclge_set_notify_packet_start(struct hclge_dev *hdev,
 	return ret;
 }
 
+static int hclge_torus_cfg_switch(struct hclge_dev *hdev, bool is_rocee,
+				  bool enabled)
+{
+	struct hclge_mac_vlan_switch_cmd *req;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_SWITCH_PARAM, true);
+	req = (struct hclge_mac_vlan_switch_cmd *)desc.data;
+	req->roce_sel = is_rocee ? 1 : 0;
+	/* set 0 to let firmware choose current function */
+	req->func_id = 0;
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to get switch param, ret = %d\n", ret);
+		return ret;
+	}
+
+	hnae3_set_bit(req->switch_param, HCLGE_SWITCH_ALW_LPBK_B, 1);
+	hnae3_set_bit(req->switch_param, HCLGE_SWITCH_ALW_LCL_LPBK_B, 0);
+	hnae3_set_bit(req->switch_param, HCLGE_SWITCH_ANTI_SPOOF_B, enabled);
+	if (!is_rocee)
+		hnae3_set_bit(req->switch_param, HCLGE_SWITCH_ALW_DST_OVRD_B,
+			      enabled);
+
+	hclge_comm_cmd_reuse_desc(&desc, false);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"failed to set switch param, ret = %d\n", ret);
+
+	return ret;
+}
+
+static int hclge_torus_cfg_vlan_filter(struct hclge_dev *hdev,
+				       bool enabled)
+{
+	struct hclge_vlan_filter_ctrl_cmd *req;
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_VLAN_FILTER, true);
+	req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data;
+	req->vlan_type = HCLGE_FILTER_TYPE_PORT;
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to get torus vlan filter, ret = %d\n", ret);
+		return ret;
+	}
+
+	hnae3_set_bit(req->vlan_fe, HCLGE_VLAN_FE_NIC_INGRESS, !enabled);
+	hnae3_set_bit(req->vlan_fe, HCLGE_VLAN_FE_ROCEE_INGRESS, !enabled);
+	req->vlan_type = HCLGE_FILTER_TYPE_PORT;
+
+	hclge_comm_cmd_reuse_desc(&desc, false);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"failed to set torus vlan filter, ret = %d\n", ret);
+
+	return ret;
+}
+
+static int hclge_torus_cfg(struct hclge_dev *hdev,
+			   struct hnae3_torus_param *param)
+{
+	struct hclge_torus_cfg_cmd *req;
+	struct hclge_desc desc;
+	u32 lan_fwd_tc_cfg = 0;
+	u32 lan_port_pair = 0;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_1D_TORUS, true);
+	req = (struct hclge_torus_cfg_cmd *)desc.data;
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to get torus config, ret = %d\n", ret);
+		return ret;
+	}
+
+	req->lan_port_pair = cpu_to_le32(param->mac_id &
+					 HCLGE_TORUS_MAC_ID_MASK);
+	hnae3_set_bit(lan_port_pair, HCLGE_UC_LAN_PAIR_EN, 1);
+	hnae3_set_bit(lan_port_pair, HCLGE_MC_BC_LAN_PAIR_EN, 1);
+	hnae3_set_bit(lan_port_pair, HCLGE_LLDP_LAN_PAIR_EN, 1);
+	hnae3_set_bit(lan_port_pair, HCLGE_TC2VLANPRI_MAPPING_EN, 1);
+	hnae3_set_bit(lan_port_pair, HCLGE_TORUS_LPBK_DROP_EN, 1);
+	if (param->enable)
+		req->lan_port_pair |= cpu_to_le32(lan_port_pair);
+
+	if (!param->is_node0) {
+		req->lan_fwd_tc_cfg &= cpu_to_le32(~HCLGE_TORUS_TC1_DROP_EN);
+		lan_fwd_tc_cfg &= ~HCLGE_TOURS_TCX_MAP_TCY_MASK;
+		lan_fwd_tc_cfg |= HCLGE_TOURS_TCX_MAP_TCY_INIT &
+				  HCLGE_TOURS_TCX_MAP_TCY_MASK;
+		req->lan_fwd_tc_cfg |= cpu_to_le32(lan_fwd_tc_cfg);
+	} else {
+		req->lan_fwd_tc_cfg |= cpu_to_le32(HCLGE_TORUS_TC1_DROP_EN);
+		lan_fwd_tc_cfg &= ~HCLGE_TOURS_TCX_MAP_TCY_MASK;
+		lan_fwd_tc_cfg |= HCLGE_TOURS_TCX_MAP_TCY_NODE0_INIT &
+				  HCLGE_TOURS_TCX_MAP_TCY_MASK;
+		req->lan_fwd_tc_cfg |= cpu_to_le32(lan_fwd_tc_cfg);
+	}
+
+	req->torus_en = cpu_to_le32(param->enable);
+	hclge_comm_cmd_reuse_desc(&desc, false);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret)
+		dev_err(&hdev->pdev->dev, "failed to set torus, ret = %d\n",
+			ret);
+
+	return ret;
+}
+
+static int hclge_set_torus_param(struct hclge_dev *hdev, void *data,
+				 size_t length)
+{
+	struct hnae3_torus_param *param = (struct hnae3_torus_param *)data;
+	int ret;
+
+	if (length != sizeof(struct hnae3_torus_param))
+		return -EINVAL;
+
+	ret = hclge_torus_cfg_switch(hdev, false, !!param->enable);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to config nic switch param, ret = %d\n", ret);
+		return ret;
+	}
+
+	ret = hclge_torus_cfg_switch(hdev, true, !!param->enable);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to config roce switch param, ret = %d\n", ret);
+		return ret;
+	}
+
+	ret = hclge_torus_cfg_vlan_filter(hdev, !!param->enable);
+	if (ret)
+		return ret;
+
+	ret = hclge_torus_cfg(hdev, param);
+	if (ret)
+		return ret;
+
+	hdev->torus_param = *param;
+	return 0;
+}
+
+static int hclge_get_torus_param(struct hclge_dev *hdev, void *data,
+				 size_t length)
+{
+	struct hnae3_torus_param *param = (struct hnae3_torus_param *)data;
+	struct hclge_torus_cfg_cmd *req;
+	struct hclge_desc desc;
+	int ret;
+
+	if (length != sizeof(struct hnae3_torus_param))
+		return -EINVAL;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_1D_TORUS, true);
+	req = (struct hclge_torus_cfg_cmd *)desc.data;
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to get torus param, ret = %d\n", ret);
+		return ret;
+	}
+
+	param->mac_id =
+		le32_to_cpu(req->lan_port_pair) & HCLGE_TORUS_MAC_ID_MASK;
+	param->enable = le32_to_cpu(req->torus_en);
+
+	return 0;
+}
+
 static void hclge_ext_resotre_config(struct hclge_dev *hdev)
 {
 	if (hdev->reset_type != HNAE3_IMP_RESET &&
@@ -126,6 +315,9 @@ static void hclge_ext_resotre_config(struct hclge_dev *hdev)
 	if (hdev->notify_param.init)
 		hclge_set_notify_packet_para(hdev, &hdev->notify_param,
 					     sizeof(hdev->notify_param));
+
+	hclge_set_torus_param(hdev, &hdev->torus_param,
+			      sizeof(hdev->torus_param));
 }
 
 static int hclge_set_reset_task(struct hclge_dev *hdev, void *data,
@@ -268,6 +460,8 @@ static const hclge_priv_ops_fn hclge_ext_func_arr[] = {
 	[HNAE3_EXT_OPC_CLEAN_STATS64] = hclge_clean_stats64,
 	[HNAE3_EXT_OPC_SET_NOTIFY_PARAM] = hclge_set_notify_packet_para,
 	[HNAE3_EXT_OPC_SET_NOTIFY_START] = hclge_set_notify_packet_start,
+	[HNAE3_EXT_OPC_SET_TORUS_PARAM] = hclge_set_torus_param,
+	[HNAE3_EXT_OPC_GET_TORUS_PARAM] = hclge_get_torus_param,
 };
 
 int hclge_ext_ops_handle(struct hnae3_handle *handle, int opcode,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h
index ce8fc17741fc..abdb00e78fc3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h
@@ -10,6 +10,23 @@
 #define HCLGE_NOTIFY_PARA_CFG_PKT_NUM_M		GENMASK(5, 2)
 #define HCLGE_NOTIFY_PARA_CFG_PKT_NUM_S		2
 
+#define HCLGE_TORUS_MAC_ID_MASK 0x3
+#define HCLGE_TOURS_TCX_MAP_TCY_INIT 0x1c6144
+#define HCLGE_TOURS_TCX_MAP_TCY_NODE0_INIT 0x1c6141
+
+#define HCLGE_VLAN_FE_NIC_INGRESS 0
+#define HCLGE_VLAN_FE_ROCEE_INGRESS 2
+
+#define HCLGE_TORUS_LPBK_DROP_EN 20
+#define HCLGE_TC2VLANPRI_MAPPING_EN 19
+#define HCLGE_LLDP_LAN_PAIR_EN 18
+#define HCLGE_MC_BC_LAN_PAIR_EN 17
+#define HCLGE_UC_LAN_PAIR_EN 16
+
+#define HCLGE_TORUS_TC1_DROP_EN BIT(26)
+
+#define HCLGE_TOURS_TCX_MAP_TCY_MASK 0x1c71c7
+
 struct hclge_pfc_storm_para_cmd {
 	__le32 dir;
 	__le32 enable;
@@ -29,8 +46,20 @@ struct hclge_notify_pkt_param_cmd {
 	u8 rsv[21];
 };
 
+struct hclge_torus_cfg_cmd {
+	u8 rsv[4];
+	__le32 lan_port_pair;
+	__le32 lan_fwd_tc_cfg;
+	__le32 pause_time_out;
+	__le32 pause_time_out_en;
+	__le32 torus_en;
+};
+
 enum hclge_ext_opcode_type {
+	HCLGE_OPC_CONFIG_SWITCH_PARAM = 0x1033,
+	HCLGE_OPC_CONFIG_VLAN_FILTER = 0x1100,
 	HCLGE_OPC_SET_NOTIFY_PKT = 0x180A,
+	HCLGE_OPC_CONFIG_1D_TORUS = 0x2300,
 	HCLGE_OPC_CFG_PAUSE_STORM_PARA = 0x7019,
 };
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 647b0ca14e1c..7a505d1195ef 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -944,6 +944,7 @@ struct hclge_dev {
 	struct irq_affinity_notify affinity_notify;
 	struct hclge_ptp *ptp;
 	struct hnae3_notify_pkt_param notify_param;
+	struct hnae3_torus_param torus_param;
 };
 
 /* VPort level vlan tag configuration for TX direction */
-- 
2.34.1

