generic: 6.1: backport LEDs patch adding additional modes
Backport LEDs patch adding additional modes for split link speed and half/full duplex state. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
		| @@ -0,0 +1,242 @@ | |||||||
|  | From d5e01266e7f5fa12400d4c8aa4e86fe89dcc61e9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Christian Marangi <ansuelsmth@gmail.com> | ||||||
|  | Date: Mon, 19 Jun 2023 22:46:58 +0200 | ||||||
|  | Subject: [PATCH 1/3] leds: trigger: netdev: add additional specific link speed | ||||||
|  |  mode | ||||||
|  |  | ||||||
|  | Add additional modes for specific link speed. Use ethtool APIs to get the | ||||||
|  | current link speed and enable the LED accordingly. Under netdev event | ||||||
|  | handler the rtnl lock is already held and is not needed to be set to | ||||||
|  | access ethtool APIs. | ||||||
|  |  | ||||||
|  | This is especially useful for PHY and Switch that supports LEDs hw | ||||||
|  | control for specific link speed. (example scenario a PHY that have 2 LED | ||||||
|  | connected one green and one orange where the green is turned on with | ||||||
|  | 1000mbps speed and orange is turned on with 10mpbs speed) | ||||||
|  |  | ||||||
|  | On mode set from sysfs we check if we have enabled split link speed mode | ||||||
|  | and reject enabling generic link mode to prevent wrong and redundant | ||||||
|  | configuration. | ||||||
|  |  | ||||||
|  | Rework logic on the set baseline state to support these new modes to | ||||||
|  | select if we need to turn on or off the LED. | ||||||
|  |  | ||||||
|  | Add additional modes: | ||||||
|  | - link_10: Turn on LED when link speed is 10mbps | ||||||
|  | - link_100: Turn on LED when link speed is 100mbps | ||||||
|  | - link_1000: Turn on LED when link speed is 1000mbps | ||||||
|  |  | ||||||
|  | Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> | ||||||
|  | Reviewed-by: Andrew Lunn <andrew@lunn.ch> | ||||||
|  | Acked-by: Lee Jones <lee@kernel.org> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/leds/trigger/ledtrig-netdev.c | 80 +++++++++++++++++++++++---- | ||||||
|  |  include/linux/leds.h                  |  3 + | ||||||
|  |  2 files changed, 73 insertions(+), 10 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/leds/trigger/ledtrig-netdev.c | ||||||
|  | +++ b/drivers/leds/trigger/ledtrig-netdev.c | ||||||
|  | @@ -13,6 +13,7 @@ | ||||||
|  |  #include <linux/atomic.h> | ||||||
|  |  #include <linux/ctype.h> | ||||||
|  |  #include <linux/device.h> | ||||||
|  | +#include <linux/ethtool.h> | ||||||
|  |  #include <linux/init.h> | ||||||
|  |  #include <linux/jiffies.h> | ||||||
|  |  #include <linux/kernel.h> | ||||||
|  | @@ -21,6 +22,7 @@ | ||||||
|  |  #include <linux/module.h> | ||||||
|  |  #include <linux/netdevice.h> | ||||||
|  |  #include <linux/mutex.h> | ||||||
|  | +#include <linux/rtnetlink.h> | ||||||
|  |  #include <linux/timer.h> | ||||||
|  |  #include "../leds.h" | ||||||
|  |   | ||||||
|  | @@ -52,6 +54,8 @@ struct led_netdev_data { | ||||||
|  |  	unsigned int last_activity; | ||||||
|  |   | ||||||
|  |  	unsigned long mode; | ||||||
|  | +	int link_speed; | ||||||
|  | + | ||||||
|  |  	bool carrier_link_up; | ||||||
|  |  	bool hw_control; | ||||||
|  |  }; | ||||||
|  | @@ -77,7 +81,24 @@ static void set_baseline_state(struct le | ||||||
|  |  	if (!trigger_data->carrier_link_up) { | ||||||
|  |  		led_set_brightness(led_cdev, LED_OFF); | ||||||
|  |  	} else { | ||||||
|  | +		bool blink_on = false; | ||||||
|  | + | ||||||
|  |  		if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) | ||||||
|  | +			blink_on = true; | ||||||
|  | + | ||||||
|  | +		if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) && | ||||||
|  | +		    trigger_data->link_speed == SPEED_10) | ||||||
|  | +			blink_on = true; | ||||||
|  | + | ||||||
|  | +		if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) && | ||||||
|  | +		    trigger_data->link_speed == SPEED_100) | ||||||
|  | +			blink_on = true; | ||||||
|  | + | ||||||
|  | +		if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && | ||||||
|  | +		    trigger_data->link_speed == SPEED_1000) | ||||||
|  | +			blink_on = true; | ||||||
|  | + | ||||||
|  | +		if (blink_on) | ||||||
|  |  			led_set_brightness(led_cdev, | ||||||
|  |  					   led_cdev->blink_brightness); | ||||||
|  |  		else | ||||||
|  | @@ -161,6 +182,18 @@ static bool can_hw_control(struct led_ne | ||||||
|  |  	return true; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void get_device_state(struct led_netdev_data *trigger_data) | ||||||
|  | +{ | ||||||
|  | +	struct ethtool_link_ksettings cmd; | ||||||
|  | + | ||||||
|  | +	trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); | ||||||
|  | +	if (!trigger_data->carrier_link_up) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) | ||||||
|  | +		trigger_data->link_speed = cmd.base.speed; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static ssize_t device_name_show(struct device *dev, | ||||||
|  |  				struct device_attribute *attr, char *buf) | ||||||
|  |  { | ||||||
|  | @@ -196,8 +229,12 @@ static int set_device_name(struct led_ne | ||||||
|  |  		    dev_get_by_name(&init_net, trigger_data->device_name); | ||||||
|  |   | ||||||
|  |  	trigger_data->carrier_link_up = false; | ||||||
|  | -	if (trigger_data->net_dev != NULL) | ||||||
|  | -		trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); | ||||||
|  | +	trigger_data->link_speed = SPEED_UNKNOWN; | ||||||
|  | +	if (trigger_data->net_dev != NULL) { | ||||||
|  | +		rtnl_lock(); | ||||||
|  | +		get_device_state(trigger_data); | ||||||
|  | +		rtnl_unlock(); | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	trigger_data->last_activity = 0; | ||||||
|  |   | ||||||
|  | @@ -234,6 +271,9 @@ static ssize_t netdev_led_attr_show(stru | ||||||
|  |   | ||||||
|  |  	switch (attr) { | ||||||
|  |  	case TRIGGER_NETDEV_LINK: | ||||||
|  | +	case TRIGGER_NETDEV_LINK_10: | ||||||
|  | +	case TRIGGER_NETDEV_LINK_100: | ||||||
|  | +	case TRIGGER_NETDEV_LINK_1000: | ||||||
|  |  	case TRIGGER_NETDEV_TX: | ||||||
|  |  	case TRIGGER_NETDEV_RX: | ||||||
|  |  		bit = attr; | ||||||
|  | @@ -249,7 +289,7 @@ static ssize_t netdev_led_attr_store(str | ||||||
|  |  				     size_t size, enum led_trigger_netdev_modes attr) | ||||||
|  |  { | ||||||
|  |  	struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); | ||||||
|  | -	unsigned long state; | ||||||
|  | +	unsigned long state, mode = trigger_data->mode; | ||||||
|  |  	int ret; | ||||||
|  |  	int bit; | ||||||
|  |   | ||||||
|  | @@ -259,6 +299,9 @@ static ssize_t netdev_led_attr_store(str | ||||||
|  |   | ||||||
|  |  	switch (attr) { | ||||||
|  |  	case TRIGGER_NETDEV_LINK: | ||||||
|  | +	case TRIGGER_NETDEV_LINK_10: | ||||||
|  | +	case TRIGGER_NETDEV_LINK_100: | ||||||
|  | +	case TRIGGER_NETDEV_LINK_1000: | ||||||
|  |  	case TRIGGER_NETDEV_TX: | ||||||
|  |  	case TRIGGER_NETDEV_RX: | ||||||
|  |  		bit = attr; | ||||||
|  | @@ -267,13 +310,20 @@ static ssize_t netdev_led_attr_store(str | ||||||
|  |  		return -EINVAL; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	cancel_delayed_work_sync(&trigger_data->work); | ||||||
|  | - | ||||||
|  |  	if (state) | ||||||
|  | -		set_bit(bit, &trigger_data->mode); | ||||||
|  | +		set_bit(bit, &mode); | ||||||
|  |  	else | ||||||
|  | -		clear_bit(bit, &trigger_data->mode); | ||||||
|  | +		clear_bit(bit, &mode); | ||||||
|  | + | ||||||
|  | +	if (test_bit(TRIGGER_NETDEV_LINK, &mode) && | ||||||
|  | +	    (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || | ||||||
|  | +	     test_bit(TRIGGER_NETDEV_LINK_100, &mode) || | ||||||
|  | +	     test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	cancel_delayed_work_sync(&trigger_data->work); | ||||||
|  |   | ||||||
|  | +	trigger_data->mode = mode; | ||||||
|  |  	trigger_data->hw_control = can_hw_control(trigger_data); | ||||||
|  |   | ||||||
|  |  	set_baseline_state(trigger_data); | ||||||
|  | @@ -295,6 +345,9 @@ static ssize_t netdev_led_attr_store(str | ||||||
|  |  	static DEVICE_ATTR_RW(trigger_name) | ||||||
|  |   | ||||||
|  |  DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); | ||||||
|  | +DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); | ||||||
|  | +DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); | ||||||
|  | +DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); | ||||||
|  |  DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); | ||||||
|  |  DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); | ||||||
|  |   | ||||||
|  | @@ -338,6 +391,9 @@ static DEVICE_ATTR_RW(interval); | ||||||
|  |  static struct attribute *netdev_trig_attrs[] = { | ||||||
|  |  	&dev_attr_device_name.attr, | ||||||
|  |  	&dev_attr_link.attr, | ||||||
|  | +	&dev_attr_link_10.attr, | ||||||
|  | +	&dev_attr_link_100.attr, | ||||||
|  | +	&dev_attr_link_1000.attr, | ||||||
|  |  	&dev_attr_rx.attr, | ||||||
|  |  	&dev_attr_tx.attr, | ||||||
|  |  	&dev_attr_interval.attr, | ||||||
|  | @@ -368,9 +424,10 @@ static int netdev_trig_notify(struct not | ||||||
|  |  	mutex_lock(&trigger_data->lock); | ||||||
|  |   | ||||||
|  |  	trigger_data->carrier_link_up = false; | ||||||
|  | +	trigger_data->link_speed = SPEED_UNKNOWN; | ||||||
|  |  	switch (evt) { | ||||||
|  |  	case NETDEV_CHANGENAME: | ||||||
|  | -		trigger_data->carrier_link_up = netif_carrier_ok(dev); | ||||||
|  | +		get_device_state(trigger_data); | ||||||
|  |  		fallthrough; | ||||||
|  |  	case NETDEV_REGISTER: | ||||||
|  |  		if (trigger_data->net_dev) | ||||||
|  | @@ -384,7 +441,7 @@ static int netdev_trig_notify(struct not | ||||||
|  |  		break; | ||||||
|  |  	case NETDEV_UP: | ||||||
|  |  	case NETDEV_CHANGE: | ||||||
|  | -		trigger_data->carrier_link_up = netif_carrier_ok(dev); | ||||||
|  | +		get_device_state(trigger_data); | ||||||
|  |  		break; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | @@ -427,7 +484,10 @@ static void netdev_trig_work(struct work | ||||||
|  |  	if (trigger_data->last_activity != new_activity) { | ||||||
|  |  		led_stop_software_blink(trigger_data->led_cdev); | ||||||
|  |   | ||||||
|  | -		invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); | ||||||
|  | +		invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || | ||||||
|  | +			 test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || | ||||||
|  | +			 test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || | ||||||
|  | +			 test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); | ||||||
|  |  		interval = jiffies_to_msecs( | ||||||
|  |  				atomic_read(&trigger_data->interval)); | ||||||
|  |  		/* base state is ON (link present) */ | ||||||
|  | --- a/include/linux/leds.h | ||||||
|  | +++ b/include/linux/leds.h | ||||||
|  | @@ -530,6 +530,9 @@ static inline void *led_get_trigger_data | ||||||
|  |  /* Trigger specific enum */ | ||||||
|  |  enum led_trigger_netdev_modes { | ||||||
|  |  	TRIGGER_NETDEV_LINK = 0, | ||||||
|  | +	TRIGGER_NETDEV_LINK_10, | ||||||
|  | +	TRIGGER_NETDEV_LINK_100, | ||||||
|  | +	TRIGGER_NETDEV_LINK_1000, | ||||||
|  |  	TRIGGER_NETDEV_TX, | ||||||
|  |  	TRIGGER_NETDEV_RX, | ||||||
|  |   | ||||||
| @@ -0,0 +1,138 @@ | |||||||
|  | From f22f95b9ff1551c9bab13104131929f33d51f23f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Christian Marangi <ansuelsmth@gmail.com> | ||||||
|  | Date: Mon, 19 Jun 2023 22:46:59 +0200 | ||||||
|  | Subject: [PATCH 2/3] leds: trigger: netdev: add additional specific link | ||||||
|  |  duplex mode | ||||||
|  |  | ||||||
|  | Add additional modes for specific link duplex. Use ethtool APIs to get the | ||||||
|  | current link duplex and enable the LED accordingly. Under netdev event | ||||||
|  | handler the rtnl lock is already held and is not needed to be set to | ||||||
|  | access ethtool APIs. | ||||||
|  |  | ||||||
|  | This is especially useful for PHY and Switch that supports LEDs hw | ||||||
|  | control for specific link duplex. | ||||||
|  |  | ||||||
|  | Add additional modes: | ||||||
|  | - half_duplex: Turn on LED when link is half duplex | ||||||
|  | - full_duplex: Turn on LED when link is full duplex | ||||||
|  |  | ||||||
|  | Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> | ||||||
|  | Reviewed-by: Andrew Lunn <andrew@lunn.ch> | ||||||
|  | Acked-by: Lee Jones <lee@kernel.org> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/leds/trigger/ledtrig-netdev.c | 27 +++++++++++++++++++++++++-- | ||||||
|  |  include/linux/leds.h                  |  2 ++ | ||||||
|  |  2 files changed, 27 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/leds/trigger/ledtrig-netdev.c | ||||||
|  | +++ b/drivers/leds/trigger/ledtrig-netdev.c | ||||||
|  | @@ -55,6 +55,7 @@ struct led_netdev_data { | ||||||
|  |   | ||||||
|  |  	unsigned long mode; | ||||||
|  |  	int link_speed; | ||||||
|  | +	u8 duplex; | ||||||
|  |   | ||||||
|  |  	bool carrier_link_up; | ||||||
|  |  	bool hw_control; | ||||||
|  | @@ -98,6 +99,14 @@ static void set_baseline_state(struct le | ||||||
|  |  		    trigger_data->link_speed == SPEED_1000) | ||||||
|  |  			blink_on = true; | ||||||
|  |   | ||||||
|  | +		if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && | ||||||
|  | +		    trigger_data->duplex == DUPLEX_HALF) | ||||||
|  | +			blink_on = true; | ||||||
|  | + | ||||||
|  | +		if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && | ||||||
|  | +		    trigger_data->duplex == DUPLEX_FULL) | ||||||
|  | +			blink_on = true; | ||||||
|  | + | ||||||
|  |  		if (blink_on) | ||||||
|  |  			led_set_brightness(led_cdev, | ||||||
|  |  					   led_cdev->blink_brightness); | ||||||
|  | @@ -190,8 +199,10 @@ static void get_device_state(struct led_ | ||||||
|  |  	if (!trigger_data->carrier_link_up) | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  | -	if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) | ||||||
|  | +	if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { | ||||||
|  |  		trigger_data->link_speed = cmd.base.speed; | ||||||
|  | +		trigger_data->duplex = cmd.base.duplex; | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static ssize_t device_name_show(struct device *dev, | ||||||
|  | @@ -230,6 +241,7 @@ static int set_device_name(struct led_ne | ||||||
|  |   | ||||||
|  |  	trigger_data->carrier_link_up = false; | ||||||
|  |  	trigger_data->link_speed = SPEED_UNKNOWN; | ||||||
|  | +	trigger_data->duplex = DUPLEX_UNKNOWN; | ||||||
|  |  	if (trigger_data->net_dev != NULL) { | ||||||
|  |  		rtnl_lock(); | ||||||
|  |  		get_device_state(trigger_data); | ||||||
|  | @@ -274,6 +286,8 @@ static ssize_t netdev_led_attr_show(stru | ||||||
|  |  	case TRIGGER_NETDEV_LINK_10: | ||||||
|  |  	case TRIGGER_NETDEV_LINK_100: | ||||||
|  |  	case TRIGGER_NETDEV_LINK_1000: | ||||||
|  | +	case TRIGGER_NETDEV_HALF_DUPLEX: | ||||||
|  | +	case TRIGGER_NETDEV_FULL_DUPLEX: | ||||||
|  |  	case TRIGGER_NETDEV_TX: | ||||||
|  |  	case TRIGGER_NETDEV_RX: | ||||||
|  |  		bit = attr; | ||||||
|  | @@ -302,6 +316,8 @@ static ssize_t netdev_led_attr_store(str | ||||||
|  |  	case TRIGGER_NETDEV_LINK_10: | ||||||
|  |  	case TRIGGER_NETDEV_LINK_100: | ||||||
|  |  	case TRIGGER_NETDEV_LINK_1000: | ||||||
|  | +	case TRIGGER_NETDEV_HALF_DUPLEX: | ||||||
|  | +	case TRIGGER_NETDEV_FULL_DUPLEX: | ||||||
|  |  	case TRIGGER_NETDEV_TX: | ||||||
|  |  	case TRIGGER_NETDEV_RX: | ||||||
|  |  		bit = attr; | ||||||
|  | @@ -348,6 +364,8 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD | ||||||
|  |  DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); | ||||||
|  |  DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); | ||||||
|  |  DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); | ||||||
|  | +DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); | ||||||
|  | +DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); | ||||||
|  |  DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); | ||||||
|  |  DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); | ||||||
|  |   | ||||||
|  | @@ -394,6 +412,8 @@ static struct attribute *netdev_trig_att | ||||||
|  |  	&dev_attr_link_10.attr, | ||||||
|  |  	&dev_attr_link_100.attr, | ||||||
|  |  	&dev_attr_link_1000.attr, | ||||||
|  | +	&dev_attr_full_duplex.attr, | ||||||
|  | +	&dev_attr_half_duplex.attr, | ||||||
|  |  	&dev_attr_rx.attr, | ||||||
|  |  	&dev_attr_tx.attr, | ||||||
|  |  	&dev_attr_interval.attr, | ||||||
|  | @@ -425,6 +445,7 @@ static int netdev_trig_notify(struct not | ||||||
|  |   | ||||||
|  |  	trigger_data->carrier_link_up = false; | ||||||
|  |  	trigger_data->link_speed = SPEED_UNKNOWN; | ||||||
|  | +	trigger_data->duplex = DUPLEX_UNKNOWN; | ||||||
|  |  	switch (evt) { | ||||||
|  |  	case NETDEV_CHANGENAME: | ||||||
|  |  		get_device_state(trigger_data); | ||||||
|  | @@ -487,7 +508,9 @@ static void netdev_trig_work(struct work | ||||||
|  |  		invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || | ||||||
|  |  			 test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || | ||||||
|  |  			 test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || | ||||||
|  | -			 test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); | ||||||
|  | +			 test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || | ||||||
|  | +			 test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || | ||||||
|  | +			 test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); | ||||||
|  |  		interval = jiffies_to_msecs( | ||||||
|  |  				atomic_read(&trigger_data->interval)); | ||||||
|  |  		/* base state is ON (link present) */ | ||||||
|  | --- a/include/linux/leds.h | ||||||
|  | +++ b/include/linux/leds.h | ||||||
|  | @@ -533,6 +533,8 @@ enum led_trigger_netdev_modes { | ||||||
|  |  	TRIGGER_NETDEV_LINK_10, | ||||||
|  |  	TRIGGER_NETDEV_LINK_100, | ||||||
|  |  	TRIGGER_NETDEV_LINK_1000, | ||||||
|  | +	TRIGGER_NETDEV_HALF_DUPLEX, | ||||||
|  | +	TRIGGER_NETDEV_FULL_DUPLEX, | ||||||
|  |  	TRIGGER_NETDEV_TX, | ||||||
|  |  	TRIGGER_NETDEV_RX, | ||||||
|  |   | ||||||
| @@ -0,0 +1,45 @@ | |||||||
|  | From b655892ffd6d89b0c7407e099c40dbde82ee3f03 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Christian Marangi <ansuelsmth@gmail.com> | ||||||
|  | Date: Mon, 19 Jun 2023 22:47:00 +0200 | ||||||
|  | Subject: [PATCH 3/3] leds: trigger: netdev: expose hw_control status via sysfs | ||||||
|  |  | ||||||
|  | Expose hw_control status via sysfs for the netdev trigger to give | ||||||
|  | userspace better understanding of the current state of the trigger and | ||||||
|  | the LED. | ||||||
|  |  | ||||||
|  | Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> | ||||||
|  | Reviewed-by: Andrew Lunn <andrew@lunn.ch> | ||||||
|  | Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com> | ||||||
|  | Acked-by: Lee Jones <lee@kernel.org> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++++++ | ||||||
|  |  1 file changed, 11 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/leds/trigger/ledtrig-netdev.c | ||||||
|  | +++ b/drivers/leds/trigger/ledtrig-netdev.c | ||||||
|  | @@ -406,6 +406,16 @@ static ssize_t interval_store(struct dev | ||||||
|  |   | ||||||
|  |  static DEVICE_ATTR_RW(interval); | ||||||
|  |   | ||||||
|  | +static ssize_t hw_control_show(struct device *dev, | ||||||
|  | +			       struct device_attribute *attr, char *buf) | ||||||
|  | +{ | ||||||
|  | +	struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); | ||||||
|  | + | ||||||
|  | +	return sprintf(buf, "%d\n", trigger_data->hw_control); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static DEVICE_ATTR_RO(hw_control); | ||||||
|  | + | ||||||
|  |  static struct attribute *netdev_trig_attrs[] = { | ||||||
|  |  	&dev_attr_device_name.attr, | ||||||
|  |  	&dev_attr_link.attr, | ||||||
|  | @@ -417,6 +427,7 @@ static struct attribute *netdev_trig_att | ||||||
|  |  	&dev_attr_rx.attr, | ||||||
|  |  	&dev_attr_tx.attr, | ||||||
|  |  	&dev_attr_interval.attr, | ||||||
|  | +	&dev_attr_hw_control.attr, | ||||||
|  |  	NULL | ||||||
|  |  }; | ||||||
|  |  ATTRIBUTE_GROUPS(netdev_trig); | ||||||
		Reference in New Issue
	
	Block a user
	 Christian Marangi
					Christian Marangi