[3/3] leds: trigger: netdev: add additional mode for unified tx/rx traffic

Message ID 20230609135103.14221-4-ansuelsmth@gmail.com
State New
Headers
Series leds: trigger: netdev: add additional modes |

Commit Message

Christian Marangi June 9, 2023, 1:51 p.m. UTC
  Add additional mode for unified tx/rx traffic. LED will blink on both tx
or rx traffic.

This is especially useful for PHY and Switch that supports LEDs hw
control that doesn't support split tx/rx traffic but supports blinking
on any kind of traffic in the link.

On mode set from sysfs we check if we have enabled split tx/rx mode and
reject enabling activity mode to prevent wrong and redundant
configuration.

Add additional modes:
- activity: Blink LED on both tx or rx traffic

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 drivers/leds/trigger/ledtrig-netdev.c | 21 +++++++++++++++++----
 include/linux/leds.h                  |  1 +
 2 files changed, 18 insertions(+), 4 deletions(-)
  

Comments

Andrew Lunn June 9, 2023, 2:36 p.m. UTC | #1
On Fri, Jun 09, 2023 at 03:51:03PM +0200, Christian Marangi wrote:
> Add additional mode for unified tx/rx traffic. LED will blink on both tx
> or rx traffic.
> 
> This is especially useful for PHY and Switch that supports LEDs hw
> control that doesn't support split tx/rx traffic but supports blinking
> on any kind of traffic in the link.
> 
> On mode set from sysfs we check if we have enabled split tx/rx mode and
> reject enabling activity mode to prevent wrong and redundant
> configuration.

TRIGGER_NETDEV_TX + TRIGGER_NETDEV_RX = TRIGGER_NETDEV_ACTIVITY:

When calling into the driver, it probably makes the drivers simpler if
you do this simplification. Within the trigger code, keep them
separate, because that is what the user has configured.

I know such a simplification will make the marvell PHY driver simpler.

	Andrew
  

Patch

diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index 3c1571b620e4..709371b2115f 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -117,7 +117,8 @@  static void set_baseline_state(struct led_netdev_data *trigger_data)
 		 * checking stats
 		 */
 		if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ||
-		    test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode))
+		    test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ||
+		    test_bit(TRIGGER_NETDEV_ACTIVITY, &trigger_data->mode))
 			schedule_delayed_work(&trigger_data->work, 0);
 	}
 }
@@ -285,6 +286,7 @@  static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
 	case TRIGGER_NETDEV_FULL_DUPLEX:
 	case TRIGGER_NETDEV_TX:
 	case TRIGGER_NETDEV_RX:
+	case TRIGGER_NETDEV_ACTIVITY:
 		bit = attr;
 		break;
 	default:
@@ -315,6 +317,7 @@  static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
 	case TRIGGER_NETDEV_FULL_DUPLEX:
 	case TRIGGER_NETDEV_TX:
 	case TRIGGER_NETDEV_RX:
+	case TRIGGER_NETDEV_ACTIVITY:
 		bit = attr;
 		break;
 	default:
@@ -332,6 +335,11 @@  static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
 	     test_bit(TRIGGER_NETDEV_LINK_1000, &mode)))
 		return -EINVAL;
 
+	if (test_bit(TRIGGER_NETDEV_ACTIVITY, &mode) &&
+	    (test_bit(TRIGGER_NETDEV_TX, &mode) ||
+	     test_bit(TRIGGER_NETDEV_RX, &mode)))
+		return -EINVAL;
+
 	cancel_delayed_work_sync(&trigger_data->work);
 
 	trigger_data->mode = mode;
@@ -363,6 +371,7 @@  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);
+DEFINE_NETDEV_TRIGGER(activity, TRIGGER_NETDEV_ACTIVITY);
 
 static ssize_t interval_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
@@ -411,6 +420,7 @@  static struct attribute *netdev_trig_attrs[] = {
 	&dev_attr_half_duplex.attr,
 	&dev_attr_rx.attr,
 	&dev_attr_tx.attr,
+	&dev_attr_activity.attr,
 	&dev_attr_interval.attr,
 	NULL
 };
@@ -502,14 +512,17 @@  static void netdev_trig_work(struct work_struct *work)
 
 	/* If we are not looking for RX/TX then return  */
 	if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) &&
-	    !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode))
+	    !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) &&
+	    !test_bit(TRIGGER_NETDEV_ACTIVITY, &trigger_data->mode))
 		return;
 
 	dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
 	new_activity =
-	    (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ?
+	    (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ||
+	     test_bit(TRIGGER_NETDEV_ACTIVITY, &trigger_data->mode) ?
 		dev_stats->tx_packets : 0) +
-	    (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ?
+	    (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ||
+	     test_bit(TRIGGER_NETDEV_ACTIVITY, &trigger_data->mode) ?
 		dev_stats->rx_packets : 0);
 
 	if (trigger_data->last_activity != new_activity) {
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 7d428100b42b..f11fa5e1e833 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -589,6 +589,7 @@  enum led_trigger_netdev_modes {
 	TRIGGER_NETDEV_FULL_DUPLEX,
 	TRIGGER_NETDEV_TX,
 	TRIGGER_NETDEV_RX,
+	TRIGGER_NETDEV_ACTIVITY,
 
 	/* Keep last */
 	__TRIGGER_NETDEV_MAX,