1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright 2017 Ben Whitten <ben.whitten@gmail.com> 3 // Copyright 2007 Oliver Jowett <oliver@opencloud.com> 4 // 5 // LED Kernel Netdev Trigger 6 // 7 // Toggles the LED to reflect the link and traffic state of a named net device 8 // 9 // Derived from ledtrig-timer.c which is: 10 // Copyright 2005-2006 Openedhand Ltd. 11 // Author: Richard Purdie <rpurdie@openedhand.com> 12 13 #include <linux/atomic.h> 14 #include <linux/ctype.h> 15 #include <linux/device.h> 16 #include <linux/init.h> 17 #include <linux/jiffies.h> 18 #include <linux/kernel.h> 19 #include <linux/leds.h> 20 #include <linux/list.h> 21 #include <linux/module.h> 22 #include <linux/netdevice.h> 23 #include <linux/mutex.h> 24 #include <linux/timer.h> 25 #include "../leds.h" 26 27 #define NETDEV_LED_DEFAULT_INTERVAL 50 28 29 /* 30 * Configurable sysfs attributes: 31 * 32 * device_name - network device name to monitor 33 * interval - duration of LED blink, in milliseconds 34 * link - LED's normal state reflects whether the link is up 35 * (has carrier) or not 36 * tx - LED blinks on transmitted data 37 * rx - LED blinks on receive data 38 * 39 */ 40 41 struct led_netdev_data { 42 struct mutex lock; 43 44 struct delayed_work work; 45 struct notifier_block notifier; 46 47 struct led_classdev *led_cdev; 48 struct net_device *net_dev; 49 50 char device_name[IFNAMSIZ]; 51 atomic_t interval; 52 unsigned int last_activity; 53 54 unsigned long mode; 55 bool carrier_link_up; 56 bool hw_control; 57 }; 58 59 static void set_baseline_state(struct led_netdev_data *trigger_data) 60 { 61 int current_brightness; 62 struct led_classdev *led_cdev = trigger_data->led_cdev; 63 64 /* Already validated, hw control is possible with the requested mode */ 65 if (trigger_data->hw_control) { 66 led_cdev->hw_control_set(led_cdev, trigger_data->mode); 67 68 return; 69 } 70 71 current_brightness = led_cdev->brightness; 72 if (current_brightness) 73 led_cdev->blink_brightness = current_brightness; 74 if (!led_cdev->blink_brightness) 75 led_cdev->blink_brightness = led_cdev->max_brightness; 76 77 if (!trigger_data->carrier_link_up) { 78 led_set_brightness(led_cdev, LED_OFF); 79 } else { 80 if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) 81 led_set_brightness(led_cdev, 82 led_cdev->blink_brightness); 83 else 84 led_set_brightness(led_cdev, LED_OFF); 85 86 /* If we are looking for RX/TX start periodically 87 * checking stats 88 */ 89 if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || 90 test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) 91 schedule_delayed_work(&trigger_data->work, 0); 92 } 93 } 94 95 static bool supports_hw_control(struct led_classdev *led_cdev) 96 { 97 if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || 98 !led_cdev->hw_control_is_supported) 99 return false; 100 101 return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); 102 } 103 104 /* 105 * Validate the configured netdev is the same as the one associated with 106 * the LED driver in hw control. 107 */ 108 static bool validate_net_dev(struct led_classdev *led_cdev, 109 struct net_device *net_dev) 110 { 111 struct device *dev = led_cdev->hw_control_get_device(led_cdev); 112 struct net_device *ndev; 113 114 if (!dev) 115 return false; 116 117 ndev = to_net_dev(dev); 118 119 return ndev == net_dev; 120 } 121 122 static bool can_hw_control(struct led_netdev_data *trigger_data) 123 { 124 unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); 125 unsigned int interval = atomic_read(&trigger_data->interval); 126 struct led_classdev *led_cdev = trigger_data->led_cdev; 127 int ret; 128 129 if (!supports_hw_control(led_cdev)) 130 return false; 131 132 /* 133 * Interval must be set to the default 134 * value. Any different value is rejected if in hw 135 * control. 136 */ 137 if (interval != default_interval) 138 return false; 139 140 /* 141 * net_dev must be set with hw control, otherwise no 142 * blinking can be happening and there is nothing to 143 * offloaded. Additionally, for hw control to be 144 * valid, the configured netdev must be the same as 145 * netdev associated to the LED. 146 */ 147 if (!validate_net_dev(led_cdev, trigger_data->net_dev)) 148 return false; 149 150 /* Check if the requested mode is supported */ 151 ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); 152 /* Fall back to software blinking if not supported */ 153 if (ret == -EOPNOTSUPP) 154 return false; 155 if (ret) { 156 dev_warn(led_cdev->dev, 157 "Current mode check failed with error %d\n", ret); 158 return false; 159 } 160 161 return true; 162 } 163 164 static ssize_t device_name_show(struct device *dev, 165 struct device_attribute *attr, char *buf) 166 { 167 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 168 ssize_t len; 169 170 mutex_lock(&trigger_data->lock); 171 len = sprintf(buf, "%s\n", trigger_data->device_name); 172 mutex_unlock(&trigger_data->lock); 173 174 return len; 175 } 176 177 static int set_device_name(struct led_netdev_data *trigger_data, 178 const char *name, size_t size) 179 { 180 cancel_delayed_work_sync(&trigger_data->work); 181 182 mutex_lock(&trigger_data->lock); 183 184 if (trigger_data->net_dev) { 185 dev_put(trigger_data->net_dev); 186 trigger_data->net_dev = NULL; 187 } 188 189 memcpy(trigger_data->device_name, name, size); 190 trigger_data->device_name[size] = 0; 191 if (size > 0 && trigger_data->device_name[size - 1] == '\n') 192 trigger_data->device_name[size - 1] = 0; 193 194 if (trigger_data->device_name[0] != 0) 195 trigger_data->net_dev = 196 dev_get_by_name(&init_net, trigger_data->device_name); 197 198 trigger_data->carrier_link_up = false; 199 if (trigger_data->net_dev != NULL) 200 trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); 201 202 trigger_data->last_activity = 0; 203 204 set_baseline_state(trigger_data); 205 mutex_unlock(&trigger_data->lock); 206 207 return 0; 208 } 209 210 static ssize_t device_name_store(struct device *dev, 211 struct device_attribute *attr, const char *buf, 212 size_t size) 213 { 214 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 215 int ret; 216 217 if (size >= IFNAMSIZ) 218 return -EINVAL; 219 220 ret = set_device_name(trigger_data, buf, size); 221 222 if (ret < 0) 223 return ret; 224 return size; 225 } 226 227 static DEVICE_ATTR_RW(device_name); 228 229 static ssize_t netdev_led_attr_show(struct device *dev, char *buf, 230 enum led_trigger_netdev_modes attr) 231 { 232 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 233 int bit; 234 235 switch (attr) { 236 case TRIGGER_NETDEV_LINK: 237 case TRIGGER_NETDEV_TX: 238 case TRIGGER_NETDEV_RX: 239 bit = attr; 240 break; 241 default: 242 return -EINVAL; 243 } 244 245 return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode)); 246 } 247 248 static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, 249 size_t size, enum led_trigger_netdev_modes attr) 250 { 251 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 252 unsigned long state; 253 int ret; 254 int bit; 255 256 ret = kstrtoul(buf, 0, &state); 257 if (ret) 258 return ret; 259 260 switch (attr) { 261 case TRIGGER_NETDEV_LINK: 262 case TRIGGER_NETDEV_TX: 263 case TRIGGER_NETDEV_RX: 264 bit = attr; 265 break; 266 default: 267 return -EINVAL; 268 } 269 270 cancel_delayed_work_sync(&trigger_data->work); 271 272 if (state) 273 set_bit(bit, &trigger_data->mode); 274 else 275 clear_bit(bit, &trigger_data->mode); 276 277 trigger_data->hw_control = can_hw_control(trigger_data); 278 279 set_baseline_state(trigger_data); 280 281 return size; 282 } 283 284 #define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ 285 static ssize_t trigger_name##_show(struct device *dev, \ 286 struct device_attribute *attr, char *buf) \ 287 { \ 288 return netdev_led_attr_show(dev, buf, trigger); \ 289 } \ 290 static ssize_t trigger_name##_store(struct device *dev, \ 291 struct device_attribute *attr, const char *buf, size_t size) \ 292 { \ 293 return netdev_led_attr_store(dev, buf, size, trigger); \ 294 } \ 295 static DEVICE_ATTR_RW(trigger_name) 296 297 DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); 298 DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); 299 DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); 300 301 static ssize_t interval_show(struct device *dev, 302 struct device_attribute *attr, char *buf) 303 { 304 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 305 306 return sprintf(buf, "%u\n", 307 jiffies_to_msecs(atomic_read(&trigger_data->interval))); 308 } 309 310 static ssize_t interval_store(struct device *dev, 311 struct device_attribute *attr, const char *buf, 312 size_t size) 313 { 314 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 315 unsigned long value; 316 int ret; 317 318 if (trigger_data->hw_control) 319 return -EINVAL; 320 321 ret = kstrtoul(buf, 0, &value); 322 if (ret) 323 return ret; 324 325 /* impose some basic bounds on the timer interval */ 326 if (value >= 5 && value <= 10000) { 327 cancel_delayed_work_sync(&trigger_data->work); 328 329 atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); 330 set_baseline_state(trigger_data); /* resets timer */ 331 } 332 333 return size; 334 } 335 336 static DEVICE_ATTR_RW(interval); 337 338 static struct attribute *netdev_trig_attrs[] = { 339 &dev_attr_device_name.attr, 340 &dev_attr_link.attr, 341 &dev_attr_rx.attr, 342 &dev_attr_tx.attr, 343 &dev_attr_interval.attr, 344 NULL 345 }; 346 ATTRIBUTE_GROUPS(netdev_trig); 347 348 static int netdev_trig_notify(struct notifier_block *nb, 349 unsigned long evt, void *dv) 350 { 351 struct net_device *dev = 352 netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); 353 struct led_netdev_data *trigger_data = 354 container_of(nb, struct led_netdev_data, notifier); 355 356 if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE 357 && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER 358 && evt != NETDEV_CHANGENAME) 359 return NOTIFY_DONE; 360 361 if (!(dev == trigger_data->net_dev || 362 (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) || 363 (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name)))) 364 return NOTIFY_DONE; 365 366 cancel_delayed_work_sync(&trigger_data->work); 367 368 mutex_lock(&trigger_data->lock); 369 370 trigger_data->carrier_link_up = false; 371 switch (evt) { 372 case NETDEV_CHANGENAME: 373 trigger_data->carrier_link_up = netif_carrier_ok(dev); 374 fallthrough; 375 case NETDEV_REGISTER: 376 if (trigger_data->net_dev) 377 dev_put(trigger_data->net_dev); 378 dev_hold(dev); 379 trigger_data->net_dev = dev; 380 break; 381 case NETDEV_UNREGISTER: 382 dev_put(trigger_data->net_dev); 383 trigger_data->net_dev = NULL; 384 break; 385 case NETDEV_UP: 386 case NETDEV_CHANGE: 387 trigger_data->carrier_link_up = netif_carrier_ok(dev); 388 break; 389 } 390 391 set_baseline_state(trigger_data); 392 393 mutex_unlock(&trigger_data->lock); 394 395 return NOTIFY_DONE; 396 } 397 398 /* here's the real work! */ 399 static void netdev_trig_work(struct work_struct *work) 400 { 401 struct led_netdev_data *trigger_data = 402 container_of(work, struct led_netdev_data, work.work); 403 struct rtnl_link_stats64 *dev_stats; 404 unsigned int new_activity; 405 struct rtnl_link_stats64 temp; 406 unsigned long interval; 407 int invert; 408 409 /* If we dont have a device, insure we are off */ 410 if (!trigger_data->net_dev) { 411 led_set_brightness(trigger_data->led_cdev, LED_OFF); 412 return; 413 } 414 415 /* If we are not looking for RX/TX then return */ 416 if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && 417 !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) 418 return; 419 420 dev_stats = dev_get_stats(trigger_data->net_dev, &temp); 421 new_activity = 422 (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? 423 dev_stats->tx_packets : 0) + 424 (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? 425 dev_stats->rx_packets : 0); 426 427 if (trigger_data->last_activity != new_activity) { 428 led_stop_software_blink(trigger_data->led_cdev); 429 430 invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); 431 interval = jiffies_to_msecs( 432 atomic_read(&trigger_data->interval)); 433 /* base state is ON (link present) */ 434 led_blink_set_oneshot(trigger_data->led_cdev, 435 &interval, 436 &interval, 437 invert); 438 trigger_data->last_activity = new_activity; 439 } 440 441 schedule_delayed_work(&trigger_data->work, 442 (atomic_read(&trigger_data->interval)*2)); 443 } 444 445 static int netdev_trig_activate(struct led_classdev *led_cdev) 446 { 447 struct led_netdev_data *trigger_data; 448 unsigned long mode; 449 struct device *dev; 450 int rc; 451 452 trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); 453 if (!trigger_data) 454 return -ENOMEM; 455 456 mutex_init(&trigger_data->lock); 457 458 trigger_data->notifier.notifier_call = netdev_trig_notify; 459 trigger_data->notifier.priority = 10; 460 461 INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work); 462 463 trigger_data->led_cdev = led_cdev; 464 trigger_data->net_dev = NULL; 465 trigger_data->device_name[0] = 0; 466 467 trigger_data->mode = 0; 468 atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); 469 trigger_data->last_activity = 0; 470 471 /* Check if hw control is active by default on the LED. 472 * Init already enabled mode in hw control. 473 */ 474 if (supports_hw_control(led_cdev) && 475 !led_cdev->hw_control_get(led_cdev, &mode)) { 476 dev = led_cdev->hw_control_get_device(led_cdev); 477 if (dev) { 478 const char *name = dev_name(dev); 479 480 set_device_name(trigger_data, name, strlen(name)); 481 trigger_data->hw_control = true; 482 trigger_data->mode = mode; 483 } 484 } 485 486 led_set_trigger_data(led_cdev, trigger_data); 487 488 rc = register_netdevice_notifier(&trigger_data->notifier); 489 if (rc) 490 kfree(trigger_data); 491 492 return rc; 493 } 494 495 static void netdev_trig_deactivate(struct led_classdev *led_cdev) 496 { 497 struct led_netdev_data *trigger_data = led_get_trigger_data(led_cdev); 498 499 unregister_netdevice_notifier(&trigger_data->notifier); 500 501 cancel_delayed_work_sync(&trigger_data->work); 502 503 if (trigger_data->net_dev) 504 dev_put(trigger_data->net_dev); 505 506 kfree(trigger_data); 507 } 508 509 static struct led_trigger netdev_led_trigger = { 510 .name = "netdev", 511 .activate = netdev_trig_activate, 512 .deactivate = netdev_trig_deactivate, 513 .groups = netdev_trig_groups, 514 }; 515 516 static int __init netdev_trig_init(void) 517 { 518 return led_trigger_register(&netdev_led_trigger); 519 } 520 521 static void __exit netdev_trig_exit(void) 522 { 523 led_trigger_unregister(&netdev_led_trigger); 524 } 525 526 module_init(netdev_trig_init); 527 module_exit(netdev_trig_exit); 528 529 MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>"); 530 MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>"); 531 MODULE_DESCRIPTION("Netdev LED trigger"); 532 MODULE_LICENSE("GPL v2"); 533