diff mbox series

[net-next,3/3] net: phy: bcm7xxx: request and manage GPHY clock

Message ID 20200903043947.3272453-4-f.fainelli@gmail.com
State Changes Requested
Delegated to: David Miller
Headers show
Series net: phy: Support enabling clocks prior to bus probe | expand

Commit Message

Florian Fainelli Sept. 3, 2020, 4:39 a.m. UTC
The internal Gigabit PHY on Broadcom STB chips has a digital clock which
drives its MDIO interface among other things, the driver now requests
and manage that clock during .probe() and .remove() accordingly.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/phy/bcm7xxx.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

Comments

Marco Felsch Sept. 4, 2020, 6:15 a.m. UTC | #1
Hi Florian,

On 20-09-02 21:39, Florian Fainelli wrote:
> The internal Gigabit PHY on Broadcom STB chips has a digital clock which
> drives its MDIO interface among other things, the driver now requests
> and manage that clock during .probe() and .remove() accordingly.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
>  drivers/net/phy/bcm7xxx.c | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
> index 692048d86ab1..f0ffcdcaef03 100644
> --- a/drivers/net/phy/bcm7xxx.c
> +++ b/drivers/net/phy/bcm7xxx.c
> @@ -11,6 +11,7 @@
>  #include "bcm-phy-lib.h"
>  #include <linux/bitops.h>
>  #include <linux/brcmphy.h>
> +#include <linux/clk.h>
>  #include <linux/mdio.h>
>  
>  /* Broadcom BCM7xxx internal PHY registers */
> @@ -39,6 +40,7 @@
>  
>  struct bcm7xxx_phy_priv {
>  	u64	*stats;
> +	struct clk *clk;
>  };
>  
>  static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
> @@ -534,7 +536,19 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
>  	if (!priv->stats)
>  		return -ENOMEM;
>  
> -	return 0;
> +	priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL);

Since the clock is binded to the mdio-dev here..

> +	if (IS_ERR(priv->clk))
> +		return PTR_ERR(priv->clk);
> +
> +	return clk_prepare_enable(priv->clk);

clould we use devm_add_action_or_reset() here so we don't have to
register the .remove() hook?

> +}
> +
> +static void bcm7xxx_28nm_remove(struct phy_device *phydev)
> +{
> +	struct bcm7xxx_phy_priv *priv = phydev->priv;
> +
> +	clk_disable_unprepare(priv->clk);
> +	devm_clk_put(&phydev->mdio.dev, priv->clk);

Is this really necessary? The devm_clk_get_optional() function already
registers the devm_clk_release() hook.

Regards,
  Marco

>  }
>  
>  #define BCM7XXX_28NM_GPHY(_oui, _name)					\
> @@ -552,6 +566,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
>  	.get_strings	= bcm_phy_get_strings,				\
>  	.get_stats	= bcm7xxx_28nm_get_phy_stats,			\
>  	.probe		= bcm7xxx_28nm_probe,				\
> +	.remove		= bcm7xxx_28nm_remove,				\
>  }
>  
>  #define BCM7XXX_28NM_EPHY(_oui, _name)					\
> @@ -567,6 +582,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
>  	.get_strings	= bcm_phy_get_strings,				\
>  	.get_stats	= bcm7xxx_28nm_get_phy_stats,			\
>  	.probe		= bcm7xxx_28nm_probe,				\
> +	.remove		= bcm7xxx_28nm_remove,				\
>  }
>  
>  #define BCM7XXX_40NM_EPHY(_oui, _name)					\
> -- 
> 2.25.1
> 
>
Marco Felsch Sept. 4, 2020, 6:18 a.m. UTC | #2
On 20-09-02 21:39, Florian Fainelli wrote:
> The internal Gigabit PHY on Broadcom STB chips has a digital clock which
> drives its MDIO interface among other things, the driver now requests
> and manage that clock during .probe() and .remove() accordingly.

Hi Florian,

Seems like you added the same support here like I did for the smsc
driver. So should I go with my proposed patch which can be adapted later
after you guys figured out who to enable the required resources?

Regards,
  Marco
Florian Fainelli Sept. 4, 2020, 3:37 p.m. UTC | #3
On 9/3/2020 11:15 PM, Marco Felsch wrote:
> Hi Florian,
> 
> On 20-09-02 21:39, Florian Fainelli wrote:
>> The internal Gigabit PHY on Broadcom STB chips has a digital clock which
>> drives its MDIO interface among other things, the driver now requests
>> and manage that clock during .probe() and .remove() accordingly.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>>   drivers/net/phy/bcm7xxx.c | 18 +++++++++++++++++-
>>   1 file changed, 17 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
>> index 692048d86ab1..f0ffcdcaef03 100644
>> --- a/drivers/net/phy/bcm7xxx.c
>> +++ b/drivers/net/phy/bcm7xxx.c
>> @@ -11,6 +11,7 @@
>>   #include "bcm-phy-lib.h"
>>   #include <linux/bitops.h>
>>   #include <linux/brcmphy.h>
>> +#include <linux/clk.h>
>>   #include <linux/mdio.h>
>>   
>>   /* Broadcom BCM7xxx internal PHY registers */
>> @@ -39,6 +40,7 @@
>>   
>>   struct bcm7xxx_phy_priv {
>>   	u64	*stats;
>> +	struct clk *clk;
>>   };
>>   
>>   static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
>> @@ -534,7 +536,19 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
>>   	if (!priv->stats)
>>   		return -ENOMEM;
>>   
>> -	return 0;
>> +	priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL);
> 
> Since the clock is binded to the mdio-dev here..
> 
>> +	if (IS_ERR(priv->clk))
>> +		return PTR_ERR(priv->clk);
>> +
>> +	return clk_prepare_enable(priv->clk);
> 
> clould we use devm_add_action_or_reset() here so we don't have to
> register the .remove() hook?

Maybe, more on that below.

> 
>> +}
>> +
>> +static void bcm7xxx_28nm_remove(struct phy_device *phydev)
>> +{
>> +	struct bcm7xxx_phy_priv *priv = phydev->priv;
>> +
>> +	clk_disable_unprepare(priv->clk);
>> +	devm_clk_put(&phydev->mdio.dev, priv->clk);
> 
> Is this really necessary? The devm_clk_get_optional() function already
> registers the devm_clk_release() hook.

Yes, because you can unbind the PHY driver from sysfs, and if you want 
to bind that driver again, which will call .probe() again, you must undo 
strictly everything that .probe() did. The embedded mdio_device does not 
go away, so there will be no automatic freeing of resources. Using 
devm_* may be confusing, so using just the plain clk_get() and clk_put() 
may be clearer here.
Florian Fainelli Sept. 4, 2020, 3:38 p.m. UTC | #4
On 9/3/2020 11:18 PM, Marco Felsch wrote:
> On 20-09-02 21:39, Florian Fainelli wrote:
>> The internal Gigabit PHY on Broadcom STB chips has a digital clock which
>> drives its MDIO interface among other things, the driver now requests
>> and manage that clock during .probe() and .remove() accordingly.
> 
> Hi Florian,
> 
> Seems like you added the same support here like I did for the smsc
> driver. So should I go with my proposed patch which can be adapted later
> after you guys figured out who to enable the required resources?

That seems fine to me, on your platform there appears to be an 
assumption that we will be able to probe the SMSC PHY because everything 
we need is already enabled, right? If so, this patch series does not 
change that state.
Marco Felsch Sept. 7, 2020, 7:34 a.m. UTC | #5
On 20-09-04 08:37, Florian Fainelli wrote:
> 
> 
> On 9/3/2020 11:15 PM, Marco Felsch wrote:
> > Hi Florian,
> > 
> > On 20-09-02 21:39, Florian Fainelli wrote:
> > > The internal Gigabit PHY on Broadcom STB chips has a digital clock which
> > > drives its MDIO interface among other things, the driver now requests
> > > and manage that clock during .probe() and .remove() accordingly.
> > > 
> > > Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> > > ---
> > >   drivers/net/phy/bcm7xxx.c | 18 +++++++++++++++++-
> > >   1 file changed, 17 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
> > > index 692048d86ab1..f0ffcdcaef03 100644
> > > --- a/drivers/net/phy/bcm7xxx.c
> > > +++ b/drivers/net/phy/bcm7xxx.c
> > > @@ -11,6 +11,7 @@
> > >   #include "bcm-phy-lib.h"
> > >   #include <linux/bitops.h>
> > >   #include <linux/brcmphy.h>
> > > +#include <linux/clk.h>
> > >   #include <linux/mdio.h>
> > >   /* Broadcom BCM7xxx internal PHY registers */
> > > @@ -39,6 +40,7 @@
> > >   struct bcm7xxx_phy_priv {
> > >   	u64	*stats;
> > > +	struct clk *clk;
> > >   };
> > >   static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
> > > @@ -534,7 +536,19 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
> > >   	if (!priv->stats)
> > >   		return -ENOMEM;
> > > -	return 0;
> > > +	priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL);
> > 
> > Since the clock is binded to the mdio-dev here..
> > 
> > > +	if (IS_ERR(priv->clk))
> > > +		return PTR_ERR(priv->clk);
> > > +
> > > +	return clk_prepare_enable(priv->clk);
> > 
> > clould we use devm_add_action_or_reset() here so we don't have to
> > register the .remove() hook?
> 
> Maybe, more on that below.
> 
> > 
> > > +}
> > > +
> > > +static void bcm7xxx_28nm_remove(struct phy_device *phydev)
> > > +{
> > > +	struct bcm7xxx_phy_priv *priv = phydev->priv;
> > > +
> > > +	clk_disable_unprepare(priv->clk);
> > > +	devm_clk_put(&phydev->mdio.dev, priv->clk);
> > 
> > Is this really necessary? The devm_clk_get_optional() function already
> > registers the devm_clk_release() hook.
> 
> Yes, because you can unbind the PHY driver from sysfs, and if you want to
> bind that driver again, which will call .probe() again, you must undo
> strictly everything that .probe() did. The embedded mdio_device does not go
> away, so there will be no automatic freeing of resources.

Okay I got this. Sry. I'm not that deep into the net-stack and the
device live time. Thanks for the clarification.

> Using devm_* may
> be confusing, so using just the plain clk_get() and clk_put() may be clearer
> here.

That would be better for others including me because I detected a
failure on my patchset.

Regards,
  Marco
Marco Felsch Sept. 7, 2020, 7:37 a.m. UTC | #6
On 20-09-04 08:38, Florian Fainelli wrote:
> 
> 
> On 9/3/2020 11:18 PM, Marco Felsch wrote:
> > On 20-09-02 21:39, Florian Fainelli wrote:
> > > The internal Gigabit PHY on Broadcom STB chips has a digital clock which
> > > drives its MDIO interface among other things, the driver now requests
> > > and manage that clock during .probe() and .remove() accordingly.
> > 
> > Hi Florian,
> > 
> > Seems like you added the same support here like I did for the smsc
> > driver. So should I go with my proposed patch which can be adapted later
> > after you guys figured out who to enable the required resources?
> 
> That seems fine to me, on your platform there appears to be an assumption
> that we will be able to probe the SMSC PHY because everything we need is
> already enabled, right? If so, this patch series does not change that state.

Unfortunately yes.. The imx-fec driver enables all DT-specified clock
and then the mdio-bus probe is initiated. The good point is that my
patchset do not require a clock-id so the generic way can replace my
work later.

Regards,
  Marco
Marco Felsch Sept. 7, 2020, 7:07 p.m. UTC | #7
On 20-09-04 08:37, Florian Fainelli wrote:

...

> > Is this really necessary? The devm_clk_get_optional() function already
> > registers the devm_clk_release() hook.
> 
> Yes, because you can unbind the PHY driver from sysfs, and if you want to
> bind that driver again, which will call .probe() again, you must undo
> strictly everything that .probe() did. The embedded mdio_device does not go
> away, so there will be no automatic freeing of resources. Using devm_* may
> be confusing, so using just the plain clk_get() and clk_put() may be clearer
> here.

Hi Florian,

sorry for asking again... I'm getting a bit confused during applying
your comments to my smsc-phy patchset.
A few drivers are using the devm_kzalloc() (including your bcm7xxx.c and
my smsc.c). Does this mean that those drivers have a memory leak since
the mdio_device does not disappear and so the memory allocated during
probe() isn't freed?

Regards,
  Marco
diff mbox series

Patch

diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
index 692048d86ab1..f0ffcdcaef03 100644
--- a/drivers/net/phy/bcm7xxx.c
+++ b/drivers/net/phy/bcm7xxx.c
@@ -11,6 +11,7 @@ 
 #include "bcm-phy-lib.h"
 #include <linux/bitops.h>
 #include <linux/brcmphy.h>
+#include <linux/clk.h>
 #include <linux/mdio.h>
 
 /* Broadcom BCM7xxx internal PHY registers */
@@ -39,6 +40,7 @@ 
 
 struct bcm7xxx_phy_priv {
 	u64	*stats;
+	struct clk *clk;
 };
 
 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
@@ -534,7 +536,19 @@  static int bcm7xxx_28nm_probe(struct phy_device *phydev)
 	if (!priv->stats)
 		return -ENOMEM;
 
-	return 0;
+	priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->clk);
+
+	return clk_prepare_enable(priv->clk);
+}
+
+static void bcm7xxx_28nm_remove(struct phy_device *phydev)
+{
+	struct bcm7xxx_phy_priv *priv = phydev->priv;
+
+	clk_disable_unprepare(priv->clk);
+	devm_clk_put(&phydev->mdio.dev, priv->clk);
 }
 
 #define BCM7XXX_28NM_GPHY(_oui, _name)					\
@@ -552,6 +566,7 @@  static int bcm7xxx_28nm_probe(struct phy_device *phydev)
 	.get_strings	= bcm_phy_get_strings,				\
 	.get_stats	= bcm7xxx_28nm_get_phy_stats,			\
 	.probe		= bcm7xxx_28nm_probe,				\
+	.remove		= bcm7xxx_28nm_remove,				\
 }
 
 #define BCM7XXX_28NM_EPHY(_oui, _name)					\
@@ -567,6 +582,7 @@  static int bcm7xxx_28nm_probe(struct phy_device *phydev)
 	.get_strings	= bcm_phy_get_strings,				\
 	.get_stats	= bcm7xxx_28nm_get_phy_stats,			\
 	.probe		= bcm7xxx_28nm_probe,				\
+	.remove		= bcm7xxx_28nm_remove,				\
 }
 
 #define BCM7XXX_40NM_EPHY(_oui, _name)					\