diff mbox series

[leds,+,devicetree,v1,2/2] leds: trigger: netdev: allow parsing `trigger-sources` from device tree

Message ID 20200914234148.19837-3-marek.behun@nic.cz
State New
Headers show
Series None | expand

Commit Message

Marek BehĂșn Sept. 14, 2020, 11:41 p.m. UTC
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(-)

Comments

kernel test robot Sept. 15, 2020, 11:04 a.m. UTC | #1
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
diff mbox series

Patch

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"