net: phy: handle state correctly in phy_stop_machine

Message ID 1490214421-7269-1-git-send-email-zach.brown@ni.com
State Accepted
Delegated to: David Miller
Headers show

Commit Message

Zach Brown March 22, 2017, 8:27 p.m.
From: Nathan Sullivan <nathan.sullivan@ni.com>

If the PHY is halted on stop, then do not set the state to PHY_UP.  This
ensures the phy will be restarted later in phy_start when the machine is
started again.

Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
Signed-off-by: Brad Mouring <brad.mouring@ni.com>
Acked-by: Xander Huff <xander.huff@ni.com>
Acked-by: Kyle Roeschley <kyle.roeschley@ni.com>
---
 drivers/net/phy/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

David Miller March 23, 2017, 9:25 p.m. | #1
From: Zach Brown <zach.brown@ni.com>
Date: Wed, 22 Mar 2017 15:27:01 -0500

> From: Nathan Sullivan <nathan.sullivan@ni.com>
> 
> If the PHY is halted on stop, then do not set the state to PHY_UP.  This
> ensures the phy will be restarted later in phy_start when the machine is
> started again.
> 
> Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
> Signed-off-by: Brad Mouring <brad.mouring@ni.com>
> Acked-by: Xander Huff <xander.huff@ni.com>
> Acked-by: Kyle Roeschley <kyle.roeschley@ni.com>

Florian, please review.
Florian Fainelli March 23, 2017, 9:41 p.m. | #2
On 03/22/2017 01:27 PM, Zach Brown wrote:
> From: Nathan Sullivan <nathan.sullivan@ni.com>
> 
> If the PHY is halted on stop, then do not set the state to PHY_UP.  This
> ensures the phy will be restarted later in phy_start when the machine is
> started again.

So essentially what you want to "defeat" here is entering phy_start()
with PHY_UP therefore not run this part:

        case PHY_HALTED:
                /* make sure interrupts are re-enabled for the PHY */
                if (phydev->irq != PHY_POLL) {
                        err = phy_enable_interrupts(phydev);
                        if (err < 0)
                                break;
                }

                phydev->state = PHY_RESUMING;
                do_resume = true;
                break;

which is what re-enables interrupts and makes sure the PHY is resumed,
right?

If that's the scenario, I guess:

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

> 
> Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
> Signed-off-by: Brad Mouring <brad.mouring@ni.com>
> Acked-by: Xander Huff <xander.huff@ni.com>
> Acked-by: Kyle Roeschley <kyle.roeschley@ni.com>
> ---
>  drivers/net/phy/phy.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index 7cc1b7d..fe2d4c4 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -678,7 +678,7 @@ void phy_stop_machine(struct phy_device *phydev)
>  	cancel_delayed_work_sync(&phydev->state_queue);
>  
>  	mutex_lock(&phydev->lock);
> -	if (phydev->state > PHY_UP)
> +	if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
>  		phydev->state = PHY_UP;
>  	mutex_unlock(&phydev->lock);
>  }
>
Florian Fainelli March 23, 2017, 9:45 p.m. | #3
On 03/23/2017 02:41 PM, Florian Fainelli wrote:
> On 03/22/2017 01:27 PM, Zach Brown wrote:
>> From: Nathan Sullivan <nathan.sullivan@ni.com>
>>
>> If the PHY is halted on stop, then do not set the state to PHY_UP.  This
>> ensures the phy will be restarted later in phy_start when the machine is
>> started again.
> 
> So essentially what you want to "defeat" here is entering phy_start()
> with PHY_UP therefore not run this part:
> 
>         case PHY_HALTED:
>                 /* make sure interrupts are re-enabled for the PHY */
>                 if (phydev->irq != PHY_POLL) {
>                         err = phy_enable_interrupts(phydev);
>                         if (err < 0)
>                                 break;
>                 }
> 
>                 phydev->state = PHY_RESUMING;
>                 do_resume = true;
>                 break;
> 
> which is what re-enables interrupts and makes sure the PHY is resumed,
> right?
> 
> If that's the scenario, I guess:
> 
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

And almost forgot:

Fixes: 00db8189d984 ("This patch adds a PHY Abstraction Layer to the
Linux Kernel, enabling ethernet drivers to remain as ignorant as is
reasonable of the connected PHY's design and operation details.")
David Miller March 24, 2017, 7:27 p.m. | #4
From: Zach Brown <zach.brown@ni.com>
Date: Wed, 22 Mar 2017 15:27:01 -0500

> From: Nathan Sullivan <nathan.sullivan@ni.com>
> 
> If the PHY is halted on stop, then do not set the state to PHY_UP.  This
> ensures the phy will be restarted later in phy_start when the machine is
> started again.
> 
> Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
> Signed-off-by: Brad Mouring <brad.mouring@ni.com>
> Acked-by: Xander Huff <xander.huff@ni.com>
> Acked-by: Kyle Roeschley <kyle.roeschley@ni.com>

Applied and queued up for -stable, thanks.

Patch

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 7cc1b7d..fe2d4c4 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -678,7 +678,7 @@  void phy_stop_machine(struct phy_device *phydev)
 	cancel_delayed_work_sync(&phydev->state_queue);
 
 	mutex_lock(&phydev->lock);
-	if (phydev->state > PHY_UP)
+	if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
 		phydev->state = PHY_UP;
 	mutex_unlock(&phydev->lock);
 }