Skip to content
Permalink
Browse files
leds: trigger: netdev: allow parsing trigger-sources from device tree
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
  • Loading branch information
elkablo authored and intel-lab-lkp committed Sep 14, 2020
1 parent b2db9d7 commit 2055fc3b24bb72ea2569a866ccfb1ee840e0d385
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 1 deletion.
@@ -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,
};

@@ -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"

0 comments on commit 2055fc3

Please sign in to comment.