--- a/drivers/leds/trigger/ledtrig-netdev.c 2024-10-23 12:18:22.727984995 +1100 +++ b/drivers/leds/trigger/ledtrig-netdev.c 2024-10-23 12:40:17.985584090 +1100 @@ -49,6 +49,7 @@ char device_name[IFNAMSIZ]; atomic_t interval; + int invert; unsigned int last_activity; unsigned long mode; @@ -75,9 +76,9 @@ led_cdev->blink_brightness = led_cdev->max_brightness; if (!trigger_data->carrier_link_up) { - led_set_brightness(led_cdev, LED_OFF); + led_set_brightness(led_cdev, trigger_data->invert ? led_cdev->blink_brightness : LED_OFF); } else { - if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) + if (trigger_data->invert ^ test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) led_set_brightness(led_cdev, led_cdev->blink_brightness); else @@ -126,6 +127,9 @@ struct led_classdev *led_cdev = trigger_data->led_cdev; int ret; + if (trigger_data->invert) + return false; + if (!supports_hw_control(led_cdev)) return false; @@ -335,12 +339,40 @@ static DEVICE_ATTR_RW(interval); +static ssize_t invert_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_netdev_data *netdev_data = led_trigger_get_drvdata(dev); + + return sprintf(buf, "%u\n", netdev_data->invert); +} + +static ssize_t invert_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct led_netdev_data *netdev_data = led_trigger_get_drvdata(dev); + unsigned long state; + int ret; + + ret = kstrtoul(buf, 0, &state); + if (ret) + return ret; + + netdev_data->invert = !!state; + + return size; +} + +static DEVICE_ATTR_RW(invert); + static struct attribute *netdev_trig_attrs[] = { &dev_attr_device_name.attr, &dev_attr_link.attr, &dev_attr_rx.attr, &dev_attr_tx.attr, &dev_attr_interval.attr, + &dev_attr_invert.attr, NULL }; ATTRIBUTE_GROUPS(netdev_trig); @@ -406,9 +438,9 @@ unsigned long interval; int invert; - /* If we dont have a device, insure we are off */ + /* If we don't have a device, ensure we are in the baseline state */ if (!trigger_data->net_dev) { - led_set_brightness(trigger_data->led_cdev, LED_OFF); + set_baseline_state(trigger_data); return; } @@ -427,7 +459,7 @@ 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 = trigger_data->invert ^ test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); interval = jiffies_to_msecs( atomic_read(&trigger_data->interval)); /* base state is ON (link present) */