All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] net: phy: leds: Add support for "link" trigger
@ 2017-10-31 11:56 Maciej S. Szmigiero
  2017-11-01 12:16 ` Andrew Lunn
  0 siblings, 1 reply; 9+ messages in thread
From: Maciej S. Szmigiero @ 2017-10-31 11:56 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli; +Cc: netdev, linux-kernel

Currently, we create a LED trigger for any link speed known to a PHY.
These triggers only fire when their exact link speed had been negotiated
(they aren't cumulative, that is, they don't fire for "their or any higher"
link speed).

What we are missing, however, is a trigger which will fire on any link
speed known to the PHY. Such trigger can then be used for implementing a
poor man's substitute of the "link" LED on boards that lack it.
Let's add it.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
---
Changes from v1: Don't keep the "link" trigger together with link speed
triggers in one array so we don't have to overload a SPEED_UNKNOWN speed
to mean the "link" trigger.

 drivers/net/phy/Kconfig            |  7 +++++--
 drivers/net/phy/phy_led_triggers.c | 43 +++++++++++++++++++++++++++++++++++---
 include/linux/phy.h                |  2 ++
 3 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index cd931cf9dcc2..3bcc2107ad77 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -191,11 +191,14 @@ config LED_TRIGGER_PHY
 	  Adds support for a set of LED trigger events per-PHY.  Link
 	  state change will trigger the events, for consumption by an
 	  LED class driver.  There are triggers for each link speed currently
-	  supported by the phy, and are of the form:
+	  supported by the PHY and also a one common "link" trigger as a
+	  logical-or of all the link speed ones.
+	  All these triggers are named according to the following pattern:
 	      <mii bus id>:<phy>:<speed>
 
 	  Where speed is in the form:
-		<Speed in megabits>Mbps or <Speed in gigabits>Gbps
+		<Speed in megabits>Mbps OR <Speed in gigabits>Gbps OR link
+		for any speed known to the PHY.
 
 
 comment "MII PHY device drivers"
diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
index 94ca42e630bb..dba937f0c61c 100644
--- a/drivers/net/phy/phy_led_triggers.c
+++ b/drivers/net/phy/phy_led_triggers.c
@@ -46,6 +46,10 @@ void phy_led_trigger_change_speed(struct phy_device *phy)
 	}
 
 	if (plt != phy->last_triggered) {
+		if (!phy->last_triggered)
+			led_trigger_event(&phy->led_link_trigger->trigger,
+					  LED_FULL);
+
 		led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
 		led_trigger_event(&plt->trigger, LED_FULL);
 		phy->last_triggered = plt;
@@ -56,11 +60,20 @@ void phy_led_trigger_change_speed(struct phy_device *phy)
 	if (phy->last_triggered) {
 		led_trigger_event(&phy->last_triggered->trigger,
 				  LED_OFF);
+		led_trigger_event(&phy->led_link_trigger->trigger,
+				  LED_OFF);
 		phy->last_triggered = NULL;
 	}
 }
 EXPORT_SYMBOL_GPL(phy_led_trigger_change_speed);
 
+static void phy_led_trigger_format_name(struct phy_device *phy, char *buf,
+					size_t size, char *suffix)
+{
+	snprintf(buf, size, PHY_ID_FMT ":%s",
+		 phy->mdio.bus->id, phy->mdio.addr, suffix);
+}
+
 static int phy_led_trigger_register(struct phy_device *phy,
 				    struct phy_led_trigger *plt,
 				    unsigned int speed)
@@ -77,8 +90,8 @@ static int phy_led_trigger_register(struct phy_device *phy,
 		snprintf(name_suffix, sizeof(name_suffix), "%dGbps",
 			 DIV_ROUND_CLOSEST(speed, 1000));
 
-	snprintf(plt->name, sizeof(plt->name), PHY_ID_FMT ":%s",
-		 phy->mdio.bus->id, phy->mdio.addr, name_suffix);
+	phy_led_trigger_format_name(phy, plt->name, sizeof(plt->name),
+				    name_suffix);
 	plt->trigger.name = plt->name;
 
 	return led_trigger_register(&plt->trigger);
@@ -99,13 +112,30 @@ int phy_led_triggers_register(struct phy_device *phy)
 	if (!phy->phy_num_led_triggers)
 		return 0;
 
+	phy->led_link_trigger = devm_kzalloc(&phy->mdio.dev,
+					     sizeof(*phy->led_link_trigger),
+					     GFP_KERNEL);
+	if (!phy->led_link_trigger) {
+		err = -ENOMEM;
+		goto out_clear;
+	}
+
+	phy_led_trigger_format_name(phy, phy->led_link_trigger->name,
+				    sizeof(phy->led_link_trigger->name),
+				    "link");
+	phy->led_link_trigger->trigger.name = phy->led_link_trigger->name;
+
+	err = led_trigger_register(&phy->led_link_trigger->trigger);
+	if (err)
+		goto out_free_link;
+
 	phy->phy_led_triggers = devm_kzalloc(&phy->mdio.dev,
 					    sizeof(struct phy_led_trigger) *
 						   phy->phy_num_led_triggers,
 					    GFP_KERNEL);
 	if (!phy->phy_led_triggers) {
 		err = -ENOMEM;
-		goto out_clear;
+		goto out_unreg_link;
 	}
 
 	for (i = 0; i < phy->phy_num_led_triggers; i++) {
@@ -123,6 +153,10 @@ int phy_led_triggers_register(struct phy_device *phy)
 	while (i--)
 		phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
 	devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
+out_unreg_link:
+	phy_led_trigger_unregister(phy->led_link_trigger);
+out_free_link:
+	devm_kfree(&phy->mdio.dev, phy->led_link_trigger);
 out_clear:
 	phy->phy_num_led_triggers = 0;
 	return err;
@@ -135,5 +169,8 @@ void phy_led_triggers_unregister(struct phy_device *phy)
 
 	for (i = 0; i < phy->phy_num_led_triggers; i++)
 		phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
+
+	if (phy->led_link_trigger)
+		phy_led_trigger_unregister(phy->led_link_trigger);
 }
 EXPORT_SYMBOL_GPL(phy_led_triggers_unregister);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index d78cd01ea513..dc82a07cb4fd 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -451,6 +451,8 @@ struct phy_device {
 	struct phy_led_trigger *phy_led_triggers;
 	unsigned int phy_num_led_triggers;
 	struct phy_led_trigger *last_triggered;
+
+	struct phy_led_trigger *led_link_trigger;
 #endif
 
 	/*

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-10-31 11:56 [PATCH v2] net: phy: leds: Add support for "link" trigger Maciej S. Szmigiero
@ 2017-11-01 12:16 ` Andrew Lunn
  2017-11-01 12:21   ` Maciej S. Szmigiero
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2017-11-01 12:16 UTC (permalink / raw)
  To: Maciej S. Szmigiero; +Cc: Florian Fainelli, netdev, linux-kernel

> @@ -123,6 +153,10 @@ int phy_led_triggers_register(struct phy_device *phy)
>  	while (i--)
>  		phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
>  	devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
> +out_unreg_link:
> +	phy_led_trigger_unregister(phy->led_link_trigger);
> +out_free_link:
> +	devm_kfree(&phy->mdio.dev, phy->led_link_trigger);

Hi Maciej

The point of the devm_ API is that you don't need to worry about
freeing the memory. The core will do it, when the driver is removed.

I guess you are just copying the code above, which i would also say is
unnecessary.

	Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 12:16 ` Andrew Lunn
@ 2017-11-01 12:21   ` Maciej S. Szmigiero
  2017-11-01 12:31     ` Andrew Lunn
  2017-11-01 12:37     ` Andrew Lunn
  0 siblings, 2 replies; 9+ messages in thread
From: Maciej S. Szmigiero @ 2017-11-01 12:21 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Florian Fainelli, netdev, linux-kernel

Hi Andrew,

On 01.11.2017 13:16, Andrew Lunn wrote:
>> @@ -123,6 +153,10 @@ int phy_led_triggers_register(struct phy_device *phy)
>>  	while (i--)
>>  		phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
>>  	devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
>> +out_unreg_link:
>> +	phy_led_trigger_unregister(phy->led_link_trigger);
>> +out_free_link:
>> +	devm_kfree(&phy->mdio.dev, phy->led_link_trigger);
> 
> Hi Maciej
> 
> The point of the devm_ API is that you don't need to worry about
> freeing the memory. The core will do it, when the driver is removed.
> 
> I guess you are just copying the code above, which i would also say is
> unnecessary.

Yes, I did it the same way as the existing code did for phy->phy_led_triggers
for reasons of both consistency and also to be on the safe side because
maybe there is some non-obvious reason why it has to be freed
explicitly (?).

> 	Andrew

Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 12:21   ` Maciej S. Szmigiero
@ 2017-11-01 12:31     ` Andrew Lunn
  2017-11-01 12:33       ` Maciej S. Szmigiero
  2017-11-01 12:37     ` Andrew Lunn
  1 sibling, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2017-11-01 12:31 UTC (permalink / raw)
  To: Maciej S. Szmigiero; +Cc: Florian Fainelli, netdev, linux-kernel

> Yes, I did it the same way as the existing code did for phy->phy_led_triggers
> for reasons of both consistency and also to be on the safe side because
> maybe there is some non-obvious reason why it has to be freed
> explicitly (?).
 
Hi Maciej

Occasionally, there is a need to call devm_kfree(). But i don't see
anything here why it is needed. So i would drop your devm_kfree(), and
if you feel like it, add an additional patch removing the existing
one.

Thanks
	Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 12:31     ` Andrew Lunn
@ 2017-11-01 12:33       ` Maciej S. Szmigiero
  2017-11-01 23:49         ` Maciej S. Szmigiero
  0 siblings, 1 reply; 9+ messages in thread
From: Maciej S. Szmigiero @ 2017-11-01 12:33 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Florian Fainelli, netdev, linux-kernel

Hi Andrew,

On 01.11.2017 13:31, Andrew Lunn wrote:
>> Yes, I did it the same way as the existing code did for phy->phy_led_triggers
>> for reasons of both consistency and also to be on the safe side because
>> maybe there is some non-obvious reason why it has to be freed
>> explicitly (?).
>  
> Hi Maciej
> 
> Occasionally, there is a need to call devm_kfree(). But i don't see
> anything here why it is needed. So i would drop your devm_kfree(), and
> if you feel like it, add an additional patch removing the existing
> one.

OK, will do as you suggest.

> Thanks
> 	Andrew
> 

Thanks,
Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 12:21   ` Maciej S. Szmigiero
  2017-11-01 12:31     ` Andrew Lunn
@ 2017-11-01 12:37     ` Andrew Lunn
  2017-11-01 12:43       ` Maciej S. Szmigiero
  1 sibling, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2017-11-01 12:37 UTC (permalink / raw)
  To: Maciej S. Szmigiero; +Cc: Florian Fainelli, netdev, linux-kernel

Hi Maciej

I don't particularly like the

       if (!phy->link)
                goto out_change_speed;

part of the existing code. Makes me thing of BASIC. goto is good for
error handling, but this is not an error.

If you feel like it, maybe you can refactor this code? Add a function like:

phy_led_trigger_no_link(struct phy_device *phy)
{
        if (phy->last_triggered) {
                led_trigger_event(&phy->last_triggered->trigger,
                                  LED_OFF);
                phy->last_triggered = NULL;
        }
}

and call it, rather than using goto? It then becomes a lot more
obvious what your change is doing, turning the LED off when there is
no link.

Thanks
   Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 12:37     ` Andrew Lunn
@ 2017-11-01 12:43       ` Maciej S. Szmigiero
  0 siblings, 0 replies; 9+ messages in thread
From: Maciej S. Szmigiero @ 2017-11-01 12:43 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Florian Fainelli, netdev, linux-kernel

Hi Andrew,

On 01.11.2017 13:37, Andrew Lunn wrote:
> Hi Maciej
> 
> I don't particularly like the
> 
>        if (!phy->link)
>                 goto out_change_speed;
> 
> part of the existing code. Makes me thing of BASIC. goto is good for
> error handling, but this is not an error.
> 
> If you feel like it, maybe you can refactor this code? Add a function like:
> 
> phy_led_trigger_no_link(struct phy_device *phy)
> {
>         if (phy->last_triggered) {
>                 led_trigger_event(&phy->last_triggered->trigger,
>                                   LED_OFF);
>                 phy->last_triggered = NULL;
>         }
> }
> 
> and call it, rather than using goto? It then becomes a lot more
> obvious what your change is doing, turning the LED off when there is
> no link.

All right, will do this, too.

> Thanks
>    Andrew
> 

Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 12:33       ` Maciej S. Szmigiero
@ 2017-11-01 23:49         ` Maciej S. Szmigiero
  2017-11-02  0:14           ` Andrew Lunn
  0 siblings, 1 reply; 9+ messages in thread
From: Maciej S. Szmigiero @ 2017-11-01 23:49 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Florian Fainelli, netdev, linux-kernel

Hi Andrew,

On 01.11.2017 13:33, Maciej S. Szmigiero wrote:
> On 01.11.2017 13:31, Andrew Lunn wrote:
>>> Yes, I did it the same way as the existing code did for phy->phy_led_triggers
>>> for reasons of both consistency and also to be on the safe side because
>>> maybe there is some non-obvious reason why it has to be freed
>>> explicitly (?).
>>  
>> Hi Maciej
>>
>> Occasionally, there is a need to call devm_kfree(). But i don't see
>> anything here why it is needed. So i would drop your devm_kfree(), and
>> if you feel like it, add an additional patch removing the existing
>> one.
> 
> OK, will do as you suggest.
> 

Upon closer inspection of the code it turned out that these devm_kfree()
calls actually had some purpose - the PHY core ignores the return value
of phy_led_triggers_register() and will successfully attach a PHY even
if this function returns an error.

In that case these LED trigger structures would unnecessary take some
memory, that's why (probably) the PHY LED code frees them on error
path.

Due to this I've decided to keep these calls to devm_kfree().

Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] net: phy: leds: Add support for "link" trigger
  2017-11-01 23:49         ` Maciej S. Szmigiero
@ 2017-11-02  0:14           ` Andrew Lunn
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2017-11-02  0:14 UTC (permalink / raw)
  To: Maciej S. Szmigiero; +Cc: Florian Fainelli, netdev, linux-kernel

On Thu, Nov 02, 2017 at 12:49:31AM +0100, Maciej S. Szmigiero wrote:
> Hi Andrew,
> 
> On 01.11.2017 13:33, Maciej S. Szmigiero wrote:
> > On 01.11.2017 13:31, Andrew Lunn wrote:
> >>> Yes, I did it the same way as the existing code did for phy->phy_led_triggers
> >>> for reasons of both consistency and also to be on the safe side because
> >>> maybe there is some non-obvious reason why it has to be freed
> >>> explicitly (?).
> >>  
> >> Hi Maciej
> >>
> >> Occasionally, there is a need to call devm_kfree(). But i don't see
> >> anything here why it is needed. So i would drop your devm_kfree(), and
> >> if you feel like it, add an additional patch removing the existing
> >> one.
> > 
> > OK, will do as you suggest.
> > 
> 
> Upon closer inspection of the code it turned out that these devm_kfree()
> calls actually had some purpose - the PHY core ignores the return value
> of phy_led_triggers_register() and will successfully attach a PHY even
> if this function returns an error.
> 
> In that case these LED trigger structures would unnecessary take some
> memory, that's why (probably) the PHY LED code frees them on error
> path.

O.K. Thanks for looking into this.

     Andrew

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-11-02  0:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-31 11:56 [PATCH v2] net: phy: leds: Add support for "link" trigger Maciej S. Szmigiero
2017-11-01 12:16 ` Andrew Lunn
2017-11-01 12:21   ` Maciej S. Szmigiero
2017-11-01 12:31     ` Andrew Lunn
2017-11-01 12:33       ` Maciej S. Szmigiero
2017-11-01 23:49         ` Maciej S. Szmigiero
2017-11-02  0:14           ` Andrew Lunn
2017-11-01 12:37     ` Andrew Lunn
2017-11-01 12:43       ` Maciej S. Szmigiero

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.