diff mbox series

[net-next,1/1] net: phy: marvell10g: Add WAKE_PHY support to WOL event

Message ID 20210813084536.182381-1-yoong.siang.song@intel.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net-next,1/1] net: phy: marvell10g: Add WAKE_PHY support to WOL event | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 57 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Song Yoong Siang Aug. 13, 2021, 8:45 a.m. UTC
Add Wake-on-PHY feature support by enabling the Link Status Changed
interrupt.

Signed-off-by: Song Yoong Siang <yoong.siang.song@intel.com>
---
 drivers/net/phy/marvell10g.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

Comments

Marek Behún Aug. 14, 2021, 5:19 p.m. UTC | #1
On Fri, 13 Aug 2021 16:45:36 +0800
Song Yoong Siang <yoong.siang.song@intel.com> wrote:

> Add Wake-on-PHY feature support by enabling the Link Status Changed
> interrupt.
> 
> Signed-off-by: Song Yoong Siang <yoong.siang.song@intel.com>

Hi Song,

I presume this is also tested.

The code look ok.

Reviewed-by: Marek Behún <kabel@kernel.org>
Russell King (Oracle) Aug. 14, 2021, 5:26 p.m. UTC | #2
On Fri, Aug 13, 2021 at 04:45:36PM +0800, Song Yoong Siang wrote:
> Add Wake-on-PHY feature support by enabling the Link Status Changed
> interrupt.
> 
> Signed-off-by: Song Yoong Siang <yoong.siang.song@intel.com>
> ---
>  drivers/net/phy/marvell10g.c | 33 ++++++++++++++++++++++++++++++++-
>  1 file changed, 32 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
> index 0b7cae118ad7..d46761c225f0 100644
> --- a/drivers/net/phy/marvell10g.c
> +++ b/drivers/net/phy/marvell10g.c
> @@ -76,6 +76,11 @@ enum {
>  	MV_PCS_CSSR1_SPD2_2500	= 0x0004,
>  	MV_PCS_CSSR1_SPD2_10000	= 0x0000,
>  
> +	/* Copper Specific Interrupt registers */
> +	MV_PCS_INTR_ENABLE	= 0x8010,
> +	MV_PCS_INTR_ENABLE_LSC	= BIT(10),
> +	MV_PCS_INTR_STS		= 0x8011,
> +
>  	/* Temperature read register (88E2110 only) */
>  	MV_PCS_TEMP		= 0x8042,
>  
> @@ -1036,7 +1041,7 @@ static void mv3110_get_wol(struct phy_device *phydev,
>  {
>  	int ret;
>  
> -	wol->supported = WAKE_MAGIC;
> +	wol->supported = WAKE_MAGIC | WAKE_PHY;
>  	wol->wolopts = 0;
>  
>  	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
> @@ -1045,6 +1050,13 @@ static void mv3110_get_wol(struct phy_device *phydev,
>  
>  	if (ret & MV_V2_WOL_CTRL_MAGIC_PKT_EN)
>  		wol->wolopts |= WAKE_MAGIC;
> +
> +	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_INTR_ENABLE);
> +	if (ret < 0)
> +		return;
> +
> +	if (ret & MV_PCS_INTR_ENABLE_LSC)
> +		wol->wolopts |= WAKE_PHY;
>  }
>  
>  static int mv3110_set_wol(struct phy_device *phydev,
> @@ -1099,6 +1111,25 @@ static int mv3110_set_wol(struct phy_device *phydev,
>  			return ret;
>  	}
>  
> +	if (wol->wolopts & WAKE_PHY) {
> +		/* Enable the link status changed interrupt */
> +		ret = phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
> +				       MV_PCS_INTR_ENABLE,
> +				       MV_PCS_INTR_ENABLE_LSC);
> +		if (ret < 0)
> +			return ret;
> +
> +		/* Clear the interrupt status register */
> +		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_INTR_STS);
> +	} else {
> +		/* Disable the link status changed interrupt */
> +		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PCS,
> +					 MV_PCS_INTR_ENABLE,
> +					 MV_PCS_INTR_ENABLE_LSC);
> +		if (ret < 0)
> +			return ret;
> +	}
> +

How does this work if the driver has no interrupt support? What is
the hardware setup this has been tested with?

What if we later want to add interrupt support to this driver to
support detecting changes in link state - isn't using this bit
in the interrupt enable register going to confict with that?
Andrew Lunn Aug. 14, 2021, 6:04 p.m. UTC | #3
> How does this work if the driver has no interrupt support? What is
> the hardware setup this has been tested with?

Hi Russell

We already know from previous patches that the Intel hardware is
broken, and does not actually deliver the interrupt which caused the
wake up. So i assume this just continues on with the same broken
hardware, but they have a different PHY connected.

> What if we later want to add interrupt support to this driver to
> support detecting changes in link state - isn't using this bit
> in the interrupt enable register going to confict with that?

Agreed. If the interrupt register is being used, i think we need this
patchset to add proper interrupt support. Can you recommend a board
they can buy off the shelf with the interrupt wired up? Or maybe Intel
can find a hardware engineer to add a patch wire to link the interrupt
output to a SoC pin that can do interrupts.

	  Andrew
Russell King (Oracle) Aug. 14, 2021, 7:49 p.m. UTC | #4
On Sat, Aug 14, 2021 at 08:04:55PM +0200, Andrew Lunn wrote:
> Agreed. If the interrupt register is being used, i think we need this
> patchset to add proper interrupt support. Can you recommend a board
> they can buy off the shelf with the interrupt wired up? Or maybe Intel
> can find a hardware engineer to add a patch wire to link the interrupt
> output to a SoC pin that can do interrupts.

The only board I'm aware of with the 88x3310 interrupt wired is the
Macchiatobin double-shot. :)

I forget why I didn't implement interrupt support though - I probably
need to revisit that. Sure enough, looking at the code I was tinkering
with, adding interrupt support would certainly conflict with this
patch.
Song Yoong Siang Aug. 16, 2021, 3:19 a.m. UTC | #5
> > How does this work if the driver has no interrupt support? What is the
> > hardware setup this has been tested with?
> 
> Hi Russell
> 
> We already know from previous patches that the Intel hardware is broken,
> and does not actually deliver the interrupt which caused the wake up. So i
> assume this just continues on with the same broken hardware, but they have
> a different PHY connected.

Hi Russell & Andrew,

This is tested on Intel Elkhart Lake (EHL) board. We are using polling mode.
Both WoL interrupt and link change interrupt are the same pin which is
routed to PMC. PMC will wake up the system when there is WoL event.

Regards
Siang

> 
> > What if we later want to add interrupt support to this driver to
> > support detecting changes in link state - isn't using this bit in the
> > interrupt enable register going to confict with that?
> 
> Agreed. If the interrupt register is being used, i think we need this patchset to
> add proper interrupt support. Can you recommend a board they can buy off
> the shelf with the interrupt wired up? Or maybe Intel can find a hardware
> engineer to add a patch wire to link the interrupt output to a SoC pin that can
> do interrupts.
> 
> 	  Andrew
Song Yoong Siang Aug. 16, 2021, 3:52 a.m. UTC | #6
> > Agreed. If the interrupt register is being used, i think we need this
> > patchset to add proper interrupt support. Can you recommend a board
> > they can buy off the shelf with the interrupt wired up? Or maybe Intel
> > can find a hardware engineer to add a patch wire to link the interrupt
> > output to a SoC pin that can do interrupts.
> 
> The only board I'm aware of with the 88x3310 interrupt wired is the
> Macchiatobin double-shot. :)
> 
> I forget why I didn't implement interrupt support though - I probably need to
> revisit that. Sure enough, looking at the code I was tinkering with, adding
> interrupt support would certainly conflict with this patch.

Hi Russell,

For EHL board, both WoL interrupt and link change interrupt are the same pin.
Based on your knowledge, is this common across other platforms?
Can we take set wol function as one of the ways to control the interrupts?

Regards,
Siang

> 
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Andrew Lunn Aug. 16, 2021, 4:10 a.m. UTC | #7
On Mon, Aug 16, 2021 at 03:19:34AM +0000, Song, Yoong Siang wrote:
> > > How does this work if the driver has no interrupt support? What is the
> > > hardware setup this has been tested with?
> > 
> > Hi Russell
> > 
> > We already know from previous patches that the Intel hardware is broken,
> > and does not actually deliver the interrupt which caused the wake up. So i
> > assume this just continues on with the same broken hardware, but they have
> > a different PHY connected.
> 
> Hi Russell & Andrew,
> 
> This is tested on Intel Elkhart Lake (EHL) board. We are using polling mode.
> Both WoL interrupt and link change interrupt are the same pin which is
> routed to PMC. PMC will wake up the system when there is WoL event.

Is the PMC also an interrupt controller?

   Andrew
Andrew Lunn Aug. 16, 2021, 4:15 a.m. UTC | #8
On Mon, Aug 16, 2021 at 03:52:06AM +0000, Song, Yoong Siang wrote:
> > > Agreed. If the interrupt register is being used, i think we need this
> > > patchset to add proper interrupt support. Can you recommend a board
> > > they can buy off the shelf with the interrupt wired up? Or maybe Intel
> > > can find a hardware engineer to add a patch wire to link the interrupt
> > > output to a SoC pin that can do interrupts.
> > 
> > The only board I'm aware of with the 88x3310 interrupt wired is the
> > Macchiatobin double-shot. :)
> > 
> > I forget why I didn't implement interrupt support though - I probably need to
> > revisit that. Sure enough, looking at the code I was tinkering with, adding
> > interrupt support would certainly conflict with this patch.
> 
> Hi Russell,
> 
> For EHL board, both WoL interrupt and link change interrupt are the same pin.
> Based on your knowledge, is this common across other platforms?

Other PHYs? Yes. WoL is just another interrupt, and any interrupt can
wake the system, so longer as the interrupt controller can actually wake the system.

> Can we take set wol function as one of the ways to control the
> interrupts?

WOl does not control the interrupt, it is an interrupt source. And you
need to service it as an interrupt. So long as your PMC is also an
interrupt controller, it should all work.

	  Andrew
Song Yoong Siang Aug. 16, 2021, 5:40 a.m. UTC | #9
> On Mon, Aug 16, 2021 at 03:52:06AM +0000, Song, Yoong Siang wrote:
> > > > Agreed. If the interrupt register is being used, i think we need
> > > > this patchset to add proper interrupt support. Can you recommend a
> > > > board they can buy off the shelf with the interrupt wired up? Or
> > > > maybe Intel can find a hardware engineer to add a patch wire to
> > > > link the interrupt output to a SoC pin that can do interrupts.
> > >
> > > The only board I'm aware of with the 88x3310 interrupt wired is the
> > > Macchiatobin double-shot. :)
> > >
> > > I forget why I didn't implement interrupt support though - I
> > > probably need to revisit that. Sure enough, looking at the code I
> > > was tinkering with, adding interrupt support would certainly conflict with
> this patch.
> >
> > Hi Russell,
> >
> > For EHL board, both WoL interrupt and link change interrupt are the same
> pin.
> > Based on your knowledge, is this common across other platforms?
> 
> Other PHYs? Yes. WoL is just another interrupt, and any interrupt can wake
> the system, so longer as the interrupt controller can actually wake the
> system.
> 
> > Can we take set wol function as one of the ways to control the
> > interrupts?
> 
> WOl does not control the interrupt, it is an interrupt source. And you need to
> service it as an interrupt. So long as your PMC is also an interrupt controller,
> it should all work.
> 
> 	  Andrew

Sorry, I should not use the word "control". Actually what I am trying to said was
"can we take set_wol() as one of the ways to enable/disable link change interrupt?".
PMC is not an interrupt controller. I guess the confusion here is due to I am
using polling mode. Let me ask the question differently.

What is the conflict that will happen when interrupt support is added? 
I can help to add config_intr() and handle_interrupt() callback support
If they will help to solve the conflict.

Regards
Siang
Russell King (Oracle) Aug. 16, 2021, 7:14 a.m. UTC | #10
On Mon, Aug 16, 2021 at 05:40:18AM +0000, Song, Yoong Siang wrote:
> > On Mon, Aug 16, 2021 at 03:52:06AM +0000, Song, Yoong Siang wrote:
> > > > > Agreed. If the interrupt register is being used, i think we need
> > > > > this patchset to add proper interrupt support. Can you recommend a
> > > > > board they can buy off the shelf with the interrupt wired up? Or
> > > > > maybe Intel can find a hardware engineer to add a patch wire to
> > > > > link the interrupt output to a SoC pin that can do interrupts.
> > > >
> > > > The only board I'm aware of with the 88x3310 interrupt wired is the
> > > > Macchiatobin double-shot. :)
> > > >
> > > > I forget why I didn't implement interrupt support though - I
> > > > probably need to revisit that. Sure enough, looking at the code I
> > > > was tinkering with, adding interrupt support would certainly conflict with
> > this patch.
> > >
> > > Hi Russell,
> > >
> > > For EHL board, both WoL interrupt and link change interrupt are the same
> > pin.
> > > Based on your knowledge, is this common across other platforms?
> > 
> > Other PHYs? Yes. WoL is just another interrupt, and any interrupt can wake
> > the system, so longer as the interrupt controller can actually wake the
> > system.
> > 
> > > Can we take set wol function as one of the ways to control the
> > > interrupts?
> > 
> > WOl does not control the interrupt, it is an interrupt source. And you need to
> > service it as an interrupt. So long as your PMC is also an interrupt controller,
> > it should all work.
> > 
> > 	  Andrew
> 
> Sorry, I should not use the word "control". Actually what I am trying to said was
> "can we take set_wol() as one of the ways to enable/disable link change interrupt?".
> PMC is not an interrupt controller. I guess the confusion here is due to I am
> using polling mode. Let me ask the question differently.
> 
> What is the conflict that will happen when interrupt support is added? 
> I can help to add config_intr() and handle_interrupt() callback support
> If they will help to solve the conflict.

The conflict is - when interrupt support is added, the link change
interrupt will be enabled all the time the PHY is in use. This will
have the effect with your patch of making the PHY appear to have WoL
enabled, even when it hasn't been configured through a set_wol call.

Essentially, your proposal for WoL on link-change fundamentally
conflicts with proper interrupt support.
Song Yoong Siang Aug. 16, 2021, 8:03 a.m. UTC | #11
> On Mon, Aug 16, 2021 at 05:40:18AM +0000, Song, Yoong Siang wrote:
> > > On Mon, Aug 16, 2021 at 03:52:06AM +0000, Song, Yoong Siang wrote:
> > > > > > Agreed. If the interrupt register is being used, i think we
> > > > > > need this patchset to add proper interrupt support. Can you
> > > > > > recommend a board they can buy off the shelf with the
> > > > > > interrupt wired up? Or maybe Intel can find a hardware
> > > > > > engineer to add a patch wire to link the interrupt output to a SoC pin
> that can do interrupts.
> > > > >
> > > > > The only board I'm aware of with the 88x3310 interrupt wired is
> > > > > the Macchiatobin double-shot. :)
> > > > >
> > > > > I forget why I didn't implement interrupt support though - I
> > > > > probably need to revisit that. Sure enough, looking at the code
> > > > > I was tinkering with, adding interrupt support would certainly
> > > > > conflict with
> > > this patch.
> > > >
> > > > Hi Russell,
> > > >
> > > > For EHL board, both WoL interrupt and link change interrupt are
> > > > the same
> > > pin.
> > > > Based on your knowledge, is this common across other platforms?
> > >
> > > Other PHYs? Yes. WoL is just another interrupt, and any interrupt
> > > can wake the system, so longer as the interrupt controller can
> > > actually wake the system.
> > >
> > > > Can we take set wol function as one of the ways to control the
> > > > interrupts?
> > >
> > > WOl does not control the interrupt, it is an interrupt source. And
> > > you need to service it as an interrupt. So long as your PMC is also
> > > an interrupt controller, it should all work.
> > >
> > > 	  Andrew
> >
> > Sorry, I should not use the word "control". Actually what I am trying
> > to said was "can we take set_wol() as one of the ways to enable/disable
> link change interrupt?".
> > PMC is not an interrupt controller. I guess the confusion here is due
> > to I am using polling mode. Let me ask the question differently.
> >
> > What is the conflict that will happen when interrupt support is added?
> > I can help to add config_intr() and handle_interrupt() callback
> > support If they will help to solve the conflict.
> 
> The conflict is - when interrupt support is added, the link change interrupt
> will be enabled all the time the PHY is in use. This will have the effect with
> your patch of making the PHY appear to have WoL enabled, even when it
> hasn't been configured through a set_wol call.
> 
> Essentially, your proposal for WoL on link-change fundamentally conflicts
> with proper interrupt support.
> 

Thanks for your explanation. I understand your concern better now.

In the case of WoL hasn't been enabled through a set_wol call, the PHY will
be suspended, so we no need worry the link change interrupt will create
an undesired WoL event. 

In the case of set_wol is called to disable WAKE_PHY event, we can keep
the link change interrupt enable, so that it won't affect the interrupt
support.

Since any interrupts can wake the system, as long as we handle the
future going-to-implement interrupt support properly, things should work
fine. Any other thoughts?

> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle) Aug. 16, 2021, 8:18 a.m. UTC | #12
On Mon, Aug 16, 2021 at 08:03:59AM +0000, Song, Yoong Siang wrote:
> Thanks for your explanation. I understand your concern better now.
> 
> In the case of WoL hasn't been enabled through a set_wol call, the PHY will
> be suspended, so we no need worry the link change interrupt will create
> an undesired WoL event. 
> 
> In the case of set_wol is called to disable WAKE_PHY event, we can keep
> the link change interrupt enable, so that it won't affect the interrupt
> support.

I think you're missing the point. In your get_wol method for this
PHY:

+       ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_INTR_ENABLE);
+       if (ret < 0)
+               return;
+
+       if (ret & MV_PCS_INTR_ENABLE_LSC)
+               wol->wolopts |= WAKE_PHY;

If the link change interrupt is enabled because we want to use
interrupt support, the above code has the effect of reporting to
userspace that WoL is enabled, even when nothing has requested WoL
to be enabled.

This also has the effect of preventing the PHY being suspended (see
phy_suspend()) and in effect means that WoL is enabled, even though
set_wol() was not called.
Song Yoong Siang Aug. 16, 2021, 8:56 a.m. UTC | #13
> On Mon, Aug 16, 2021 at 08:03:59AM +0000, Song, Yoong Siang wrote:
> > Thanks for your explanation. I understand your concern better now.
> >
> > In the case of WoL hasn't been enabled through a set_wol call, the PHY
> > will be suspended, so we no need worry the link change interrupt will
> > create an undesired WoL event.
> >
> > In the case of set_wol is called to disable WAKE_PHY event, we can
> > keep the link change interrupt enable, so that it won't affect the
> > interrupt support.
> 
> I think you're missing the point. In your get_wol method for this
> PHY:
> 
> +       ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
> MV_PCS_INTR_ENABLE);
> +       if (ret < 0)
> +               return;
> +
> +       if (ret & MV_PCS_INTR_ENABLE_LSC)
> +               wol->wolopts |= WAKE_PHY;
> 
> If the link change interrupt is enabled because we want to use interrupt
> support, the above code has the effect of reporting to userspace that WoL is
> enabled, even when nothing has requested WoL to be enabled.
> 
> This also has the effect of preventing the PHY being suspended (see
> phy_suspend()) and in effect means that WoL is enabled, even though
> set_wol() was not called.
> 
Yes, you are right. I missed the effect of get_wol.
Is it needed in future to implement link change interrupt in phy driver?
Cause I dint see much phy driver implement link change interrupt.
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Marek Behún Aug. 16, 2021, 9:54 a.m. UTC | #14
On Mon, 16 Aug 2021 08:56:36 +0000
"Song, Yoong Siang" <yoong.siang.song@intel.com> wrote:

> Yes, you are right. I missed the effect of get_wol.
> Is it needed in future to implement link change interrupt in phy
> driver? Cause I dint see much phy driver implement link change
> interrupt.

If there is a board that has interrupt pin wired correctly from the
PHY and the interrupt controller is safe to use (i.e. it is not a
PCA953x which cannot handle interrupt storms correctly), then I think
the PHY driver should use the interrupt, instead of polling.

Marek
Song Yoong Siang Aug. 16, 2021, 3:02 p.m. UTC | #15
> > Yes, you are right. I missed the effect of get_wol.
> > Is it needed in future to implement link change interrupt in phy
> > driver? Cause I dint see much phy driver implement link change
> > interrupt.
> 
> If there is a board that has interrupt pin wired correctly from the PHY and the
> interrupt controller is safe to use (i.e. it is not a PCA953x which cannot
> handle interrupt storms correctly), then I think the PHY driver should use the
> interrupt, instead of polling.
> 
> Marek

Any suggestion to avoid the conflict of "WoL on link change" mentioned by Russell?
Is it make sense to create a new member called wolopts under struct phy_device
to track the WoL status and return the correct status in get_wol callback?

Regards
Siang
Andrew Lunn Aug. 16, 2021, 3:27 p.m. UTC | #16
On Mon, Aug 16, 2021 at 03:02:03PM +0000, Song, Yoong Siang wrote:
> > > Yes, you are right. I missed the effect of get_wol.
> > > Is it needed in future to implement link change interrupt in phy
> > > driver? Cause I dint see much phy driver implement link change
> > > interrupt.
> > 
> > If there is a board that has interrupt pin wired correctly from the PHY and the
> > interrupt controller is safe to use (i.e. it is not a PCA953x which cannot
> > handle interrupt storms correctly), then I think the PHY driver should use the
> > interrupt, instead of polling.
> > 
> > Marek
> 
> Any suggestion to avoid the conflict of "WoL on link change" mentioned by Russell?
> Is it make sense to create a new member called wolopts under struct phy_device
> to track the WoL status and return the correct status in get_wol callback?

I really think you need to look at your PMC and see if you can make it
an interrupt controller. You only need level interrupts, not edge. So
the microcontroller in the PMC could just poll the GPIO. There appears
to be a simple IPC between the host and PMC, so just extend it with a
couple of registers, interrupt state, interrupt mask, and make use of
the existing interrupt between the host and PMC.

    Andrew
Song Yoong Siang Aug. 20, 2021, 1:22 a.m. UTC | #17
> > > > Yes, you are right. I missed the effect of get_wol.
> > > > Is it needed in future to implement link change interrupt in phy
> > > > driver? Cause I dint see much phy driver implement link change
> > > > interrupt.
> > >
> > > If there is a board that has interrupt pin wired correctly from the
> > > PHY and the interrupt controller is safe to use (i.e. it is not a
> > > PCA953x which cannot handle interrupt storms correctly), then I
> > > think the PHY driver should use the interrupt, instead of polling.
> > >
> > > Marek
> >
> > Any suggestion to avoid the conflict of "WoL on link change" mentioned by
> Russell?
> > Is it make sense to create a new member called wolopts under struct
> > phy_device to track the WoL status and return the correct status in get_wol
> callback?
> 
> I really think you need to look at your PMC and see if you can make it an
> interrupt controller. You only need level interrupts, not edge. So the
> microcontroller in the PMC could just poll the GPIO. There appears to be a
> simple IPC between the host and PMC, so just extend it with a couple of
> registers, interrupt state, interrupt mask, and make use of the existing
> interrupt between the host and PMC.
> 
>     Andrew

Thanks for your suggestion. Currently, PMC is designed for platform-wide
power management and not meant to control any device specific registers.
Seem like it is not possible to make PMC an interrupt controller, but I will
continue to discuss more with my team.

Regards
Siang
diff mbox series

Patch

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 0b7cae118ad7..d46761c225f0 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -76,6 +76,11 @@  enum {
 	MV_PCS_CSSR1_SPD2_2500	= 0x0004,
 	MV_PCS_CSSR1_SPD2_10000	= 0x0000,
 
+	/* Copper Specific Interrupt registers */
+	MV_PCS_INTR_ENABLE	= 0x8010,
+	MV_PCS_INTR_ENABLE_LSC	= BIT(10),
+	MV_PCS_INTR_STS		= 0x8011,
+
 	/* Temperature read register (88E2110 only) */
 	MV_PCS_TEMP		= 0x8042,
 
@@ -1036,7 +1041,7 @@  static void mv3110_get_wol(struct phy_device *phydev,
 {
 	int ret;
 
-	wol->supported = WAKE_MAGIC;
+	wol->supported = WAKE_MAGIC | WAKE_PHY;
 	wol->wolopts = 0;
 
 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
@@ -1045,6 +1050,13 @@  static void mv3110_get_wol(struct phy_device *phydev,
 
 	if (ret & MV_V2_WOL_CTRL_MAGIC_PKT_EN)
 		wol->wolopts |= WAKE_MAGIC;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_INTR_ENABLE);
+	if (ret < 0)
+		return;
+
+	if (ret & MV_PCS_INTR_ENABLE_LSC)
+		wol->wolopts |= WAKE_PHY;
 }
 
 static int mv3110_set_wol(struct phy_device *phydev,
@@ -1099,6 +1111,25 @@  static int mv3110_set_wol(struct phy_device *phydev,
 			return ret;
 	}
 
+	if (wol->wolopts & WAKE_PHY) {
+		/* Enable the link status changed interrupt */
+		ret = phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
+				       MV_PCS_INTR_ENABLE,
+				       MV_PCS_INTR_ENABLE_LSC);
+		if (ret < 0)
+			return ret;
+
+		/* Clear the interrupt status register */
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_INTR_STS);
+	} else {
+		/* Disable the link status changed interrupt */
+		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PCS,
+					 MV_PCS_INTR_ENABLE,
+					 MV_PCS_INTR_ENABLE_LSC);
+		if (ret < 0)
+			return ret;
+	}
+
 	/* Reset the clear WOL status bit as it does not self-clear */
 	return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
 				  MV_V2_WOL_CTRL,