All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110
@ 2021-06-23 13:09 Ling Pei Lee
  2021-06-23 20:06 ` Russell King (Oracle)
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Ling Pei Lee @ 2021-06-23 13:09 UTC (permalink / raw)
  To: Russell King, Andrew Lunn, Heiner Kallweit, davem,
	Jakub Kicinski, netdev, linux-kernel
  Cc: Marek Behun, weifeng.voon, vee.khee.wong, vee.khee.wong, pei.lee.ling

From: Voon Weifeng <weifeng.voon@intel.com>

Basically it is just to enable to WoL interrupt and enable WoL detection.
Then, configure the MAC address into address detection register.

Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
Signed-off-by: Ling PeiLee <pei.lee.ling@intel.com>
---
 drivers/net/phy/marvell10g.c | 102 +++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index bbbc6ac8fa82..93410ece83af 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -28,6 +28,7 @@
 #include <linux/marvell_phy.h>
 #include <linux/phy.h>
 #include <linux/sfp.h>
+#include <linux/netdevice.h>
 
 #define MV_PHY_ALASKA_NBT_QUIRK_MASK	0xfffffffe
 #define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
@@ -106,6 +107,17 @@ enum {
 	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
 	MV_V2_TEMP		= 0xf08c,
 	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
+	MV_V2_MAGIC_PKT_WORD0	= 0xf06b,
+	MV_V2_MAGIC_PKT_WORD1	= 0xf06c,
+	MV_V2_MAGIC_PKT_WORD2	= 0xf06d,
+	/* Wake on LAN registers */
+	MV_V2_WOL_CTRL		= 0xf06e,
+	MV_V2_WOL_STS		= 0xf06f,
+	MV_V2_WOL_CLEAR_STS	= BIT(15),
+	MV_V2_WOL_MAGIC_PKT_EN	= BIT(0),
+	MV_V2_PORT_INTR_STS	= 0xf040,
+	MV_V2_PORT_INTR_MASK	= 0xf043,
+	MV_V2_WOL_INTR_EN	= BIT(8),
 };
 
 struct mv3310_chip {
@@ -991,6 +1003,94 @@ static int mv2111_match_phy_device(struct phy_device *phydev)
 	return mv211x_match_phy_device(phydev, false);
 }
 
+static void mv2110_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+	int ret = 0;
+
+	wol->supported = WAKE_MAGIC;
+	wol->wolopts = 0;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
+
+	if (ret & MV_V2_WOL_MAGIC_PKT_EN)
+		wol->wolopts |= WAKE_MAGIC;
+}
+
+static int mv2110_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+	int ret = 0;
+
+	if (wol->wolopts & WAKE_MAGIC) {
+		/* Enable the WOL interrupt */
+		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
+				       MV_V2_PORT_INTR_MASK,
+				       MV_V2_WOL_INTR_EN);
+
+		if (ret < 0)
+			return ret;
+
+		/* Store the device address for the magic packet */
+		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+				    MV_V2_MAGIC_PKT_WORD2,
+				    ((phydev->attached_dev->dev_addr[5] << 8) |
+				    phydev->attached_dev->dev_addr[4]));
+
+		if (ret < 0)
+			return ret;
+
+		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+				    MV_V2_MAGIC_PKT_WORD1,
+				    ((phydev->attached_dev->dev_addr[3] << 8) |
+				    phydev->attached_dev->dev_addr[2]));
+
+		if (ret < 0)
+			return ret;
+
+		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+				    MV_V2_MAGIC_PKT_WORD0,
+				    ((phydev->attached_dev->dev_addr[1] << 8) |
+				    phydev->attached_dev->dev_addr[0]));
+
+		if (ret < 0)
+			return ret;
+
+		/* Clear WOL status and enable magic packet matching */
+		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
+				       MV_V2_WOL_CTRL,
+				       MV_V2_WOL_MAGIC_PKT_EN |
+				       MV_V2_WOL_CLEAR_STS);
+
+		if (ret < 0)
+			return ret;
+
+		/* Reset the clear WOL status bit as it does not self-clear */
+		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
+					 MV_V2_WOL_CTRL,
+					 MV_V2_WOL_CLEAR_STS);
+
+		if (ret < 0)
+			return ret;
+	} else {
+		/* Disable magic packet matching & reset WOL status bit */
+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
+				     MV_V2_WOL_CTRL,
+				     MV_V2_WOL_MAGIC_PKT_EN,
+				     MV_V2_WOL_CLEAR_STS);
+
+		if (ret < 0)
+			return ret;
+
+		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
+					 MV_V2_WOL_CTRL,
+					 MV_V2_WOL_CLEAR_STS);
+
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
+}
+
 static struct phy_driver mv3310_drivers[] = {
 	{
 		.phy_id		= MARVELL_PHY_ID_88X3310,
@@ -1045,6 +1145,8 @@ static struct phy_driver mv3310_drivers[] = {
 		.set_tunable	= mv3310_set_tunable,
 		.remove		= mv3310_remove,
 		.set_loopback	= genphy_c45_loopback,
+		.get_wol	= mv2110_get_wol,
+		.set_wol	= mv2110_set_wol,
 	},
 	{
 		.phy_id		= MARVELL_PHY_ID_88E2110,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110
  2021-06-23 13:09 [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110 Ling Pei Lee
@ 2021-06-23 20:06 ` Russell King (Oracle)
  2021-06-24 15:27   ` Wong Vee Khee
  2021-06-23 21:38 ` Marek Behun
  2021-06-24 15:34 ` Russell King (Oracle)
  2 siblings, 1 reply; 6+ messages in thread
From: Russell King (Oracle) @ 2021-06-23 20:06 UTC (permalink / raw)
  To: Ling Pei Lee
  Cc: Andrew Lunn, Heiner Kallweit, davem, Jakub Kicinski, netdev,
	linux-kernel, Marek Behun, weifeng.voon, vee.khee.wong,
	vee.khee.wong

On Wed, Jun 23, 2021 at 09:09:29PM +0800, Ling Pei Lee wrote:
> +static void mv2110_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
> +{
> +	int ret = 0;

This initialiser doesn't do anything.

> +
> +	wol->supported = WAKE_MAGIC;
> +	wol->wolopts = 0;
> +
> +	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
> +
> +	if (ret & MV_V2_WOL_MAGIC_PKT_EN)
> +		wol->wolopts |= WAKE_MAGIC;

You need to check whether "ret" is a negative number - if phy_read_mmd()
returns an error, this test could be true or false. It would be better
to have well defined behaviour (e.g. reporting that WOL is disabled?)

> +		/* Reset the clear WOL status bit as it does not self-clear */
> +		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
> +					 MV_V2_WOL_CTRL,
> +					 MV_V2_WOL_CLEAR_STS);
> +
> +		if (ret < 0)
> +			return ret;
> +	} else {
> +		/* Disable magic packet matching & reset WOL status bit */
> +		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
> +				     MV_V2_WOL_CTRL,
> +				     MV_V2_WOL_MAGIC_PKT_EN,
> +				     MV_V2_WOL_CLEAR_STS);
> +
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
> +					 MV_V2_WOL_CTRL,
> +					 MV_V2_WOL_CLEAR_STS);
> +
> +		if (ret < 0)
> +			return ret;

This phy_clear_bits_mmd() is the same as the tail end of the other part
of the if() clause. Consider moving it after the if () { } else { }
statement...

> +	}
> +
> +	return ret;

and as all paths return "ret" just do:

	return phy_clear_bits_mmd(...

I will also need to check whether this is the same as the 88x3310, but
I'm afraid I don't have the energy this evening - please email me a
remind to look at this tomorrow. Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110
  2021-06-23 13:09 [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110 Ling Pei Lee
  2021-06-23 20:06 ` Russell King (Oracle)
@ 2021-06-23 21:38 ` Marek Behun
  2021-06-24  2:56   ` Wong Vee Khee
  2021-06-24 15:34 ` Russell King (Oracle)
  2 siblings, 1 reply; 6+ messages in thread
From: Marek Behun @ 2021-06-23 21:38 UTC (permalink / raw)
  To: Ling Pei Lee
  Cc: Russell King, Andrew Lunn, Heiner Kallweit, davem,
	Jakub Kicinski, netdev, linux-kernel, weifeng.voon,
	vee.khee.wong, vee.khee.wong

On Wed, 23 Jun 2021 21:09:29 +0800
Ling Pei Lee <pei.lee.ling@intel.com> wrote:

> +		/* Enable the WOL interrupt */
> +		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
> +				       MV_V2_PORT_INTR_MASK,
> +				       MV_V2_WOL_INTR_EN);
> +
> +		if (ret < 0)
> +			return ret;

Hi, in addition to what Russell said, please remove the extra newline
between function call and return value check, i.e. instead of
  ret = phy_xyz(...);

  if (ret)
     return ret;

  ret = phy_xyz(...);

  if (ret)
     return ret;

do
  ret = phy_xyz(...);
  if (ret)
     return ret;

  ret = phy_xyz(...);
  if (ret)
     return ret;

This is how this driver does this everywhere else.

Do you have a device that uses this WoL feature?

Marek

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110
  2021-06-23 21:38 ` Marek Behun
@ 2021-06-24  2:56   ` Wong Vee Khee
  0 siblings, 0 replies; 6+ messages in thread
From: Wong Vee Khee @ 2021-06-24  2:56 UTC (permalink / raw)
  To: Marek Behun
  Cc: Ling Pei Lee, Russell King, Andrew Lunn, Heiner Kallweit, davem,
	Jakub Kicinski, netdev, linux-kernel, weifeng.voon,
	vee.khee.wong

Hi Marek,

On Wed, Jun 23, 2021 at 11:38:54PM +0200, Marek Behun wrote:
> On Wed, 23 Jun 2021 21:09:29 +0800
> Ling Pei Lee <pei.lee.ling@intel.com> wrote:
> 
> > +		/* Enable the WOL interrupt */
> > +		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
> > +				       MV_V2_PORT_INTR_MASK,
> > +				       MV_V2_WOL_INTR_EN);
> > +
> > +		if (ret < 0)
> > +			return ret;
> 
> Hi, in addition to what Russell said, please remove the extra newline
> between function call and return value check, i.e. instead of
>   ret = phy_xyz(...);
> 
>   if (ret)
>      return ret;
> 
>   ret = phy_xyz(...);
> 
>   if (ret)
>      return ret;
> 
> do
>   ret = phy_xyz(...);
>   if (ret)
>      return ret;
> 
>   ret = phy_xyz(...);
>   if (ret)
>      return ret;
> 
> This is how this driver does this everywhere else.
> 
> Do you have a device that uses this WoL feature?
>

Yes. We have Intel Elkhart Lake platform with Integrated Sypnosys MAC
controller(STMMAC) paired with External PHY device (in this case the
Marvell Alaska 88E2110).

BR,
 VK


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110
  2021-06-23 20:06 ` Russell King (Oracle)
@ 2021-06-24 15:27   ` Wong Vee Khee
  0 siblings, 0 replies; 6+ messages in thread
From: Wong Vee Khee @ 2021-06-24 15:27 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Ling Pei Lee, Andrew Lunn, Heiner Kallweit, davem,
	Jakub Kicinski, netdev, linux-kernel, Marek Behun, weifeng.voon,
	vee.khee.wong

Hi Russell,

On Wed, Jun 23, 2021 at 09:06:18PM +0100, Russell King (Oracle) wrote:
> On Wed, Jun 23, 2021 at 09:09:29PM +0800, Ling Pei Lee wrote:
> > +static void mv2110_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
> > +{
> > +	int ret = 0;
> 
> This initialiser doesn't do anything.
> 
> > +
> > +	wol->supported = WAKE_MAGIC;
> > +	wol->wolopts = 0;
> > +
> > +	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
> > +
> > +	if (ret & MV_V2_WOL_MAGIC_PKT_EN)
> > +		wol->wolopts |= WAKE_MAGIC;
> 
> You need to check whether "ret" is a negative number - if phy_read_mmd()
> returns an error, this test could be true or false. It would be better
> to have well defined behaviour (e.g. reporting that WOL is disabled?)
> 
> > +		/* Reset the clear WOL status bit as it does not self-clear */
> > +		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
> > +					 MV_V2_WOL_CTRL,
> > +					 MV_V2_WOL_CLEAR_STS);
> > +
> > +		if (ret < 0)
> > +			return ret;
> > +	} else {
> > +		/* Disable magic packet matching & reset WOL status bit */
> > +		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
> > +				     MV_V2_WOL_CTRL,
> > +				     MV_V2_WOL_MAGIC_PKT_EN,
> > +				     MV_V2_WOL_CLEAR_STS);
> > +
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
> > +					 MV_V2_WOL_CTRL,
> > +					 MV_V2_WOL_CLEAR_STS);
> > +
> > +		if (ret < 0)
> > +			return ret;
> 
> This phy_clear_bits_mmd() is the same as the tail end of the other part
> of the if() clause. Consider moving it after the if () { } else { }
> statement...
> 
> > +	}
> > +
> > +	return ret;
> 
> and as all paths return "ret" just do:
> 
> 	return phy_clear_bits_mmd(...
> 
> I will also need to check whether this is the same as the 88x3310, but
> I'm afraid I don't have the energy this evening - please email me a
> remind to look at this tomorrow. Thanks.
>

Shall we add this for the 88x3310 as well?

BR,
 VK 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110
  2021-06-23 13:09 [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110 Ling Pei Lee
  2021-06-23 20:06 ` Russell King (Oracle)
  2021-06-23 21:38 ` Marek Behun
@ 2021-06-24 15:34 ` Russell King (Oracle)
  2 siblings, 0 replies; 6+ messages in thread
From: Russell King (Oracle) @ 2021-06-24 15:34 UTC (permalink / raw)
  To: Ling Pei Lee
  Cc: Andrew Lunn, Heiner Kallweit, davem, Jakub Kicinski, netdev,
	linux-kernel, Marek Behun, weifeng.voon, vee.khee.wong,
	vee.khee.wong

On Wed, Jun 23, 2021 at 09:09:29PM +0800, Ling Pei Lee wrote:
> @@ -106,6 +107,17 @@ enum {
>  	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
>  	MV_V2_TEMP		= 0xf08c,
>  	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
> +	MV_V2_MAGIC_PKT_WORD0	= 0xf06b,
> +	MV_V2_MAGIC_PKT_WORD1	= 0xf06c,
> +	MV_V2_MAGIC_PKT_WORD2	= 0xf06d,
> +	/* Wake on LAN registers */
> +	MV_V2_WOL_CTRL		= 0xf06e,
> +	MV_V2_WOL_STS		= 0xf06f,
> +	MV_V2_WOL_CLEAR_STS	= BIT(15),
> +	MV_V2_WOL_MAGIC_PKT_EN	= BIT(0),
> +	MV_V2_PORT_INTR_STS	= 0xf040,
> +	MV_V2_PORT_INTR_MASK	= 0xf043,
> +	MV_V2_WOL_INTR_EN	= BIT(8),

Please put these new register definitions in address order. This list is
first sorted by MMD and then by address. So these should be before the
definition of MV_V2_TEMP_CTRL.

As I suspected, the 88x3310 shares this same register layout for the WOL
and at least bit 8 of the interrupt status and enable registers.

Thanks, and thanks for reminding me to look at this today!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-06-24 15:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-23 13:09 [PATCH net-next] net: phy: marvell10g: enable WoL for mv2110 Ling Pei Lee
2021-06-23 20:06 ` Russell King (Oracle)
2021-06-24 15:27   ` Wong Vee Khee
2021-06-23 21:38 ` Marek Behun
2021-06-24  2:56   ` Wong Vee Khee
2021-06-24 15:34 ` Russell King (Oracle)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.