From 61839f9ee3c7cff5f4f31b75edb5dbf46c2774f5 Mon Sep 17 00:00:00 2001
From: wangpeiyang <wangpeiyang1@huawei.com>
Date: Fri, 21 Apr 2023 17:01:57 +0800
Subject: [PATCH 205/283] net: hns3: add support set mac state

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

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

The patch provides a customized interface to modify the MAC mode.

Signed-off-by: wangpeiyang <wangpeiyang1@huawei.com>
Signed-off-by: shaojijie <shaojijie@huawei.com>
Signed-off-by: Jiantao Xiao <xiaojiantao1@h-partners.com>
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
---
 .../net/ethernet/hisilicon/hns3/hnae3_ext.h   |  1 +
 .../net/ethernet/hisilicon/hns3/hns3_ext.c    |  7 ++++
 .../net/ethernet/hisilicon/hns3/hns3_ext.h    |  1 +
 .../hisilicon/hns3/hns3pf/hclge_ext.c         | 34 +++++++++++++++++++
 .../hisilicon/hns3/hns3pf/hclge_main.c        |  8 +++--
 .../hisilicon/hns3/hns3pf/hclge_main.h        |  1 +
 include/linux/phy.h                           |  9 +++++
 7 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h b/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h
index e326267d9d2e..36eff4b0a228 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h
@@ -47,6 +47,7 @@ enum hnae3_ext_opcode {
 	HNAE3_EXT_OPC_GET_HILINK_REF_LOS,
 	HNAE3_EXT_OPC_GET_PORT_FAULT_STATUS,
 	HNAE3_EXT_OPC_GET_PORT_TYPE,
+	HNAE3_EXT_OPC_SET_MAC_STATE,
 };
 
 struct hnae3_pfc_storm_para {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c
index 7e0048a7a37a..da1473cbf42b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c
@@ -403,3 +403,10 @@ int nic_get_port_wire_type(struct net_device *ndev, u32 *wire_type)
 				  wire_type, sizeof(*wire_type));
 }
 EXPORT_SYMBOL(nic_get_port_wire_type);
+
+int nic_set_mac_state(struct net_device *ndev, int enable)
+{
+	return nic_invoke_pri_ops(ndev, HNAE3_EXT_OPC_SET_MAC_STATE,
+				  &enable, sizeof(enable));
+}
+EXPORT_SYMBOL(nic_set_mac_state);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h
index baa3cda8b671..4c57ddb011c3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h
@@ -54,4 +54,5 @@ int nic_set_pfc_time_cfg(struct net_device *ndev, u16 time);
 int nic_get_port_fault_status(struct net_device *ndev,
 			      u32 fault_type, u32 *status);
 int nic_get_port_wire_type(struct net_device *ndev, u32 *wire_type);
+int nic_set_mac_state(struct net_device *ndev, int enable);
 #endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c
index eac784e243f5..bf59a796a2c6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c
@@ -605,6 +605,39 @@ static int hclge_get_port_wire_type(struct hclge_dev *hdev, void *data,
 	return 0;
 }
 
+static void hclge_set_phy_state(struct hclge_dev *hdev, bool enable)
+{
+	struct phy_device *phydev = hdev->hw.mac.phydev;
+
+	if (!phydev)
+		return;
+
+	if (enable && (phydev->state == PHY_READY ||
+		       phydev->state == PHY_HALTED))
+		phy_start(phydev);
+	else if (!enable && (phy_is_started(phydev) ||
+			     phydev->state == PHY_DOWN))
+		phy_stop(phydev);
+}
+
+static int hclge_set_mac_state(struct hclge_dev *hdev, void *data,
+			       size_t length)
+{
+	bool enable;
+	int ret;
+
+	if (length != sizeof(int))
+		return -EINVAL;
+
+	enable = !!*(int *)data;
+	ret = hclge_cfg_mac_mode(hdev, enable);
+
+	if (!ret && !hclge_comm_dev_phy_imp_supported(hdev->ae_dev))
+		hclge_set_phy_state(hdev, enable);
+
+	return ret;
+}
+
 static void hclge_ext_resotre_config(struct hclge_dev *hdev)
 {
 	if (hdev->reset_type != HNAE3_IMP_RESET &&
@@ -773,6 +806,7 @@ static const hclge_priv_ops_fn hclge_ext_func_arr[] = {
 	[HNAE3_EXT_OPC_GET_HILINK_REF_LOS] = hclge_get_hilink_ref_los,
 	[HNAE3_EXT_OPC_GET_PORT_FAULT_STATUS] = hclge_get_port_fault_status,
 	[HNAE3_EXT_OPC_GET_PORT_TYPE] = hclge_get_port_wire_type,
+	[HNAE3_EXT_OPC_SET_MAC_STATE] = hclge_set_mac_state,
 };
 
 int hclge_ext_ops_handle(struct hnae3_handle *handle, int opcode,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 4e7f16f2c0b1..68158219e8c6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7290,7 +7290,7 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
 	}
 }
 
-static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
+int hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
 {
 	struct hclge_desc desc;
 	struct hclge_config_mac_mode_cmd *req =
@@ -7317,8 +7317,10 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
 
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret)
-		dev_err(&hdev->pdev->dev,
-			"mac enable fail, ret =%d.\n", ret);
+		dev_err(&hdev->pdev->dev, "failed to %s mac, ret = %d.\n",
+			enable ? "enable" : "disable", ret);
+
+	return ret;
 }
 
 static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index e22702108846..c2fcbf658bfa 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -1176,4 +1176,5 @@ void hclge_reset_task_schedule(struct hclge_dev *hdev);
 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);
 #endif
diff --git a/include/linux/phy.h b/include/linux/phy.h
index d428623582e5..03eb46c632da 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -694,6 +694,15 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
 
 void phy_resolve_aneg_linkmode(struct phy_device *phydev);
 
+/**
+ * phy_is_started - Convenience function to check whether PHY is started
+ * @phydev: The phy_device struct
+ */
+static inline bool phy_is_started(struct phy_device *phydev)
+{
+	return phydev->state >= PHY_UP;
+}
+
 /**
  * phy_read_mmd - Convenience function for reading a register
  * from an MMD on a given PHY.
-- 
2.34.1

