diff mbox

[1/2] net: smsc911x: Fix register_netdev, phy startup, driver unload ordering

Message ID 1472747141-15886-2-git-send-email-jeremy.linton@arm.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Jeremy Linton Sept. 1, 2016, 4:25 p.m. UTC
Move phy startup/shutdown into the smsc911x_open/stop routines. This
allows the module to be unloaded because phy_connect_direct is no longer
always holding the module use count. This one change also resolves a
number of other problems.

The link status of a downed interface no longer reflects a stale state.
Errors caused by the net device being opened before the mdio/phy was
configured. There is also a potential power savings as the phy's don't
remain powered when the interface isn't running.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 drivers/net/ethernet/smsc/smsc911x.c | 51 ++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 23 deletions(-)

Comments

Andrew Lunn Sept. 1, 2016, 4:58 p.m. UTC | #1
> @@ -1520,17 +1513,22 @@ static int smsc911x_open(struct net_device *dev)
>  	unsigned int timeout;
>  	unsigned int temp;
>  	unsigned int intcfg;
> +	int retval;
>  
> -	/* if the phy is not yet registered, retry later*/
> +	/* find and start the given phy */
>  	if (!dev->phydev) {
> -		SMSC_WARN(pdata, hw, "phy_dev is NULL");
> -		return -EAGAIN;
> +		if (smsc911x_mii_probe(dev) < 0) {
> +			SMSC_WARN(pdata, probe, "Error starting phy");
> +			retval = -EAGAIN;

smsc911x_mii_probe() returns an error code. It is better to use that,
than -EAGAIN, which is rather odd to start with.

> +			goto out;
> +		}
>  	}
>  
>  	/* Reset the LAN911x */
>  	if (smsc911x_soft_reset(pdata)) {
>  		SMSC_WARN(pdata, hw, "soft reset failed");
> -		return -EIO;
> +		retval = -EIO;
> +		goto mii_free_out;

smsc911x_soft_reset() also returns an error code you should use.

This patch also seems to do quite a few different things. Please can
you break it up into multiple patches.

Thanks
	Andrew
Jeremy Linton Sept. 1, 2016, 6:42 p.m. UTC | #2
On 09/01/2016 11:58 AM, Andrew Lunn wrote:
>> @@ -1520,17 +1513,22 @@ static int smsc911x_open(struct net_device *dev)
>>  	unsigned int timeout;
>>  	unsigned int temp;
>>  	unsigned int intcfg;
>> +	int retval;
>>
>> -	/* if the phy is not yet registered, retry later*/
>> +	/* find and start the given phy */
>>  	if (!dev->phydev) {
>> -		SMSC_WARN(pdata, hw, "phy_dev is NULL");
>> -		return -EAGAIN;
>> +		if (smsc911x_mii_probe(dev) < 0) {
>> +			SMSC_WARN(pdata, probe, "Error starting phy");
>> +			retval = -EAGAIN;
>
> smsc911x_mii_probe() returns an error code. It is better to use that,
> than -EAGAIN, which is rather odd to start with.

	Thats a good point, I was just maintaining the existing behavior, but 
its definitely better to just return the actual error.

>
>> +			goto out;
>> +		}
>>  	}
>>
>>  	/* Reset the LAN911x */
>>  	if (smsc911x_soft_reset(pdata)) {
>>  		SMSC_WARN(pdata, hw, "soft reset failed");
>> -		return -EIO;
>> +		retval = -EIO;
>> +		goto mii_free_out;
>
> smsc911x_soft_reset() also returns an error code you should use.
>
> This patch also seems to do quite a few different things. Please can
> you break it up into multiple patches.
	

	That was the comment from the previous patch, but It confused me 
because it was only really moving the MDIO startup, the rest was a side 
effect of that and atomic to it (AKA it wasn't clear how to make it 
smaller). I read it as Steve misinterpreting the laundry list of fixes 
as things being individually fixed, rather than one thing fixing a bunch 
of stuff.

This patch does add additional code I overlooked to cleanup the phy if 
it fails, I guess in theory that portion could be a prereq patch, I will 
break that portion out. I'm still not sure how to partially move the 
MDIO startup...
Andrew Lunn Sept. 1, 2016, 7:22 p.m. UTC | #3
> This patch does add additional code I overlooked to cleanup the phy
> if it fails, I guess in theory that portion could be a prereq patch,
> I will break that portion out. I'm still not sure how to partially
> move the MDIO startup...

Hi Jeremy

You can add a cleanup patch which replaces these hard coded return
values with the value returned by the function calls. Then do the
move.

In general, it is easier to review lots of small obvious patches, than
one big patch with lots of things going on.

    Andrew
diff mbox

Patch

diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index ca31345..6d6dcfe 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1099,15 +1099,8 @@  static int smsc911x_mii_init(struct platform_device *pdev,
 		goto err_out_free_bus_2;
 	}
 
-	if (smsc911x_mii_probe(dev) < 0) {
-		SMSC_WARN(pdata, probe, "Error registering mii bus");
-		goto err_out_unregister_bus_3;
-	}
-
 	return 0;
 
-err_out_unregister_bus_3:
-	mdiobus_unregister(pdata->mii_bus);
 err_out_free_bus_2:
 	mdiobus_free(pdata->mii_bus);
 err_out_1:
@@ -1520,17 +1513,22 @@  static int smsc911x_open(struct net_device *dev)
 	unsigned int timeout;
 	unsigned int temp;
 	unsigned int intcfg;
+	int retval;
 
-	/* if the phy is not yet registered, retry later*/
+	/* find and start the given phy */
 	if (!dev->phydev) {
-		SMSC_WARN(pdata, hw, "phy_dev is NULL");
-		return -EAGAIN;
+		if (smsc911x_mii_probe(dev) < 0) {
+			SMSC_WARN(pdata, probe, "Error starting phy");
+			retval = -EAGAIN;
+			goto out;
+		}
 	}
 
 	/* Reset the LAN911x */
 	if (smsc911x_soft_reset(pdata)) {
 		SMSC_WARN(pdata, hw, "soft reset failed");
-		return -EIO;
+		retval = -EIO;
+		goto mii_free_out;
 	}
 
 	smsc911x_reg_write(pdata, HW_CFG, 0x00050000);
@@ -1600,7 +1598,8 @@  static int smsc911x_open(struct net_device *dev)
 	if (!pdata->software_irq_signal) {
 		netdev_warn(dev, "ISR failed signaling test (IRQ %d)\n",
 			    dev->irq);
-		return -ENODEV;
+		retval = -ENODEV;
+		goto mii_free_out;
 	}
 	SMSC_TRACE(pdata, ifup, "IRQ handler passed test using IRQ %d",
 		   dev->irq);
@@ -1646,6 +1645,12 @@  static int smsc911x_open(struct net_device *dev)
 
 	netif_start_queue(dev);
 	return 0;
+
+mii_free_out:
+	phy_disconnect(dev->phydev);
+	dev->phydev = NULL;
+out:
+	return retval;
 }
 
 /* Entry point for stopping the interface */
@@ -1668,8 +1673,11 @@  static int smsc911x_stop(struct net_device *dev)
 	smsc911x_tx_update_txcounters(dev);
 
 	/* Bring the PHY down */
-	if (dev->phydev)
+	if (dev->phydev) {
 		phy_stop(dev->phydev);
+		phy_disconnect(dev->phydev);
+		dev->phydev = NULL;
+	}
 
 	SMSC_TRACE(pdata, ifdown, "Interface stopped");
 	return 0;
@@ -2291,11 +2299,10 @@  static int smsc911x_drv_remove(struct platform_device *pdev)
 	pdata = netdev_priv(dev);
 	BUG_ON(!pdata);
 	BUG_ON(!pdata->ioaddr);
-	BUG_ON(!dev->phydev);
+	WARN_ON(dev->phydev);
 
 	SMSC_TRACE(pdata, ifdown, "Stopping driver");
 
-	phy_disconnect(dev->phydev);
 	mdiobus_unregister(pdata->mii_bus);
 	mdiobus_free(pdata->mii_bus);
 
@@ -2494,6 +2501,12 @@  static int smsc911x_drv_probe(struct platform_device *pdev)
 
 	netif_carrier_off(dev);
 
+	retval = smsc911x_mii_init(pdev, dev);
+	if (retval) {
+		SMSC_WARN(pdata, probe, "Error %i initialising mii", retval);
+		goto out_free_irq;
+	}
+
 	retval = register_netdev(dev);
 	if (retval) {
 		SMSC_WARN(pdata, probe, "Error %i registering device", retval);
@@ -2503,12 +2516,6 @@  static int smsc911x_drv_probe(struct platform_device *pdev)
 			   "Network interface: \"%s\"", dev->name);
 	}
 
-	retval = smsc911x_mii_init(pdev, dev);
-	if (retval) {
-		SMSC_WARN(pdata, probe, "Error %i initialising mii", retval);
-		goto out_unregister_netdev_5;
-	}
-
 	spin_lock_irq(&pdata->mac_lock);
 
 	/* Check if mac address has been specified when bringing interface up */
@@ -2544,8 +2551,6 @@  static int smsc911x_drv_probe(struct platform_device *pdev)
 
 	return 0;
 
-out_unregister_netdev_5:
-	unregister_netdev(dev);
 out_free_irq:
 	free_irq(dev->irq, dev);
 out_disable_resources: