Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1675534 > unrolled thread

[PATCH NET V6 0/2] Add loopback support in phy_driver and hns ethtool fix

Started byLin Yun Sheng <linyunsheng@huawei.com>
First post2017-06-27 12:40 +0200
Last post2017-06-27 12:40 +0200
Articles 5 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH NET V6 0/2] Add loopback support in phy_driver and hns ethtool fix Lin Yun Sheng <linyunsheng@huawei.com> - 2017-06-27 12:40 +0200
    [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework Lin Yun Sheng <linyunsheng@huawei.com> - 2017-06-27 12:40 +0200
      RE: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy  framework Madalin-cristian Bucur <madalin.bucur@nxp.com> - 2017-06-27 13:50 +0200
        Re: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy  framework Yunsheng Lin <linyunsheng@huawei.com> - 2017-06-28 02:40 +0200
    [PATCH NET V6 2/2] net: hns: Use phy_driver to setup Phy loopback Lin Yun Sheng <linyunsheng@huawei.com> - 2017-06-27 12:40 +0200

#1675534 — [PATCH NET V6 0/2] Add loopback support in phy_driver and hns ethtool fix

FromLin Yun Sheng <linyunsheng@huawei.com>
Date2017-06-27 12:40 +0200
Subject[PATCH NET V6 0/2] Add loopback support in phy_driver and hns ethtool fix
Message-ID<tWW4x-7Dy-7@gated-at.bofh.it>
This Patch Set add set_loopback in phy_driver and use it to setup loopback
when doing ethtool phy self_test.

Patch V6:
	Fix Or'ing error code in __lb_setup.

Patch V5:
	Removing non loopback related code change.

Patch V4:
	1. Remove c45 checking
	2. Add -ENOTSUPP when function pointer is null,
	   take mutex in phy_loopback.

Patch V3:
	Calling phy_loopback enable and disable in pair in hns mac driver.

Patch V2:
	1. Add phy_loopback in phy_device.c.
	2. Do error checking and do the read and write once in
	   genphy_loopback.
	3. Remove gen10g_loopback in phy_device.c.

Patch V1:
	Initial Submit

Lin Yun Sheng (2):
  net: phy: Add phy loopback support in net phy framework
  net: hns: Use phy_driver to setup Phy loopback

 drivers/net/ethernet/hisilicon/hns/hnae.h        |   1 +
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 102 +++++++----------------
 drivers/net/phy/marvell.c                        |   1 +
 drivers/net/phy/phy_device.c                     |  51 ++++++++++++
 include/linux/phy.h                              |   5 ++
 5 files changed, 89 insertions(+), 71 deletions(-)

-- 
1.9.1

[toc] | [next] | [standalone]


#1675536 — [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework

FromLin Yun Sheng <linyunsheng@huawei.com>
Date2017-06-27 12:40 +0200
Subject[PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework
Message-ID<tWW4x-7Dy-25@gated-at.bofh.it>
In reply to#1675534
This patch add set_loopback in phy_driver, which is used by Mac
driver to enable or disable a phy. it also add a generic
genphy_loopback function, which use BMCR loopback bit to enable
or disable a phy.

Signed-off-by: Lin Yun Sheng <linyunsheng@huawei.com>
---
 drivers/net/phy/marvell.c    |  1 +
 drivers/net/phy/phy_device.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/phy.h          |  5 +++++
 3 files changed, 57 insertions(+)

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 57297ba..01a1586 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -2094,6 +2094,7 @@ static int m88e1510_probe(struct phy_device *phydev)
 		.get_sset_count = marvell_get_sset_count,
 		.get_strings = marvell_get_strings,
 		.get_stats = marvell_get_stats,
+		.set_loopback = genphy_loopback,
 	},
 	{
 		.phy_id = MARVELL_PHY_ID_88E1540,
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 1219eea..1e08d62 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1123,6 +1123,39 @@ int phy_resume(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_resume);
 
+int phy_loopback(struct phy_device *phydev, bool enable)
+{
+	struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+	int ret = 0;
+
+	mutex_lock(&phydev->lock);
+
+	if (enable && phydev->loopback_enabled) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!enable && !phydev->loopback_enabled) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (phydev->drv && phydrv->set_loopback)
+		ret = phydrv->set_loopback(phydev, enable);
+	else
+		ret = -EOPNOTSUPP;
+
+	if (ret)
+		goto out;
+
+	phydev->loopback_enabled = enable;
+
+out:
+	mutex_unlock(&phydev->lock);
+	return ret;
+}
+EXPORT_SYMBOL(phy_loopback);
+
 /* Generic PHY support and helper functions */
 
 /**
@@ -1628,6 +1661,23 @@ static int gen10g_resume(struct phy_device *phydev)
 	return 0;
 }
 
+int genphy_loopback(struct phy_device *phydev, bool enable)
+{
+	int value;
+
+	value = phy_read(phydev, MII_BMCR);
+	if (value < 0)
+		return value;
+
+	if (enable)
+		value |= BMCR_LOOPBACK;
+	else
+		value &= ~BMCR_LOOPBACK;
+
+	return phy_write(phydev, MII_BMCR, value);
+}
+EXPORT_SYMBOL(genphy_loopback);
+
 static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
 	/* The default values for phydev->supported are provided by the PHY
@@ -1874,6 +1924,7 @@ void phy_drivers_unregister(struct phy_driver *drv, int n)
 	.read_status	= genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
+	.set_loopback	= genphy_loopback,
 }, {
 	.phy_id         = 0xffffffff,
 	.phy_id_mask    = 0xffffffff,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e76e4ad..49c903dc 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -364,6 +364,7 @@ struct phy_c45_device_ids {
  * is_pseudo_fixed_link: Set to true if this phy is an Ethernet switch, etc.
  * has_fixups: Set to true if this phy has fixups/quirks.
  * suspended: Set to true if this phy has been suspended successfully.
+ * loopback_enabled: Set true if this phy has been loopbacked successfully.
  * state: state of the PHY for management purposes
  * dev_flags: Device-specific flags used by the PHY driver.
  * link_timeout: The number of timer firings to wait before the
@@ -400,6 +401,7 @@ struct phy_device {
 	bool is_pseudo_fixed_link;
 	bool has_fixups;
 	bool suspended;
+	bool loopback_enabled;
 
 	enum phy_state state;
 
@@ -639,6 +641,7 @@ struct phy_driver {
 	int (*set_tunable)(struct phy_device *dev,
 			    struct ethtool_tunable *tuna,
 			    const void *data);
+	int (*set_loopback)(struct phy_device *dev, bool enable);
 };
 #define to_phy_driver(d) container_of(to_mdio_common_driver(d),		\
 				      struct phy_driver, mdiodrv)
@@ -774,6 +777,7 @@ static inline void phy_device_free(struct phy_device *phydev) { }
 int phy_init_hw(struct phy_device *phydev);
 int phy_suspend(struct phy_device *phydev);
 int phy_resume(struct phy_device *phydev);
+int phy_loopback(struct phy_device *phydev, bool enable);
 struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
 			      phy_interface_t interface);
 struct phy_device *phy_find_first(struct mii_bus *bus);
@@ -825,6 +829,7 @@ void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
 int genphy_read_status(struct phy_device *phydev);
 int genphy_suspend(struct phy_device *phydev);
 int genphy_resume(struct phy_device *phydev);
+int genphy_loopback(struct phy_device *phydev, bool enable);
 int genphy_soft_reset(struct phy_device *phydev);
 static inline int genphy_no_soft_reset(struct phy_device *phydev)
 {
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1675591 — RE: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework

FromMadalin-cristian Bucur <madalin.bucur@nxp.com>
Date2017-06-27 13:50 +0200
SubjectRE: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework
Message-ID<tWXai-8mt-21@gated-at.bofh.it>
In reply to#1675536
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Lin Yun Sheng
> Sent: Tuesday, June 27, 2017 2:01 PM
> To: davem@davemloft.net; andrew@lunn.ch; f.fainelli@gmail.com
> Cc: huangdaode@hisilicon.com; xuwei5@hisilicon.com;
> liguozhu@hisilicon.com; Yisen.Zhuang@huawei.com;
> gabriele.paoloni@huawei.com; john.garry@huawei.com; linuxarm@huawei.com;
> yisen.zhuang@huawei.com; salil.mehta@huawei.com; lipeng321@huawei.com;
> tremyfr@gmail.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy
> framework
> 
> This patch add set_loopback in phy_driver, which is used by Mac
> driver to enable or disable a phy. it also add a generic
> genphy_loopback function, which use BMCR loopback bit to enable
> or disable a phy.

"disable a phy" or disable the PHY loopback function?

> 
> Signed-off-by: Lin Yun Sheng <linyunsheng@huawei.com>
> ---
>  drivers/net/phy/marvell.c    |  1 +
>  drivers/net/phy/phy_device.c | 51
> ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/phy.h          |  5 +++++
>  3 files changed, 57 insertions(+)
> 
> diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
> index 57297ba..01a1586 100644
> --- a/drivers/net/phy/marvell.c
> +++ b/drivers/net/phy/marvell.c
> @@ -2094,6 +2094,7 @@ static int m88e1510_probe(struct phy_device *phydev)
>  		.get_sset_count = marvell_get_sset_count,
>  		.get_strings = marvell_get_strings,
>  		.get_stats = marvell_get_stats,
> +		.set_loopback = genphy_loopback,
>  	},
>  	{
>  		.phy_id = MARVELL_PHY_ID_88E1540,
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 1219eea..1e08d62 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -1123,6 +1123,39 @@ int phy_resume(struct phy_device *phydev)
>  }
>  EXPORT_SYMBOL(phy_resume);
> 
> +int phy_loopback(struct phy_device *phydev, bool enable)
> +{
> +	struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
> +	int ret = 0;
> +
> +	mutex_lock(&phydev->lock);
> +
> +	if (enable && phydev->loopback_enabled) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	if (!enable && !phydev->loopback_enabled) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +

if (enable == phydev->loopback_enabled)

> +	if (phydev->drv && phydrv->set_loopback)
> +		ret = phydrv->set_loopback(phydev, enable);
> +	else
> +		ret = -EOPNOTSUPP;
> +
> +	if (ret)
> +		goto out;
> +
> +	phydev->loopback_enabled = enable;
> +
> +out:
> +	mutex_unlock(&phydev->lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL(phy_loopback);
> +
>  /* Generic PHY support and helper functions */
> 
>  /**
> @@ -1628,6 +1661,23 @@ static int gen10g_resume(struct phy_device *phydev)
>  	return 0;
>  }
> 
> +int genphy_loopback(struct phy_device *phydev, bool enable)
> +{
> +	int value;
> +
> +	value = phy_read(phydev, MII_BMCR);
> +	if (value < 0)
> +		return value;
> +
> +	if (enable)
> +		value |= BMCR_LOOPBACK;
> +	else
> +		value &= ~BMCR_LOOPBACK;
> +
> +	return phy_write(phydev, MII_BMCR, value);
> +}
> +EXPORT_SYMBOL(genphy_loopback);
> +
>  static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
>  {
>  	/* The default values for phydev->supported are provided by the PHY
> @@ -1874,6 +1924,7 @@ void phy_drivers_unregister(struct phy_driver *drv,
> int n)
>  	.read_status	= genphy_read_status,
>  	.suspend	= genphy_suspend,
>  	.resume		= genphy_resume,
> +	.set_loopback	= genphy_loopback,
>  }, {
>  	.phy_id         = 0xffffffff,
>  	.phy_id_mask    = 0xffffffff,
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index e76e4ad..49c903dc 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -364,6 +364,7 @@ struct phy_c45_device_ids {
>   * is_pseudo_fixed_link: Set to true if this phy is an Ethernet switch,
> etc.
>   * has_fixups: Set to true if this phy has fixups/quirks.
>   * suspended: Set to true if this phy has been suspended successfully.
> + * loopback_enabled: Set true if this phy has been loopbacked
> successfully.
>   * state: state of the PHY for management purposes
>   * dev_flags: Device-specific flags used by the PHY driver.
>   * link_timeout: The number of timer firings to wait before the
> @@ -400,6 +401,7 @@ struct phy_device {
>  	bool is_pseudo_fixed_link;
>  	bool has_fixups;
>  	bool suspended;
> +	bool loopback_enabled;
> 
>  	enum phy_state state;
> 
> @@ -639,6 +641,7 @@ struct phy_driver {
>  	int (*set_tunable)(struct phy_device *dev,
>  			    struct ethtool_tunable *tuna,
>  			    const void *data);
> +	int (*set_loopback)(struct phy_device *dev, bool enable);
>  };
>  #define to_phy_driver(d) container_of(to_mdio_common_driver(d),		\
>  				      struct phy_driver, mdiodrv)
> @@ -774,6 +777,7 @@ static inline void phy_device_free(struct phy_device
> *phydev) { }
>  int phy_init_hw(struct phy_device *phydev);
>  int phy_suspend(struct phy_device *phydev);
>  int phy_resume(struct phy_device *phydev);
> +int phy_loopback(struct phy_device *phydev, bool enable);
>  struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
>  			      phy_interface_t interface);
>  struct phy_device *phy_find_first(struct mii_bus *bus);
> @@ -825,6 +829,7 @@ void phy_attached_print(struct phy_device *phydev,
> const char *fmt, ...)
>  int genphy_read_status(struct phy_device *phydev);
>  int genphy_suspend(struct phy_device *phydev);
>  int genphy_resume(struct phy_device *phydev);
> +int genphy_loopback(struct phy_device *phydev, bool enable);
>  int genphy_soft_reset(struct phy_device *phydev);
>  static inline int genphy_no_soft_reset(struct phy_device *phydev)
>  {
> --
> 1.9.1

Madalin

[toc] | [prev] | [next] | [standalone]


#1676294 — Re: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework

FromYunsheng Lin <linyunsheng@huawei.com>
Date2017-06-28 02:40 +0200
SubjectRe: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy framework
Message-ID<tX9bs-86t-11@gated-at.bofh.it>
In reply to#1675591
Hi, Madalin

On 2017/6/27 19:48, Madalin-cristian Bucur wrote:
>> -----Original Message-----
>> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
>> On Behalf Of Lin Yun Sheng
>> Sent: Tuesday, June 27, 2017 2:01 PM
>> To: davem@davemloft.net; andrew@lunn.ch; f.fainelli@gmail.com
>> Cc: huangdaode@hisilicon.com; xuwei5@hisilicon.com;
>> liguozhu@hisilicon.com; Yisen.Zhuang@huawei.com;
>> gabriele.paoloni@huawei.com; john.garry@huawei.com; linuxarm@huawei.com;
>> yisen.zhuang@huawei.com; salil.mehta@huawei.com; lipeng321@huawei.com;
>> tremyfr@gmail.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
>> Subject: [PATCH NET V6 1/2] net: phy: Add phy loopback support in net phy
>> framework
>>
>> This patch add set_loopback in phy_driver, which is used by Mac
>> driver to enable or disable a phy. it also add a generic
>> genphy_loopback function, which use BMCR loopback bit to enable
>> or disable a phy.
> 
> "disable a phy" or disable the PHY loopback function?
It should be disable the PHY loopback function, thanks for pointing out.

> 

>> @@ -1123,6 +1123,39 @@ int phy_resume(struct phy_device *phydev)
>>  }
>>  EXPORT_SYMBOL(phy_resume);
>>
>> +int phy_loopback(struct phy_device *phydev, bool enable)
>> +{
>> +	struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
>> +	int ret = 0;
>> +
>> +	mutex_lock(&phydev->lock);
>> +
>> +	if (enable && phydev->loopback_enabled) {
>> +		ret = -EBUSY;
>> +		goto out;
>> +	}
>> +
>> +	if (!enable && !phydev->loopback_enabled) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
> 
> if (enable == phydev->loopback_enabled)
One if statement don't work here, it returns different error code.

> 
>> +	if (phydev->drv && phydrv->set_loopback)
>> +		ret = phydrv->set_loopback(phydev, enable);
>> +	else
>> +		ret = -EOPNOTSUPP;
>> +
>> +	if (ret)
>> +		goto out;
>> +
>> +	phydev->loopback_enabled = enable;
>> +
>> +out:
>> +	mutex_unlock(&phydev->lock);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL(phy_loopback);
>> +
>

Best Regards
Yunsheng

[toc] | [prev] | [next] | [standalone]


#1675537 — [PATCH NET V6 2/2] net: hns: Use phy_driver to setup Phy loopback

FromLin Yun Sheng <linyunsheng@huawei.com>
Date2017-06-27 12:40 +0200
Subject[PATCH NET V6 2/2] net: hns: Use phy_driver to setup Phy loopback
Message-ID<tWW4x-7Dy-23@gated-at.bofh.it>
In reply to#1675534
Use function set_loopback in phy_driver to setup phy loopback
when doing ethtool self test.

Signed-off-by: Lin Yun Sheng <linyunsheng@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns/hnae.h        |   1 +
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 102 +++++++----------------
 2 files changed, 32 insertions(+), 71 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 04211ac..7ba653a 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -360,6 +360,7 @@ enum hnae_loop {
 	MAC_INTERNALLOOP_MAC = 0,
 	MAC_INTERNALLOOP_SERDES,
 	MAC_INTERNALLOOP_PHY,
+	MAC_LOOP_PHY_NONE,
 	MAC_LOOP_NONE,
 };
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index e95795b..7fdd26e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -259,67 +259,24 @@ static int hns_nic_set_link_ksettings(struct net_device *net_dev,
 
 static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
 {
-#define COPPER_CONTROL_REG 0
-#define PHY_POWER_DOWN BIT(11)
-#define PHY_LOOP_BACK BIT(14)
-	u16 val = 0;
-
-	if (phy_dev->is_c45) /* c45 branch adding for XGE PHY */
-		return -ENOTSUPP;
+	int err;
 
 	if (en) {
-		/* speed : 1000M */
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 2);
-		phy_write(phy_dev, 21, 0x1046);
-
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
-		/* Force Master */
-		phy_write(phy_dev, 9, 0x1F00);
-
-		/* Soft-reset */
-		phy_write(phy_dev, 0, 0x9140);
-		/* If autoneg disabled,two soft-reset operations */
-		phy_write(phy_dev, 0, 0x9140);
-
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);
-
-		/* Default is 0x0400 */
-		phy_write(phy_dev, 1, 0x418);
-
-		/* Force 1000M Link, Default is 0x0200 */
-		phy_write(phy_dev, 7, 0x20C);
-
-		/* Powerup Fiber */
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 1);
-		val = phy_read(phy_dev, COPPER_CONTROL_REG);
-		val &= ~PHY_POWER_DOWN;
-		phy_write(phy_dev, COPPER_CONTROL_REG, val);
-
-		/* Enable Phy Loopback */
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
-		val = phy_read(phy_dev, COPPER_CONTROL_REG);
-		val |= PHY_LOOP_BACK;
-		val &= ~PHY_POWER_DOWN;
-		phy_write(phy_dev, COPPER_CONTROL_REG, val);
+		err = phy_resume(phy_dev);
+		if (err)
+			goto out;
+
+		err = phy_loopback(phy_dev, true);
 	} else {
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);
-		phy_write(phy_dev, 1, 0x400);
-		phy_write(phy_dev, 7, 0x200);
-
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 1);
-		val = phy_read(phy_dev, COPPER_CONTROL_REG);
-		val |= PHY_POWER_DOWN;
-		phy_write(phy_dev, COPPER_CONTROL_REG, val);
-
-		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
-		phy_write(phy_dev, 9, 0xF00);
-
-		val = phy_read(phy_dev, COPPER_CONTROL_REG);
-		val &= ~PHY_LOOP_BACK;
-		val |= PHY_POWER_DOWN;
-		phy_write(phy_dev, COPPER_CONTROL_REG, val);
+		err = phy_loopback(phy_dev, false);
+		if (err)
+			goto out;
+
+		err = phy_suspend(phy_dev);
 	}
-	return 0;
+
+out:
+	return err;
 }
 
 static int __lb_setup(struct net_device *ndev,
@@ -332,10 +289,9 @@ static int __lb_setup(struct net_device *ndev,
 
 	switch (loop) {
 	case MAC_INTERNALLOOP_PHY:
-		if ((phy_dev) && (!phy_dev->is_c45)) {
-			ret = hns_nic_config_phy_loopback(phy_dev, 0x1);
-			ret |= h->dev->ops->set_loopback(h, loop, 0x1);
-		}
+		ret = hns_nic_config_phy_loopback(phy_dev, 0x1);
+		if (!ret)
+			ret = h->dev->ops->set_loopback(h, loop, 0x1);
 		break;
 	case MAC_INTERNALLOOP_MAC:
 		if ((h->dev->ops->set_loopback) &&
@@ -346,17 +302,17 @@ static int __lb_setup(struct net_device *ndev,
 		if (h->dev->ops->set_loopback)
 			ret = h->dev->ops->set_loopback(h, loop, 0x1);
 		break;
+	case MAC_LOOP_PHY_NONE:
+		ret = hns_nic_config_phy_loopback(phy_dev, 0x0);
 	case MAC_LOOP_NONE:
-		if ((phy_dev) && (!phy_dev->is_c45))
-			ret |= hns_nic_config_phy_loopback(phy_dev, 0x0);
-
-		if (h->dev->ops->set_loopback) {
+		if (!ret && h->dev->ops->set_loopback) {
 			if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
-				ret |= h->dev->ops->set_loopback(h,
+				ret = h->dev->ops->set_loopback(h,
 					MAC_INTERNALLOOP_MAC, 0x0);
 
-			ret |= h->dev->ops->set_loopback(h,
-				MAC_INTERNALLOOP_SERDES, 0x0);
+			if (!ret)
+				ret = h->dev->ops->set_loopback(h,
+					MAC_INTERNALLOOP_SERDES, 0x0);
 		}
 		break;
 	default:
@@ -582,13 +538,16 @@ static int __lb_run_test(struct net_device *ndev,
 	return ret_val;
 }
 
-static int __lb_down(struct net_device *ndev)
+static int __lb_down(struct net_device *ndev, enum hnae_loop loop)
 {
 	struct hns_nic_priv *priv = netdev_priv(ndev);
 	struct hnae_handle *h = priv->ae_handle;
 	int ret;
 
-	ret = __lb_setup(ndev, MAC_LOOP_NONE);
+	if (loop == MAC_INTERNALLOOP_PHY)
+		ret = __lb_setup(ndev, MAC_LOOP_PHY_NONE);
+	else
+		ret = __lb_setup(ndev, MAC_LOOP_NONE);
 	if (ret)
 		netdev_err(ndev, "%s: __lb_setup return error(%d)!\n",
 			   __func__,
@@ -644,7 +603,8 @@ static void hns_nic_self_test(struct net_device *ndev,
 			if (!data[test_index]) {
 				data[test_index] = __lb_run_test(
 					ndev, (enum hnae_loop)st_param[i][0]);
-				(void)__lb_down(ndev);
+				(void)__lb_down(ndev,
+						(enum hnae_loop)st_param[i][0]);
 			}
 
 			if (data[test_index])
-- 
1.9.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web