From: Marek Behún <kabel@kernel.org> Date: 2021-05-26 18:01:35
Hello,
I am sending the first non-RFC version of the series adding support
for offloading LED triggers to HW, with the netdev trigger being the
first user.
I have addressed the issues with the RFC version from October.
This version only implements the offloading API and adds support for
offloading to the netdev trigger. In the RFC I also added one user of
this API (Marvell ethernet PHY driver). I plan to continue the work on
those patches once the offloading API is finally merged.
Also, there is now other possible user for this API: leds-nuc driver
by Mauro.
Changes since RFC:
- split the patch adding HW offloading support to netdev trigger into
several separate patches (suggested by Pavel):
1. move trigger data structure to include/linux/ledtrig.h
2. support HW offloading
3. change spinlock to mutex
- fixed bug where the .offloaded variable was not set to false when
offloading was disabled (suggested by Pavel)
- removed the code saving one call to set_baseline_state() on the
NETDEV_CHANGE event. It is not needed, the trigger_offload() method
can handle this situation on its own (suggested by Pavel)
- documentation now explicitly says that when offloading is being
disabled, the function must return 0 (no error) (suggested by Pavel)
Marek Behún (5):
leds: trigger: netdev: don't explicitly zero kzalloced data
leds: trigger: add API for HW offloading of triggers
leds: trigger: netdev: move trigger data structure to global include
dir
leds: trigger: netdev: support HW offloading
leds: trigger: netdev: change spinlock to mutex
Documentation/leds/leds-class.rst | 22 +++++++++++++
drivers/leds/led-triggers.c | 1 +
drivers/leds/trigger/ledtrig-netdev.c | 47 ++++++++-------------------
include/linux/leds.h | 29 +++++++++++++++++
include/linux/ledtrig.h | 40 +++++++++++++++++++++++
5 files changed, 105 insertions(+), 34 deletions(-)
create mode 100644 include/linux/ledtrig.h
--
2.26.3
From: Marek Behún <kabel@kernel.org> Date: 2021-05-26 18:01:37
The trigger_data struct is allocated with kzalloc, so we do not need to
explicitly set members to zero.
Signed-off-by: Marek Behún <kabel@kernel.org>
Acked-by: Pavel Machek <redacted>
---
drivers/leds/trigger/ledtrig-netdev.c | 4 ----
1 file changed, 4 deletions(-)
From: Marek Behún <kabel@kernel.org> Date: 2021-05-26 18:01:39
Add method trigger_offload() and member variable `offloaded` to struct
led_classdev. Add helper functions led_trigger_offload() and
led_trigger_offload_stop().
The trigger_offload() method, when implemented by the LED driver, should
be called (via led_trigger_offload() function) from trigger code wanting
to be offloaded at the moment when configuration of the trigger changes.
If the trigger is successfully offloaded, this method returns 0 and the
trigger does not have to blink the LED in software.
If the trigger with given configuration cannot be offloaded, the method
should return -EOPNOTSUPP, in which case the trigger must blink the LED
in SW.
The second argument to trigger_offload() being false means that the
offloading is being disabled. In this case the function must return 0,
errors are not permitted.
Signed-off-by: Marek Behún <kabel@kernel.org>
---
Documentation/leds/leds-class.rst | 22 ++++++++++++++++++++++
drivers/leds/led-triggers.c | 1 +
include/linux/leds.h | 29 +++++++++++++++++++++++++++++
3 files changed, 52 insertions(+)
@@ -169,6 +169,28 @@ Setting the brightness to zero with brightness_set() callback function should completely turn off the LED and cancel the previously programmed hardware blinking function, if any.+Hardware offloading of LED triggers+===================================++Some LEDs can offload SW triggers to hardware (for example a LED connected to+an ethernet PHY or an ethernet switch can be configured to blink on activity on+the network, which in software is done by the netdev trigger).++To do such offloading, both the trigger code and LED driver must support this.+The LED must implement the trigger_offload() method and the trigger code must+try to call this method (via led_trigger_offload() function) when configuration+of the trigger (trigger_data) changes.++The implementation of the trigger_offload() method by the LED driver must return+0 if the offload is successful and -EOPNOTSUPP if the requested trigger+configuration is not supported and the trigger should be executed in software.+If trigger_offload() returns negative value, the trigger will be done in+software, so any active offloading must also be disabled.++If the second argument (enable) to the trigger_offload() method is false, any+active HW offloading must be deactivated. In this case errors are not permitted+in the trigger_offload() method.+ Known Issues ============
@@ -148,6 +148,11 @@ struct led_classdev {/* LEDs that have private triggers have this set */structled_hw_trigger_type*trigger_type;++/* some LEDs may be able to offload some SW triggers to HW */+int(*trigger_offload)(structled_classdev*led_cdev,+boolenable);+booloffloaded;#endif#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
From: Marek Behún <kabel@kernel.org> Date: 2021-05-26 18:01:43
In preparation for HW offloading of netdev trigger, move struct
led_trigger_data into global include directory, into file
linux/ledtrig.h, so that drivers wanting to offload the trigger can see
the requested settings.
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/leds/trigger/ledtrig-netdev.c | 23 +---------------
include/linux/ledtrig.h | 38 +++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 22 deletions(-)
create mode 100644 include/linux/ledtrig.h
From: Marek Behún <kabel@kernel.org> Date: 2021-05-26 18:01:46
Add support for HW offloading of the netdev trigger.
We need to export the netdev_led_trigger variable so that drivers may
check whether the LED is set to this trigger.
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/leds/trigger/ledtrig-netdev.c | 6 +++++-
include/linux/ledtrig.h | 2 ++
2 files changed, 7 insertions(+), 1 deletion(-)
From: Marek Behún <kabel@kernel.org> Date: 2021-05-26 18:01:48
Using spinlocks requires that the trigger_offload() method cannot sleep.
This can be problematic for some hardware, since access to registers may
sleep.
We can change the spinlock to mutex because, according to Jacek:
register_netdevice_notifier() registers raw notifier chain,
whose callbacks are not called from atomic context and there are
no restrictions on callbacks. See include/linux/notifier.h.
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/leds/trigger/ledtrig-netdev.c | 14 +++++++-------
include/linux/ledtrig.h | 4 ++--
2 files changed, 9 insertions(+), 9 deletions(-)
From: Andrew Lunn <andrew@lunn.ch> Date: 2021-05-27 16:38:45
On Wed, May 26, 2021 at 08:00:16PM +0200, Marek Behún wrote:
The trigger_data struct is allocated with kzalloc, so we do not need to
explicitly set members to zero.
Signed-off-by: Marek Behún <kabel@kernel.org>
Acked-by: Pavel Machek <redacted>
From: Andrew Lunn <andrew@lunn.ch> Date: 2021-05-27 16:48:24
On Wed, May 26, 2021 at 08:00:18PM +0200, Marek Behún wrote:
In preparation for HW offloading of netdev trigger, move struct
led_trigger_data into global include directory, into file
linux/ledtrig.h, so that drivers wanting to offload the trigger can see
the requested settings.
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/leds/trigger/ledtrig-netdev.c | 23 +---------------
include/linux/ledtrig.h | 38 +++++++++++++++++++++++++++
I'm wondering how this is going to scale, if we have a lot of triggers
which can be offloaded. Rather than try to pack them all into
one header, would it make more sense to add
include/linux/led/ledtrig-netdev.h
Andrew
From: Andrew Lunn <andrew@lunn.ch> Date: 2021-05-27 16:57:21
On Wed, May 26, 2021 at 08:00:19PM +0200, Marek Behún wrote:
Add support for HW offloading of the netdev trigger.
We need to export the netdev_led_trigger variable so that drivers may
check whether the LED is set to this trigger.
Without seeing the driver side, it is not obvious to me why this is
needed. Please add the driver changes to this patchset, so we can
fully see how the API works.
From: Marek Behún <hidden> Date: 2021-05-28 06:30:03
On Thu, 27 May 2021 18:48:21 +0200
Andrew Lunn [off-list ref] wrote:
On Wed, May 26, 2021 at 08:00:18PM +0200, Marek Behún wrote:
quoted
In preparation for HW offloading of netdev trigger, move struct
led_trigger_data into global include directory, into file
linux/ledtrig.h, so that drivers wanting to offload the trigger can
see the requested settings.
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/leds/trigger/ledtrig-netdev.c | 23 +---------------
include/linux/ledtrig.h | 38
+++++++++++++++++++++++++++
I'm wondering how this is going to scale, if we have a lot of triggers
which can be offloaded. Rather than try to pack them all into
one header, would it make more sense to add
include/linux/led/ledtrig-netdev.h
Andrew
Hmm, I guess you are right. Also when looking at a LED controller
driver we could immediately see which triggers this driver can offload,
when looking at headers included.
From: Marek Behún <hidden> Date: 2021-05-28 06:47:06
On Thu, 27 May 2021 18:57:17 +0200
Andrew Lunn [off-list ref] wrote:
On Wed, May 26, 2021 at 08:00:19PM +0200, Marek Behún wrote:
quoted
Add support for HW offloading of the netdev trigger.
We need to export the netdev_led_trigger variable so that drivers
may check whether the LED is set to this trigger.
Without seeing the driver side, it is not obvious to me why this is
needed. Please add the driver changes to this patchset, so we can
fully see how the API works.
OK, I will send an implementation for leds-turris-omnia with v2.
The idea is that the trigger_offload() method should check which
trigger it should offload. A potential LED controller may be configured
to link the LED on net activity, or on SATA activity. So the method
should do something like this:
static int my_trigger_offload(struct led_classdev *cdev, bool enable)
{
if (!enable)
return my_disable_hw_triggering(cdev);
if (cdev->trigger == &netdev_led_trigger)
return my_offload_netdev_triggering(cdev);
else if (cdev->trigger == &blkdev_led_trigger)
return my_offload_blkdev_triggering(cdev);
else
return -EOPNOTSUPP;
}
If these are going to be exported, maybe they should be made const to
protect them a bit?
The trigger structure must be defined writable, for the code holds
a list of LEDs that have this trigger activated in the structure, among
other data. I don't think if it can be declared as const and then
defined non-const.
Marek
From: Andrew Lunn <andrew@lunn.ch> Date: 2021-05-28 13:50:14
On Fri, May 28, 2021 at 08:45:56AM +0200, Marek Behún wrote:
On Thu, 27 May 2021 18:57:17 +0200
Andrew Lunn [off-list ref] wrote:
quoted
On Wed, May 26, 2021 at 08:00:19PM +0200, Marek Behún wrote:
quoted
Add support for HW offloading of the netdev trigger.
We need to export the netdev_led_trigger variable so that drivers
may check whether the LED is set to this trigger.
Without seeing the driver side, it is not obvious to me why this is
needed. Please add the driver changes to this patchset, so we can
fully see how the API works.
OK, I will send an implementation for leds-turris-omnia with v2.
The idea is that the trigger_offload() method should check which
trigger it should offload. A potential LED controller may be configured
to link the LED on net activity, or on SATA activity. So the method
should do something like this:
static int my_trigger_offload(struct led_classdev *cdev, bool enable)
{
if (!enable)
return my_disable_hw_triggering(cdev);
if (cdev->trigger == &netdev_led_trigger)
return my_offload_netdev_triggering(cdev);
else if (cdev->trigger == &blkdev_led_trigger)
return my_offload_blkdev_triggering(cdev);
else
return -EOPNOTSUPP;
}
So the hardware driver does not need the contents of the trigger? It
never manipulates the trigger. Maybe to keep the abstraction cleaner,
an enum can be added to the trigger to identify it. The code then
becomes:
static int my_trigger_offload(struct led_classdev *cdev, bool enable)
{
if (!enable)
return my_disable_hw_triggering(cdev);
switch(cdev->trigger->trigger) {
case TRIGGER_NETDEV:
return my_offload_netdev_triggering(cdev);
case TRIGGER_BLKDEV:
return my_offload_blkdev_triggering(cdev);
default:
return -EOPNOTSUPP;
}
Andrew
From: Marek Behún <hidden> Date: 2021-05-28 13:57:48
On Fri, 28 May 2021 15:50:08 +0200
Andrew Lunn [off-list ref] wrote:
On Fri, May 28, 2021 at 08:45:56AM +0200, Marek Behún wrote:
quoted
On Thu, 27 May 2021 18:57:17 +0200
Andrew Lunn [off-list ref] wrote:
quoted
On Wed, May 26, 2021 at 08:00:19PM +0200, Marek Behún wrote:
quoted
Add support for HW offloading of the netdev trigger.
We need to export the netdev_led_trigger variable so that
drivers may check whether the LED is set to this trigger.
Without seeing the driver side, it is not obvious to me why this
is needed. Please add the driver changes to this patchset, so we
can fully see how the API works.
OK, I will send an implementation for leds-turris-omnia with v2.
The idea is that the trigger_offload() method should check which
trigger it should offload. A potential LED controller may be
configured to link the LED on net activity, or on SATA activity. So
the method should do something like this:
static int my_trigger_offload(struct led_classdev *cdev, bool
enable) {
if (!enable)
return my_disable_hw_triggering(cdev);
if (cdev->trigger == &netdev_led_trigger)
return my_offload_netdev_triggering(cdev);
else if (cdev->trigger == &blkdev_led_trigger)
return my_offload_blkdev_triggering(cdev);
else
return -EOPNOTSUPP;
}
So the hardware driver does not need the contents of the trigger? It
never manipulates the trigger. Maybe to keep the abstraction cleaner,
an enum can be added to the trigger to identify it. The code then
becomes:
static int my_trigger_offload(struct led_classdev *cdev, bool enable)
{
if (!enable)
return my_disable_hw_triggering(cdev);
switch(cdev->trigger->trigger) {
case TRIGGER_NETDEV:
return my_offload_netdev_triggering(cdev);
case TRIGGER_BLKDEV:
return my_offload_blkdev_triggering(cdev);
default:
return -EOPNOTSUPP;
}
If we want to avoid exporting the symbol I would rather compare
!strcmp(cdev->trigger->name, "netdev")
What do you think?