From 032dc6157f90eabc76f47b5a655ba7c356955c37 Mon Sep 17 00:00:00 2001
From: Hao Chen <chenhao418@huawei.com>
Date: Wed, 30 Nov 2022 18:23:35 +0800
Subject: [PATCH 209/283] net: hns3: PF supports to set and query lane_num by
 sysfs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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

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

When serdes lane support setting 25Gb/s、50Gb/s speed and user wants to
set port speed as 50Gb/s, it can be setted as one 50Gb/s serdes lane or
two 25Gb/s serdes lanes.

So, this patch adds support to query and set lane number by sysfs
to satisfy this scenario.

Signed-off-by: Hao Chen <chenhao418@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/Makefile
	drivers/net/ethernet/hisilicon/hns3/hnae3.h
	drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
	drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
	drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
	drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
---
 drivers/net/ethernet/hisilicon/hns3/Makefile  |  1 +
 .../hisilicon/hns3/hns3pf/hclge_cmd.h         |  7 +-
 .../hisilicon/hns3/hns3pf/hclge_main.c        | 24 +++--
 .../hisilicon/hns3/hns3pf/hclge_main.h        |  4 +-
 .../hisilicon/hns3/hns3pf/hclge_sysfs.c       | 91 +++++++++++++++++++
 5 files changed, 118 insertions(+), 9 deletions(-)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_sysfs.c

diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
index d0f56781b558..8a9c53f86dce 100644
--- a/drivers/net/ethernet/hisilicon/hns3/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -36,6 +36,7 @@ HCLGE_OBJ = 	hns3pf/hclge_main.o \
 			hns3pf/hclge_mdio.o \
 			hns3pf/hclge_debugfs.o \
 			hns3pf/hclge_tm.o \
+			hns3pf/hclge_sysfs.o \
 			hns3pf/hclge_mbx.o \
 			hns3pf/hclge_err.o \
 			hns3pf/hclge_ptp.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index a4599f717da5..38b82f87ec76 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -671,7 +671,9 @@ struct hclge_config_mac_speed_dup_cmd {
 
 #define HCLGE_CFG_MAC_SPEED_CHANGE_EN_B	0
 	u8 mac_change_fec_en;
-	u8 rsv[22];
+	u8 rsv[4];
+	u8 lane_num;
+	u8 rsv1[17];
 };
 
 #define HCLGE_RING_ID_MASK		GENMASK(9, 0)
@@ -699,7 +701,8 @@ struct hclge_sfp_info_cmd {
 	__le32 speed_ability; /* speed ability for current media */
 	__le32 module_type;
 	u8 fec_ability;
-	u8 rsv[7];
+	u8 lane_num;
+	u8 rsv[6];
 };
 
 struct hclge_port_fault_cmd {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 68158219e8c6..898c724a53b8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -2631,7 +2631,7 @@ static u8 hclge_check_speed_dup(u8 duplex, int speed)
 }
 
 int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
-				      u8 duplex)
+			       u8 duplex, u8 lane_num)
 {
 	struct hclge_config_mac_speed_dup_cmd *req;
 	struct hclge_desc desc;
@@ -2688,6 +2688,7 @@ int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
 
 	hnae3_set_bit(req->mac_change_fec_en, HCLGE_CFG_MAC_SPEED_CHANGE_EN_B,
 		      1);
+	req->lane_num = lane_num;
 
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret) {
@@ -2709,7 +2710,7 @@ int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
 	    mac->duplex == duplex)
 		return 0;
 
-	ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex);
+	ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex, 0);
 	if (ret)
 		return ret;
 
@@ -2874,7 +2875,8 @@ static int hclge_mac_init(struct hclge_dev *hdev)
 	hdev->support_sfp_query = true;
 	hdev->hw.mac.duplex = HCLGE_MAC_FULL;
 	ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
-					 hdev->hw.mac.duplex);
+					 hdev->hw.mac.duplex,
+					 hdev->hw.mac.lane_num);
 	if (ret)
 		return ret;
 
@@ -3202,6 +3204,7 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac)
 		mac->autoneg = resp->autoneg;
 		mac->support_autoneg = resp->autoneg_ability;
 		mac->speed_type = QUERY_ACTIVE_SPEED;
+		mac->lane_num = resp->lane_num;
 		if (!resp->active_fec)
 			mac->fec_mode = 0;
 		else
@@ -7592,7 +7595,7 @@ static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en)
 	}
 
 	duplex = en ? DUPLEX_FULL : hdev->hw.mac.duplex;
-	ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, duplex);
+	ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, duplex, hdev->hw.mac.lane_num);
 	if (ret)
 		return ret;
 
@@ -11470,13 +11473,19 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
 		goto err_mdiobus_unreg;
 	}
 
+	ret = hclge_register_sysfs(hdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register sysfs, ret = %d\n", ret);
+		goto err_mdiobus_unreg;
+	}
+
 	ret = hclge_ptp_init(hdev);
 	if (ret)
-		goto err_mdiobus_unreg;
+		goto err_sysfs_unregister;
 
 	ret = hclge_update_port_info(hdev);
 	if (ret)
-		goto err_mdiobus_unreg;
+		goto err_sysfs_unregister;
 
 	INIT_KFIFO(hdev->mac_tnl_log);
 
@@ -11529,6 +11538,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
 
 	return 0;
 
+err_sysfs_unregister:
+	hclge_unregister_sysfs(hdev);
 err_mdiobus_unreg:
 	if (hdev->hw.mac.phydev)
 		mdiobus_unregister(hdev->hw.mac.mdio_bus);
@@ -11912,6 +11923,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
 	struct hclge_dev *hdev = ae_dev->priv;
 	struct hclge_mac *mac = &hdev->hw.mac;
 
+	hclge_unregister_sysfs(hdev);
 	hclge_reset_vf_rate(hdev);
 	hclge_clear_vf_vlan(hdev);
 	hclge_misc_affinity_teardown(hdev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index c2fcbf658bfa..df2b56b83084 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -296,6 +296,7 @@ struct hclge_mac {
 	u8 duplex_last;
 	u8 support_autoneg;
 	u8 speed_type;	/* 0: sfp speed, 1: active speed */
+	u8 lane_num;
 	u32 speed;
 	u32 max_speed;
 	u32 speed_ability; /* speed ability supported by current media */
@@ -1168,7 +1169,6 @@ int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en);
 int hclge_mac_update_stats(struct hclge_dev *hdev);
 int hclge_register_sysfs(struct hclge_dev *hdev);
 void hclge_unregister_sysfs(struct hclge_dev *hdev);
-int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed, u8 duplex);
 int hclge_get_wol_supported_mode(struct hclge_dev *hdev, u32 *wol_supported);
 int hclge_get_wol_cfg(struct hclge_dev *hdev, u32 *mode);
 struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf);
@@ -1177,4 +1177,6 @@ void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle);
 void hclge_get_media_type(struct hnae3_handle *handle, u8 *media_type,
 			  u8 *module_type);
 int hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable);
+int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed, u8 duplex,
+			       u8 lane_num);
 #endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_sysfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_sysfs.c
new file mode 100644
index 000000000000..b7cc89c3f6d8
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_sysfs.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
+
+#include "hnae3.h"
+#include "hclge_main.h"
+
+static ssize_t lane_num_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
+	struct hclge_dev *hdev = ae_dev->priv;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", hdev->hw.mac.lane_num);
+}
+
+static ssize_t lane_num_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+#define HCLGE_CONVERSION_NUM	10  /* Convert string to decimal number */
+
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
+	struct hclge_dev *hdev = ae_dev->priv;
+	u8 lane_num, duplex;
+	u32 speed;
+	int ret;
+
+	ret = kstrtou8(buf, HCLGE_CONVERSION_NUM, &lane_num);
+	if (ret) {
+		dev_err(dev, "input params of lane number format unmatch.\n");
+		return -EINVAL;
+	}
+
+	if (!lane_num || lane_num > 8 || !is_power_of_2(lane_num)) {
+		dev_err(dev, "lane number only supports setting 1, 2, 4, 8.\n");
+		return -EINVAL;
+	}
+
+	rtnl_lock();
+
+	if (hdev->hw.mac.support_autoneg && hdev->hw.mac.autoneg) {
+		ret = count;
+		goto out;
+	}
+
+	if (lane_num == hdev->hw.mac.lane_num) {
+		dev_info(dev, "setting lane number not changed.\n");
+		ret = count;
+		goto out;
+	}
+
+	speed = hdev->hw.mac.speed;
+	duplex = hdev->hw.mac.duplex;
+
+	ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex, lane_num);
+	if (!ret)
+		ret = count;
+
+out:
+	rtnl_unlock();
+	return ret;
+}
+
+static DEVICE_ATTR_RW(lane_num);
+
+static const struct device_attribute *hclge_hw_attrs_list[] = {
+	&dev_attr_lane_num,
+};
+
+int hclge_register_sysfs(struct hclge_dev *hdev)
+{
+	int ret;
+
+	if (!hnae3_ae_dev_lane_num_supported(hdev->ae_dev))
+		return 0;
+
+	ret = device_create_file(&hdev->pdev->dev, hclge_hw_attrs_list[0]);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"failed to create node %s, ret = %d.\n",
+			hclge_hw_attrs_list[0]->attr.name, ret);
+
+	return ret;
+}
+
+void hclge_unregister_sysfs(struct hclge_dev *hdev)
+{
+	device_remove_file(&hdev->pdev->dev, hclge_hw_attrs_list[0]);
+}
-- 
2.34.1

