diff mbox series

[net-next,v2,2/4] net: phy: warn if phy_start is called from invalid state

Message ID cc566aa7-27cd-67fb-ea4b-00ee84d3dd7b@gmail.com
State Changes Requested
Delegated to: David Miller
Headers show
Series net: phy: improve starting PHY | expand

Commit Message

Heiner Kallweit Jan. 20, 2019, 9:02 a.m. UTC
phy_start() should be called from states PHY_READY or PHY_HALTED only.
Check for this to detect misbehaving drivers. Also the state machine
should be started only when being called from one of the valid states.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/phy/phy.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

Comments

Andrew Lunn Jan. 21, 2019, 4:40 p.m. UTC | #1
On Sun, Jan 20, 2019 at 10:02:13AM +0100, Heiner Kallweit wrote:
> phy_start() should be called from states PHY_READY or PHY_HALTED only.
> Check for this to detect misbehaving drivers. Also the state machine
> should be started only when being called from one of the valid states.
> 
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
> ---
>  drivers/net/phy/phy.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index 3df6aadc5..fd928979b 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -861,9 +861,16 @@ void phy_start(struct phy_device *phydev)
>  
>  	mutex_lock(&phydev->lock);
>  
> +	if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) {
> +		WARN(1, "called from state %s\n",
> +		     phy_state_to_str(phydev->state));
> +		goto out;
> +	}

Hi Heiner

Warning is good. But jumping to out i'm not so sure about. Drivers
which are 'broken' work well enough that users don't know they are
broken. But jumping to out is going to really break them. It seems
better to have the kernel only warn for one cycle so we find out about
such drivers and fix them, and later add the goto out.

     Andrew
Heiner Kallweit Jan. 21, 2019, 6:25 p.m. UTC | #2
On 21.01.2019 17:40, Andrew Lunn wrote:
> On Sun, Jan 20, 2019 at 10:02:13AM +0100, Heiner Kallweit wrote:
>> phy_start() should be called from states PHY_READY or PHY_HALTED only.
>> Check for this to detect misbehaving drivers. Also the state machine
>> should be started only when being called from one of the valid states.
>>
>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>> ---
>>  drivers/net/phy/phy.c | 11 +++++++++--
>>  1 file changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
>> index 3df6aadc5..fd928979b 100644
>> --- a/drivers/net/phy/phy.c
>> +++ b/drivers/net/phy/phy.c
>> @@ -861,9 +861,16 @@ void phy_start(struct phy_device *phydev)
>>  
>>  	mutex_lock(&phydev->lock);
>>  
>> +	if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) {
>> +		WARN(1, "called from state %s\n",
>> +		     phy_state_to_str(phydev->state));
>> +		goto out;
>> +	}
> 
> Hi Heiner
> 
> Warning is good. But jumping to out i'm not so sure about. Drivers
> which are 'broken' work well enough that users don't know they are
> broken. But jumping to out is going to really break them. It seems
> better to have the kernel only warn for one cycle so we find out about
> such drivers and fix them, and later add the goto out.
> 
For all invalid states phy_start() basically was a no-op. All it did was
triggering a state machine run, but for all "running" states the poll
loop was active anyway. And if called from PHY_DOWN, the state machine
does nothing. Therefore I see no scenario where jumping to out would
break anything.

>      Andrew
> 
Heiner
Andrew Lunn Jan. 21, 2019, 6:29 p.m. UTC | #3
> For all invalid states phy_start() basically was a no-op. All it did was
> triggering a state machine run, but for all "running" states the poll
> loop was active anyway. And if called from PHY_DOWN, the state machine
> does nothing. Therefore I see no scenario where jumping to out would
> break anything.

Hi Heiner

It is useful to put this sort of analysis in the commit message. You
then won't get people like me asking about it.

     Andrew
Heiner Kallweit Jan. 21, 2019, 6:30 p.m. UTC | #4
On 21.01.2019 19:29, Andrew Lunn wrote:
>> For all invalid states phy_start() basically was a no-op. All it did was
>> triggering a state machine run, but for all "running" states the poll
>> loop was active anyway. And if called from PHY_DOWN, the state machine
>> does nothing. Therefore I see no scenario where jumping to out would
>> break anything.
> 
> Hi Heiner
> 
> It is useful to put this sort of analysis in the commit message. You
> then won't get people like me asking about it.
> 
Will add this to my "best practices" list ;)

>      Andrew
> 
Heiner
diff mbox series

Patch

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3df6aadc5..fd928979b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -861,9 +861,16 @@  void phy_start(struct phy_device *phydev)
 
 	mutex_lock(&phydev->lock);
 
+	if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) {
+		WARN(1, "called from state %s\n",
+		     phy_state_to_str(phydev->state));
+		goto out;
+	}
+
 	switch (phydev->state) {
 	case PHY_READY:
 		phydev->state = PHY_UP;
+		phy_start_machine(phydev);
 		break;
 	case PHY_HALTED:
 		/* if phy was suspended, bring the physical link up again */
@@ -877,13 +884,13 @@  void phy_start(struct phy_device *phydev)
 		}
 
 		phydev->state = PHY_RESUMING;
+		phy_start_machine(phydev);
 		break;
 	default:
 		break;
 	}
+out:
 	mutex_unlock(&phydev->lock);
-
-	phy_start_machine(phydev);
 }
 EXPORT_SYMBOL(phy_start);