linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH leds + devicetree v1 0/2] Parse DT property `trigger-sources` for netdev LED trigger
@ 2020-09-14 23:41 Marek Behún
  2020-09-14 23:41 ` [PATCH leds + devicetree v1 1/2] leds: trigger: add DT `trigger-sources` validating method Marek Behún
  2020-09-14 23:41 ` [PATCH leds + devicetree v1 2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree Marek Behún
  0 siblings, 2 replies; 4+ messages in thread
From: Marek Behún @ 2020-09-14 23:41 UTC (permalink / raw)
  To: linux-leds
  Cc: Pavel Machek, Dan Murphy, Ondřej Jirman, Russell King,
	Andrew Lunn, linux-kernel, Matthias Schiffer, Marek Behún

Hi,

the `trigger-sources` LED DT property is currently only implemented
for ledtrig-usbport.

Lets implement it for the netdev LED trigger.

In this proposal the specific netdev LED trigger mode is determined
from the `function` LED DT property.

Example:
  eth0: ethernet@30000 {
    compatible = "xyz";
    #trigger-source-cells = <0>;
  };

  led {
    color = <LED_COLOR_ID_GREEN>;
    function = LED_FUNCTION_LINK;
    trigger-sources = <&eth0>;
  };

When led is registered, the netdev trigger is automatically activated
and set to light the LED on if eth0 is linked.

Please let me know if this binding is OK, or if the binding should
instead of the `function` property determine the trigger settings from
arguments of the `trigger-sources` property :
  led {
    color = <LED_COLOR_ID_GREEN>;
    trigger-sources = <&eth0 (NETDEV_ATTR_LINK | NETDEV_ATTR_RX)>;
  };

I prefer the first binding, since we already have the `function`
property. Multiple modes can be achieved by string array, but this is
not yet implemented:
  led {
    color = <LED_COLOR_ID_GREEN>;
    function = LED_FUNCTION_LINK, LED_FUNCTION_ACTIVITY;
    trigger-sources = <&eth0>;
  };

Marek

Marek Behún (2):
  leds: trigger: add DT `trigger-source` validating method
  leds: trigger: netdev: allow parsing `trigger-sources` from device
    tree

 drivers/leds/led-triggers.c           | 26 +++++---
 drivers/leds/trigger/ledtrig-netdev.c | 91 ++++++++++++++++++++++++++-
 include/dt-bindings/leds/common.h     |  1 +
 include/linux/leds.h                  |  6 ++
 4 files changed, 115 insertions(+), 9 deletions(-)

-- 
2.26.2


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

* [PATCH leds + devicetree v1 1/2] leds: trigger: add DT `trigger-sources` validating method
  2020-09-14 23:41 [PATCH leds + devicetree v1 0/2] Parse DT property `trigger-sources` for netdev LED trigger Marek Behún
@ 2020-09-14 23:41 ` Marek Behún
  2020-09-14 23:41 ` [PATCH leds + devicetree v1 2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree Marek Behún
  1 sibling, 0 replies; 4+ messages in thread
From: Marek Behún @ 2020-09-14 23:41 UTC (permalink / raw)
  To: linux-leds
  Cc: Pavel Machek, Dan Murphy, Ondřej Jirman, Russell King,
	Andrew Lunn, linux-kernel, Matthias Schiffer, Marek Behún,
	Rob Herring, devicetree

Currently we use the `linux,default-trigger` device tree property of a
LED to define the default trigger which should be activated for a LED.

But the LED device tree binding also documents the `trigger-sources`
property, which specifies the source device which should be triggering
the LED.

The `trigger-sources` property is currently implemented only in
drivers/usb/core/ledtrig-usbport.c.

Lets add a method to struct led_trigger which, if implemented, can check
whether this trigger should be enabled as default. This check shall be
done by checking whether the specified `trigger-sources` refers to a
device compatible with the trigger.

Signed-off-by: Marek Behún <marek.behun@nic.cz>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
---
 drivers/leds/led-triggers.c | 26 ++++++++++++++++++--------
 include/linux/leds.h        |  6 ++++++
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 91da90cfb11d9..c96577f0bfe97 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -243,18 +243,30 @@ void led_trigger_remove(struct led_classdev *led_cdev)
 }
 EXPORT_SYMBOL_GPL(led_trigger_remove);
 
+static bool trigger_is_default(struct led_classdev *led_cdev,
+			       struct led_trigger *trig)
+{
+	if (!trigger_relevant(led_cdev, trig))
+		return false;
+
+	if (led_cdev->default_trigger &&
+	    !strcmp(led_cdev->default_trigger, trig->name))
+		return true;
+
+	if (trig->has_valid_source && trig->has_valid_source(led_cdev))
+		return true;
+
+	return false;
+}
+
 void led_trigger_set_default(struct led_classdev *led_cdev)
 {
 	struct led_trigger *trig;
 
-	if (!led_cdev->default_trigger)
-		return;
-
 	down_read(&triggers_list_lock);
 	down_write(&led_cdev->trigger_lock);
 	list_for_each_entry(trig, &trigger_list, next_trig) {
-		if (!strcmp(led_cdev->default_trigger, trig->name) &&
-		    trigger_relevant(led_cdev, trig)) {
+		if (trigger_is_default(led_cdev, trig)) {
 			led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
 			led_trigger_set(led_cdev, trig);
 			break;
@@ -306,9 +318,7 @@ int led_trigger_register(struct led_trigger *trig)
 	down_read(&leds_list_lock);
 	list_for_each_entry(led_cdev, &leds_list, node) {
 		down_write(&led_cdev->trigger_lock);
-		if (!led_cdev->trigger && led_cdev->default_trigger &&
-		    !strcmp(led_cdev->default_trigger, trig->name) &&
-		    trigger_relevant(led_cdev, trig)) {
+		if (!led_cdev->trigger && trigger_is_default(led_cdev, trig)) {
 			led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
 			led_trigger_set(led_cdev, trig);
 		}
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 6a8d6409c993e..4cbb826e4bec4 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -352,6 +352,12 @@ struct led_trigger {
 	int		(*activate)(struct led_classdev *led_cdev);
 	void		(*deactivate)(struct led_classdev *led_cdev);
 
+	/*
+	 * Check whether LED has defined valid source for this trigger.
+	 * If yes, this trigger should be set as default trigger for LED.
+	 */
+	bool		(*has_valid_source)(struct led_classdev *led_cdev);
+
 	/* LED-private triggers have this set */
 	struct led_hw_trigger_type *trigger_type;
 
-- 
2.26.2


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

* [PATCH leds + devicetree v1 2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree
  2020-09-14 23:41 [PATCH leds + devicetree v1 0/2] Parse DT property `trigger-sources` for netdev LED trigger Marek Behún
  2020-09-14 23:41 ` [PATCH leds + devicetree v1 1/2] leds: trigger: add DT `trigger-sources` validating method Marek Behún
@ 2020-09-14 23:41 ` Marek Behún
  2020-09-15 11:04   ` kernel test robot
  1 sibling, 1 reply; 4+ messages in thread
From: Marek Behún @ 2020-09-14 23:41 UTC (permalink / raw)
  To: linux-leds
  Cc: Pavel Machek, Dan Murphy, Ondřej Jirman, Russell King,
	Andrew Lunn, linux-kernel, Matthias Schiffer, Marek Behún,
	Rob Herring, devicetree

Allow setting netdev LED trigger as default when given LED DT node has
the `trigger-sources` property pointing to a node corresponding to a
network device.

The specific netdev trigger mode is determined from the `function` LED
property.

Example:
  eth0: ethernet@30000 {
    compatible = "xyz";
    #trigger-source-cells = <0>;
  };

  led {
    color = <LED_COLOR_ID_GREEN>;
    function = LED_FUNCTION_LINK;
    trigger-sources = <&eth0>;
  };

Signed-off-by: Marek Behún <marek.behun@nic.cz>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
---
 drivers/leds/trigger/ledtrig-netdev.c | 91 ++++++++++++++++++++++++++-
 include/dt-bindings/leds/common.h     |  1 +
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index d5e774d830215..c6dce28dc52ed 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -20,6 +20,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/of_net.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include "../leds.h"
@@ -389,6 +390,81 @@ static void netdev_trig_work(struct work_struct *work)
 			(atomic_read(&trigger_data->interval)*2));
 }
 
+static bool netdev_trig_of_parse(struct led_classdev *led_cdev,
+				 struct led_netdev_data *trigger_data)
+{
+	struct of_phandle_args args;
+	struct net_device *netdev;
+	struct device_node *np;
+	const char *function;
+	unsigned long mode;
+	int count, err;
+
+	np = dev_of_node(led_cdev->dev);
+	if (!np)
+		return -EOPNOTSUPP;
+
+	count = of_count_phandle_with_args(np, "trigger-sources",
+					   "#trigger-source-cells");
+	if (count == -ENOENT) {
+		return false;
+	} else if (count < 0) {
+		dev_warn(led_cdev->dev,
+			 "Failed parsing trigger sources for %pOF!\n", np);
+		return false;
+	}
+
+	/* netdev trigger can have only one source */
+	if (count != 1)
+		return false;
+
+	err = of_parse_phandle_with_args(np, "trigger-sources",
+					 "#trigger-source-cells", 0, &args);
+	if (err)
+		return false;
+
+	netdev = of_find_net_device_by_node(args.np);
+	if (!netdev)
+		return false;
+
+	err = of_property_read_string(np, "function", &function);
+	if (err && err != -ENOENT) {
+		dev_warn(led_cdev->dev, "Failed parsing function for %pOF!\n",
+			 np);
+		return false;
+	} else if (err == -ENOENT) {
+		/* default function is link */
+		function = LED_FUNCTION_LINK;
+	}
+
+	mode = 0;
+	if (!strcmp(function, LED_FUNCTION_LINK)) {
+		set_bit(NETDEV_LED_LINK, &mode);
+	} else if (!strcmp(function, LED_FUNCTION_ACTIVITY)) {
+		set_bit(NETDEV_LED_TX, &mode);
+		set_bit(NETDEV_LED_RX, &mode);
+	} else if (!strcmp(function, LED_FUNCTION_RX)) {
+		set_bit(NETDEV_LED_RX, &mode);
+	} else if (!strcmp(function, LED_FUNCTION_TX)) {
+		set_bit(NETDEV_LED_TX, &mode);
+	} else {
+		dev_dbg(led_cdev->dev,
+			"Unsupported netdev trigger function for %pOF!\n", np);
+		return false;
+	}
+
+	if (trigger_data) {
+		dev_hold(netdev);
+		trigger_data->net_dev = netdev;
+		memcpy(trigger_data->device_name, netdev->name, IFNAMSIZ);
+		trigger_data->mode = mode;
+		if (netif_carrier_ok(netdev))
+			set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+	}
+
+	return true;
+}
+
 static int netdev_trig_activate(struct led_classdev *led_cdev)
 {
 	struct led_netdev_data *trigger_data;
@@ -414,10 +490,17 @@ static int netdev_trig_activate(struct led_classdev *led_cdev)
 	trigger_data->last_activity = 0;
 
 	led_set_trigger_data(led_cdev, trigger_data);
+	netdev_trig_of_parse(led_cdev, trigger_data);
 
 	rc = register_netdevice_notifier(&trigger_data->notifier);
-	if (rc)
+	if (rc) {
+		if (trigger_data->net_dev)
+			dev_put(trigger_data->net_dev);
 		kfree(trigger_data);
+	} else {
+		if (trigger_data->net_dev)
+			set_baseline_state(trigger_data);
+	}
 
 	return rc;
 }
@@ -436,10 +519,16 @@ static void netdev_trig_deactivate(struct led_classdev *led_cdev)
 	kfree(trigger_data);
 }
 
+static bool netdev_trig_has_valid_source(struct led_classdev *led_cdev)
+{
+	return netdev_trig_of_parse(led_cdev, NULL);
+}
+
 static struct led_trigger netdev_led_trigger = {
 	.name = "netdev",
 	.activate = netdev_trig_activate,
 	.deactivate = netdev_trig_deactivate,
+	.has_valid_source = netdev_trig_has_valid_source,
 	.groups = netdev_trig_groups,
 };
 
diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h
index 52b619d44ba25..c7f9d34d60206 100644
--- a/include/dt-bindings/leds/common.h
+++ b/include/dt-bindings/leds/common.h
@@ -77,6 +77,7 @@
 #define LED_FUNCTION_HEARTBEAT "heartbeat"
 #define LED_FUNCTION_INDICATOR "indicator"
 #define LED_FUNCTION_LAN "lan"
+#define LED_FUNCTION_LINK "link"
 #define LED_FUNCTION_MAIL "mail"
 #define LED_FUNCTION_MTD "mtd"
 #define LED_FUNCTION_PANIC "panic"
-- 
2.26.2


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

* Re: [PATCH leds + devicetree v1 2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree
  2020-09-14 23:41 ` [PATCH leds + devicetree v1 2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree Marek Behún
@ 2020-09-15 11:04   ` kernel test robot
  0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2020-09-15 11:04 UTC (permalink / raw)
  To: Marek Behún, linux-leds
  Cc: kbuild-all, clang-built-linux, Pavel Machek, Dan Murphy,
	Ondřej Jirman, Russell King, Andrew Lunn, linux-kernel,
	Matthias Schiffer, Marek Behún, Rob Herring

[-- Attachment #1: Type: text/plain, Size: 5695 bytes --]

Hi "Marek,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on pavel-linux-leds/for-next]
[also build test ERROR on robh/for-next linus/master v5.9-rc5 next-20200915]
[cannot apply to linux/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Marek-Beh-n/Parse-DT-property-trigger-sources-for-netdev-LED-trigger/20200915-074253
base:   git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds.git for-next
config: x86_64-randconfig-a016-20200914 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 3ed89b51da38f081fedb57727076262abb81d149)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/leds/trigger/ledtrig-netdev.c:396:25: error: variable has incomplete type 'struct of_phandle_args'
           struct of_phandle_args args;
                                  ^
   drivers/leds/trigger/ledtrig-netdev.c:396:9: note: forward declaration of 'struct of_phandle_args'
           struct of_phandle_args args;
                  ^
>> drivers/leds/trigger/ledtrig-netdev.c:407:10: error: implicit declaration of function 'of_count_phandle_with_args' [-Werror,-Wimplicit-function-declaration]
           count = of_count_phandle_with_args(np, "trigger-sources",
                   ^
>> drivers/leds/trigger/ledtrig-netdev.c:421:8: error: implicit declaration of function 'of_parse_phandle_with_args' [-Werror,-Wimplicit-function-declaration]
           err = of_parse_phandle_with_args(np, "trigger-sources",
                 ^
   drivers/leds/trigger/ledtrig-netdev.c:421:8: note: did you mean 'of_count_phandle_with_args'?
   drivers/leds/trigger/ledtrig-netdev.c:407:10: note: 'of_count_phandle_with_args' declared here
           count = of_count_phandle_with_args(np, "trigger-sources",
                   ^
>> drivers/leds/trigger/ledtrig-netdev.c:430:8: error: implicit declaration of function 'of_property_read_string' [-Werror,-Wimplicit-function-declaration]
           err = of_property_read_string(np, "function", &function);
                 ^
   4 errors generated.

# https://github.com/0day-ci/linux/commit/2055fc3b24bb72ea2569a866ccfb1ee840e0d385
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Marek-Beh-n/Parse-DT-property-trigger-sources-for-netdev-LED-trigger/20200915-074253
git checkout 2055fc3b24bb72ea2569a866ccfb1ee840e0d385
vim +396 drivers/leds/trigger/ledtrig-netdev.c

   392	
   393	static bool netdev_trig_of_parse(struct led_classdev *led_cdev,
   394					 struct led_netdev_data *trigger_data)
   395	{
 > 396		struct of_phandle_args args;
   397		struct net_device *netdev;
   398		struct device_node *np;
   399		const char *function;
   400		unsigned long mode;
   401		int count, err;
   402	
   403		np = dev_of_node(led_cdev->dev);
   404		if (!np)
   405			return -EOPNOTSUPP;
   406	
 > 407		count = of_count_phandle_with_args(np, "trigger-sources",
   408						   "#trigger-source-cells");
   409		if (count == -ENOENT) {
   410			return false;
   411		} else if (count < 0) {
   412			dev_warn(led_cdev->dev,
   413				 "Failed parsing trigger sources for %pOF!\n", np);
   414			return false;
   415		}
   416	
   417		/* netdev trigger can have only one source */
   418		if (count != 1)
   419			return false;
   420	
 > 421		err = of_parse_phandle_with_args(np, "trigger-sources",
   422						 "#trigger-source-cells", 0, &args);
   423		if (err)
   424			return false;
   425	
   426		netdev = of_find_net_device_by_node(args.np);
   427		if (!netdev)
   428			return false;
   429	
 > 430		err = of_property_read_string(np, "function", &function);
   431		if (err && err != -ENOENT) {
   432			dev_warn(led_cdev->dev, "Failed parsing function for %pOF!\n",
   433				 np);
   434			return false;
   435		} else if (err == -ENOENT) {
   436			/* default function is link */
   437			function = LED_FUNCTION_LINK;
   438		}
   439	
   440		mode = 0;
   441		if (!strcmp(function, LED_FUNCTION_LINK)) {
   442			set_bit(NETDEV_LED_LINK, &mode);
   443		} else if (!strcmp(function, LED_FUNCTION_ACTIVITY)) {
   444			set_bit(NETDEV_LED_TX, &mode);
   445			set_bit(NETDEV_LED_RX, &mode);
   446		} else if (!strcmp(function, LED_FUNCTION_RX)) {
   447			set_bit(NETDEV_LED_RX, &mode);
   448		} else if (!strcmp(function, LED_FUNCTION_TX)) {
   449			set_bit(NETDEV_LED_TX, &mode);
   450		} else {
   451			dev_dbg(led_cdev->dev,
   452				"Unsupported netdev trigger function for %pOF!\n", np);
   453			return false;
   454		}
   455	
   456		if (trigger_data) {
   457			dev_hold(netdev);
   458			trigger_data->net_dev = netdev;
   459			memcpy(trigger_data->device_name, netdev->name, IFNAMSIZ);
   460			trigger_data->mode = mode;
   461			if (netif_carrier_ok(netdev))
   462				set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
   463		}
   464	
   465		return true;
   466	}
   467	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37437 bytes --]

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

end of thread, other threads:[~2020-09-15 11:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-14 23:41 [PATCH leds + devicetree v1 0/2] Parse DT property `trigger-sources` for netdev LED trigger Marek Behún
2020-09-14 23:41 ` [PATCH leds + devicetree v1 1/2] leds: trigger: add DT `trigger-sources` validating method Marek Behún
2020-09-14 23:41 ` [PATCH leds + devicetree v1 2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree Marek Behún
2020-09-15 11:04   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).