From 4639dc08250c9f77bbbad67f81f3039d4d057519 Mon Sep 17 00:00:00 2001
From: liaoguojia <liaoguojia@huawei.com>
Date: Wed, 30 Nov 2022 18:23:36 +0800
Subject: [PATCH 188/283] net: hns3: refactor the debugfs for dumping FD tcam

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

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

On version HNAE3_DEVICE_VERSION_V2, the tcam table entry of the FD is
obtained by traversing the list recorded by the driver.

On version HNAE3_DEVICE_VERSION_V3, a new usage mode of FD is supported,
called Queue bond mode. In this mode, the hardware automatically creates
rules and the driver does not record the flow table entry.

So we needs to check the validity of the entry by traversing the entire
hardware entry to dump out the QB tcam table.

Signed-off-by: liaoguojia <liaoguojia@huawei.com>
Signed-off-by: Jiantao Xiao <xiaojiantao1@h-partners.com>
Reviewed-by: Yue Haibing <yuehaibing@huawei.com>
Reviewed-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>

 Conflicts:
	drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
	drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
---
 drivers/net/ethernet/hisilicon/hns3/hnae3.h   |   3 +
 .../hns3/hns3_common/hclge_comm_cmd.h         |   3 +
 .../hisilicon/hns3/hns3pf/hclge_debugfs.c     | 115 +++++++++++++++---
 3 files changed, 106 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 07db6d16abbe..f016bf08f297 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -101,6 +101,9 @@ enum HNAE3_DEV_CAP_BITS {
 	HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B,
 };
 
+#define hnae3_ae_dev_fd_supported(ae_dev) \
+		test_bit(HNAE3_DEV_SUPPORT_FD_B, (ae_dev)->caps)
+
 #define hnae3_dev_fd_supported(hdev) \
 	test_bit(HNAE3_DEV_SUPPORT_FD_B, (hdev)->ae_dev->caps)
 
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 52fc4b830772..ea30d94c081c 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
@@ -7,6 +7,9 @@
 
 #include "hnae3.h"
 
+#define HCLGE_COMM_CMD_FLAG_IN			BIT(0)
+#define HCLGE_COMM_CMD_FLAG_NEXT		BIT(2)
+#define HCLGE_COMM_CMD_FLAG_WR			BIT(3)
 #define HCLGE_COMM_CMD_FLAG_NO_INTR		BIT(4)
 
 #define HCLGE_COMM_SEND_SYNC(flag) \
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index 985e6677ea27..63cc42060a31 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -1525,8 +1525,7 @@ static int hclge_dbg_dump_mng_table(struct hclge_dev *hdev, char *buf, int len)
 #define HCLGE_DBG_TCAM_BUF_SIZE 256
 
 static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, bool sel_x,
-				  char *tcam_buf,
-				  struct hclge_dbg_tcam_msg tcam_msg)
+				  char *tcam_buf, u8 stage, u32 loc)
 {
 	struct hclge_fd_tcam_config_1_cmd *req1;
 	struct hclge_fd_tcam_config_2_cmd *req2;
@@ -1546,9 +1545,9 @@ static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, bool sel_x,
 	req2 = (struct hclge_fd_tcam_config_2_cmd *)desc[1].data;
 	req3 = (struct hclge_fd_tcam_config_3_cmd *)desc[2].data;
 
-	req1->stage  = tcam_msg.stage;
+	req1->stage  = stage;
 	req1->xy_sel = sel_x ? 1 : 0;
-	req1->index  = cpu_to_le32(tcam_msg.loc);
+	req1->index  = cpu_to_le32(loc);
 
 	ret = hclge_cmd_send(&hdev->hw, desc, 3);
 	if (ret)
@@ -1556,7 +1555,7 @@ static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, bool sel_x,
 
 	pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos,
 			 "read result tcam key %s(%u):\n", sel_x ? "x" : "y",
-			 tcam_msg.loc);
+			 loc);
 
 	/* tcam_data0 ~ tcam_data1 */
 	req = (u32 *)req1->tcam_data;
@@ -1601,7 +1600,6 @@ static int hclge_dbg_get_rules_location(struct hclge_dev *hdev, u16 *rule_locs)
 static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len)
 {
 	u32 rule_num = hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1];
-	struct hclge_dbg_tcam_msg tcam_msg;
 	int i, ret, rule_cnt;
 	u16 *rule_locs;
 	char *tcam_buf;
@@ -1636,10 +1634,8 @@ static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len)
 
 	ret = 0;
 	for (i = 0; i < rule_cnt; i++) {
-		tcam_msg.stage = HCLGE_FD_STAGE_1;
-		tcam_msg.loc = rule_locs[i];
-
-		ret = hclge_dbg_fd_tcam_read(hdev, true, tcam_buf, tcam_msg);
+		ret = hclge_dbg_fd_tcam_read(hdev, true, tcam_buf,
+					     HCLGE_FD_STAGE_1, rule_locs[i]);
 		if (ret) {
 			dev_err(&hdev->pdev->dev,
 				"failed to get fd tcam key x, ret = %d\n", ret);
@@ -1648,7 +1644,8 @@ static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len)
 
 		pos += scnprintf(buf + pos, len - pos, "%s", tcam_buf);
 
-		ret = hclge_dbg_fd_tcam_read(hdev, false, tcam_buf, tcam_msg);
+		ret = hclge_dbg_fd_tcam_read(hdev, false, tcam_buf,
+					     HCLGE_FD_STAGE_1, rule_locs[i]);
 		if (ret) {
 			dev_err(&hdev->pdev->dev,
 				"failed to get fd tcam key y, ret = %d\n", ret);
@@ -1664,6 +1661,86 @@ static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len)
 	return ret;
 }
 
+static int hclge_query_rules_valid(struct hclge_dev *hdev, u8 stage, u32 loc)
+{
+#define HCLGE_TCAM_SELECTION_X	1
+	struct hclge_fd_tcam_config_1_cmd *req1;
+	struct hclge_fd_tcam_config_2_cmd *req2;
+	struct hclge_fd_tcam_config_3_cmd *req3;
+	struct hclge_desc desc[3];
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_FD_TCAM_OP, true);
+	desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
+	hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_FD_TCAM_OP, true);
+	desc[1].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
+	hclge_cmd_setup_basic_desc(&desc[2], HCLGE_OPC_FD_TCAM_OP, true);
+
+	req1 = (struct hclge_fd_tcam_config_1_cmd *)desc[0].data;
+	req2 = (struct hclge_fd_tcam_config_2_cmd *)desc[1].data;
+	req3 = (struct hclge_fd_tcam_config_3_cmd *)desc[2].data;
+
+	req1->stage = stage;
+	req1->xy_sel = HCLGE_TCAM_SELECTION_X;
+	req1->index = cpu_to_le32(loc);
+
+	ret = hclge_cmd_send(&hdev->hw, desc, 3);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to read tcam status, ret = %d\n", ret);
+		return ret;
+	}
+
+	return req1->entry_vld;
+}
+
+static int hclge_dbg_dump_qb_tcam(struct hclge_dev *hdev, char *buf, int len)
+{
+	char *tcam_buf;
+	int pos = 0;
+	int ret = 0;
+	int i;
+
+	if (!hnae3_ae_dev_fd_supported(hdev->ae_dev)) {
+		dev_err(&hdev->pdev->dev,
+			"Only FD-supported dev supports dump fd tcam\n");
+		return -EOPNOTSUPP;
+	}
+
+	tcam_buf = kzalloc(HCLGE_DBG_TCAM_BUF_SIZE, GFP_KERNEL);
+	if (!tcam_buf)
+		return -ENOMEM;
+
+	for (i = 0; i < hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]; i++) {
+		if (hclge_query_rules_valid(hdev, HCLGE_FD_STAGE_1, i) <= 0)
+			continue;
+
+		ret = hclge_dbg_fd_tcam_read(hdev, true, tcam_buf,
+					     HCLGE_FD_STAGE_1, i);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"failed to get qb tcam key x, ret = %d\n", ret);
+			goto out;
+		}
+
+		pos += scnprintf(buf + pos, len - pos, "%s", tcam_buf);
+
+		ret = hclge_dbg_fd_tcam_read(hdev, false, tcam_buf,
+					     HCLGE_FD_STAGE_1, i);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"failed to get qb tcam key y, ret = %d\n", ret);
+			goto out;
+		}
+
+		pos += scnprintf(buf + pos, len - pos, "%s", tcam_buf);
+	}
+
+out:
+	kfree(tcam_buf);
+	return ret;
+}
+
 static int hclge_dbg_dump_fd_counter(struct hclge_dev *hdev, char *buf, int len)
 {
 	u8 func_num = pci_num_vf(hdev->pdev) + 1; /* pf and enabled vf num */
@@ -2286,6 +2363,14 @@ static int hclge_dbg_dump_mac_uc(struct hclge_dev *hdev, char *buf, int len)
 	return 0;
 }
 
+static int hclge_dbg_dump_tcam(struct hclge_dev *hdev, char *buf, int len)
+{
+	if (test_bit(HCLGE_STATE_HW_QB_ENABLE, &hdev->state))
+		return hclge_dbg_dump_qb_tcam(hdev, buf, len);
+	else
+		return hclge_dbg_dump_fd_tcam(hdev, buf, len);
+};
+
 static int hclge_dbg_dump_mac_mc(struct hclge_dev *hdev, char *buf, int len)
 {
 	hclge_dbg_dump_mac_list(hdev, buf, len, false);
@@ -2440,14 +2525,14 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = {
 		.cmd = HNAE3_DBG_CMD_REG_DCB,
 		.dbg_dump = hclge_dbg_dump_dcb,
 	},
-	{
-		.cmd = HNAE3_DBG_CMD_FD_TCAM,
-		.dbg_dump = hclge_dbg_dump_fd_tcam,
-	},
 	{
 		.cmd = HNAE3_DBG_CMD_MAC_TNL_STATUS,
 		.dbg_dump = hclge_dbg_dump_mac_tnl_status,
 	},
+	{
+		.cmd = HNAE3_DBG_CMD_FD_TCAM,
+		.dbg_dump = hclge_dbg_dump_tcam,
+	},
 	{
 		.cmd = HNAE3_DBG_CMD_SERV_INFO,
 		.dbg_dump = hclge_dbg_dump_serv_info,
-- 
2.34.1

