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/ethtool.h> 17 #include <linux/init.h> 18 #include <linux/jiffies.h> 19 #include <linux/kernel.h> 20 #include <linux/leds.h> 21 #include <linux/list.h> 22 #include <linux/module.h> 23 #include <linux/netdevice.h> 24 #include <linux/mutex.h> 25 #include <linux/rtnetlink.h> 26 #include <linux/timer.h> 27 #include "../leds.h" 28 29 #define NETDEV_LED_DEFAULT_INTERVAL 50 30 31 /* 32 * Configurable sysfs attributes: 33 * 34 * device_name - network device name to monitor 35 * interval - duration of LED blink, in milliseconds 36 * link - LED's normal state reflects whether the link is up 37 * (has carrier) or not 38 * tx - LED blinks on transmitted data 39 * rx - LED blinks on receive data 40 * 41 * Note: If the user selects a mode that is not supported by hw, default 42 * behavior is to fall back to software control of the LED. However not every 43 * hw supports software control. LED callbacks brightness_set() and 44 * brightness_set_blocking() are NULL in this case. hw_control_is_supported() 45 * should use available means supported by hw to inform the user that selected 46 * mode isn't supported by hw. This could be switching off the LED or any 47 * hw blink mode. If software control fallback isn't possible, we return 48 * -EOPNOTSUPP to the user, but still store the selected mode. This is needed 49 * in case an intermediate unsupported mode is necessary to switch from one 50 * supported mode to another. 51 */ 52 53 struct led_netdev_data { 54 struct mutex lock; 55 56 struct delayed_work work; 57 struct notifier_block notifier; 58 59 struct led_classdev *led_cdev; 60 struct net_device *net_dev; 61 62 char device_name[IFNAMSIZ]; 63 atomic_t interval; 64 unsigned int last_activity; 65 66 unsigned long mode; 67 int link_speed; 68 u8 duplex; 69 70 bool carrier_link_up; 71 bool hw_control; 72 }; 73 74 static void set_baseline_state(struct led_netdev_data *trigger_data) 75 { 76 int current_brightness; 77 struct led_classdev *led_cdev = trigger_data->led_cdev; 78 79 /* Already validated, hw control is possible with the requested mode */ 80 if (trigger_data->hw_control) { 81 led_cdev->hw_control_set(led_cdev, trigger_data->mode); 82 83 return; 84 } 85 86 current_brightness = led_cdev->brightness; 87 if (current_brightness) 88 led_cdev->blink_brightness = current_brightness; 89 if (!led_cdev->blink_brightness) 90 led_cdev->blink_brightness = led_cdev->max_brightness; 91 92 if (!trigger_data->carrier_link_up) { 93 led_set_brightness(led_cdev, LED_OFF); 94 } else { 95 bool blink_on = false; 96 97 if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) 98 blink_on = true; 99 100 if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) && 101 trigger_data->link_speed == SPEED_10) 102 blink_on = true; 103 104 if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) && 105 trigger_data->link_speed == SPEED_100) 106 blink_on = true; 107 108 if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && 109 trigger_data->link_speed == SPEED_1000) 110 blink_on = true; 111 112 if (test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) && 113 trigger_data->link_speed == SPEED_2500) 114 blink_on = true; 115 116 if (test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) && 117 trigger_data->link_speed == SPEED_5000) 118 blink_on = true; 119 120 if (test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) && 121 trigger_data->link_speed == SPEED_10000) 122 blink_on = true; 123 124 if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && 125 trigger_data->duplex == DUPLEX_HALF) 126 blink_on = true; 127 128 if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && 129 trigger_data->duplex == DUPLEX_FULL) 130 blink_on = true; 131 132 if (blink_on) 133 led_set_brightness(led_cdev, 134 led_cdev->blink_brightness); 135 else 136 led_set_brightness(led_cdev, LED_OFF); 137 138 /* If we are looking for RX/TX start periodically 139 * checking stats 140 */ 141 if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || 142 test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) 143 schedule_delayed_work(&trigger_data->work, 0); 144 } 145 } 146 147 static bool supports_hw_control(struct led_classdev *led_cdev) 148 { 149 if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || 150 !led_cdev->hw_control_is_supported) 151 return false; 152 153 return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); 154 } 155 156 /* 157 * Validate the configured netdev is the same as the one associated with 158 * the LED driver in hw control. 159 */ 160 static bool validate_net_dev(struct led_classdev *led_cdev, 161 struct net_device *net_dev) 162 { 163 struct device *dev = led_cdev->hw_control_get_device(led_cdev); 164 struct net_device *ndev; 165 166 if (!dev) 167 return false; 168 169 ndev = to_net_dev(dev); 170 171 return ndev == net_dev; 172 } 173 174 static bool can_hw_control(struct led_netdev_data *trigger_data) 175 { 176 unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); 177 unsigned int interval = atomic_read(&trigger_data->interval); 178 struct led_classdev *led_cdev = trigger_data->led_cdev; 179 int ret; 180 181 if (!supports_hw_control(led_cdev)) 182 return false; 183 184 /* 185 * Interval must be set to the default 186 * value. Any different value is rejected if in hw 187 * control. 188 */ 189 if (interval != default_interval) 190 return false; 191 192 /* 193 * net_dev must be set with hw control, otherwise no 194 * blinking can be happening and there is nothing to 195 * offloaded. Additionally, for hw control to be 196 * valid, the configured netdev must be the same as 197 * netdev associated to the LED. 198 */ 199 if (!validate_net_dev(led_cdev, trigger_data->net_dev)) 200 return false; 201 202 /* Check if the requested mode is supported */ 203 ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); 204 /* Fall back to software blinking if not supported */ 205 if (ret == -EOPNOTSUPP) 206 return false; 207 if (ret) { 208 dev_warn(led_cdev->dev, 209 "Current mode check failed with error %d\n", ret); 210 return false; 211 } 212 213 return true; 214 } 215 216 static void get_device_state(struct led_netdev_data *trigger_data) 217 { 218 struct ethtool_link_ksettings cmd; 219 220 trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); 221 if (!trigger_data->carrier_link_up) 222 return; 223 224 if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { 225 trigger_data->link_speed = cmd.base.speed; 226 trigger_data->duplex = cmd.base.duplex; 227 } 228 } 229 230 static ssize_t device_name_show(struct device *dev, 231 struct device_attribute *attr, char *buf) 232 { 233 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 234 ssize_t len; 235 236 mutex_lock(&trigger_data->lock); 237 len = sprintf(buf, "%s\n", trigger_data->device_name); 238 mutex_unlock(&trigger_data->lock); 239 240 return len; 241 } 242 243 static int set_device_name(struct led_netdev_data *trigger_data, 244 const char *name, size_t size) 245 { 246 if (size >= IFNAMSIZ) 247 return -EINVAL; 248 249 cancel_delayed_work_sync(&trigger_data->work); 250 251 /* 252 * Take RTNL lock before trigger_data lock to prevent potential 253 * deadlock with netdev notifier registration. 254 */ 255 rtnl_lock(); 256 mutex_lock(&trigger_data->lock); 257 258 if (trigger_data->net_dev) { 259 dev_put(trigger_data->net_dev); 260 trigger_data->net_dev = NULL; 261 } 262 263 memcpy(trigger_data->device_name, name, size); 264 trigger_data->device_name[size] = 0; 265 if (size > 0 && trigger_data->device_name[size - 1] == '\n') 266 trigger_data->device_name[size - 1] = 0; 267 268 if (trigger_data->device_name[0] != 0) 269 trigger_data->net_dev = 270 dev_get_by_name(&init_net, trigger_data->device_name); 271 272 trigger_data->carrier_link_up = false; 273 trigger_data->link_speed = SPEED_UNKNOWN; 274 trigger_data->duplex = DUPLEX_UNKNOWN; 275 if (trigger_data->net_dev) 276 get_device_state(trigger_data); 277 278 trigger_data->last_activity = 0; 279 280 set_baseline_state(trigger_data); 281 mutex_unlock(&trigger_data->lock); 282 rtnl_unlock(); 283 284 return 0; 285 } 286 287 static ssize_t device_name_store(struct device *dev, 288 struct device_attribute *attr, const char *buf, 289 size_t size) 290 { 291 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 292 int ret; 293 294 ret = set_device_name(trigger_data, buf, size); 295 296 if (ret < 0) 297 return ret; 298 return size; 299 } 300 301 static DEVICE_ATTR_RW(device_name); 302 303 static ssize_t netdev_led_attr_show(struct device *dev, char *buf, 304 enum led_trigger_netdev_modes attr) 305 { 306 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 307 int bit; 308 309 switch (attr) { 310 case TRIGGER_NETDEV_LINK: 311 case TRIGGER_NETDEV_LINK_10: 312 case TRIGGER_NETDEV_LINK_100: 313 case TRIGGER_NETDEV_LINK_1000: 314 case TRIGGER_NETDEV_LINK_2500: 315 case TRIGGER_NETDEV_LINK_5000: 316 case TRIGGER_NETDEV_LINK_10000: 317 case TRIGGER_NETDEV_HALF_DUPLEX: 318 case TRIGGER_NETDEV_FULL_DUPLEX: 319 case TRIGGER_NETDEV_TX: 320 case TRIGGER_NETDEV_RX: 321 bit = attr; 322 break; 323 default: 324 return -EINVAL; 325 } 326 327 return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode)); 328 } 329 330 static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, 331 size_t size, enum led_trigger_netdev_modes attr) 332 { 333 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 334 struct led_classdev *led_cdev = trigger_data->led_cdev; 335 unsigned long state, mode = trigger_data->mode; 336 int ret; 337 int bit; 338 339 ret = kstrtoul(buf, 0, &state); 340 if (ret) 341 return ret; 342 343 switch (attr) { 344 case TRIGGER_NETDEV_LINK: 345 case TRIGGER_NETDEV_LINK_10: 346 case TRIGGER_NETDEV_LINK_100: 347 case TRIGGER_NETDEV_LINK_1000: 348 case TRIGGER_NETDEV_LINK_2500: 349 case TRIGGER_NETDEV_LINK_5000: 350 case TRIGGER_NETDEV_LINK_10000: 351 case TRIGGER_NETDEV_HALF_DUPLEX: 352 case TRIGGER_NETDEV_FULL_DUPLEX: 353 case TRIGGER_NETDEV_TX: 354 case TRIGGER_NETDEV_RX: 355 bit = attr; 356 break; 357 default: 358 return -EINVAL; 359 } 360 361 if (state) 362 set_bit(bit, &mode); 363 else 364 clear_bit(bit, &mode); 365 366 if (test_bit(TRIGGER_NETDEV_LINK, &mode) && 367 (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || 368 test_bit(TRIGGER_NETDEV_LINK_100, &mode) || 369 test_bit(TRIGGER_NETDEV_LINK_1000, &mode) || 370 test_bit(TRIGGER_NETDEV_LINK_2500, &mode) || 371 test_bit(TRIGGER_NETDEV_LINK_5000, &mode) || 372 test_bit(TRIGGER_NETDEV_LINK_10000, &mode))) 373 return -EINVAL; 374 375 cancel_delayed_work_sync(&trigger_data->work); 376 377 trigger_data->mode = mode; 378 trigger_data->hw_control = can_hw_control(trigger_data); 379 380 if (!led_cdev->brightness_set && !led_cdev->brightness_set_blocking && 381 !trigger_data->hw_control) 382 return -EOPNOTSUPP; 383 384 set_baseline_state(trigger_data); 385 386 return size; 387 } 388 389 #define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ 390 static ssize_t trigger_name##_show(struct device *dev, \ 391 struct device_attribute *attr, char *buf) \ 392 { \ 393 return netdev_led_attr_show(dev, buf, trigger); \ 394 } \ 395 static ssize_t trigger_name##_store(struct device *dev, \ 396 struct device_attribute *attr, const char *buf, size_t size) \ 397 { \ 398 return netdev_led_attr_store(dev, buf, size, trigger); \ 399 } \ 400 static DEVICE_ATTR_RW(trigger_name) 401 402 DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); 403 DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); 404 DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); 405 DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); 406 DEFINE_NETDEV_TRIGGER(link_2500, TRIGGER_NETDEV_LINK_2500); 407 DEFINE_NETDEV_TRIGGER(link_5000, TRIGGER_NETDEV_LINK_5000); 408 DEFINE_NETDEV_TRIGGER(link_10000, TRIGGER_NETDEV_LINK_10000); 409 DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); 410 DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); 411 DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); 412 DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); 413 414 static ssize_t interval_show(struct device *dev, 415 struct device_attribute *attr, char *buf) 416 { 417 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 418 419 return sprintf(buf, "%u\n", 420 jiffies_to_msecs(atomic_read(&trigger_data->interval))); 421 } 422 423 static ssize_t interval_store(struct device *dev, 424 struct device_attribute *attr, const char *buf, 425 size_t size) 426 { 427 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 428 unsigned long value; 429 int ret; 430 431 if (trigger_data->hw_control) 432 return -EINVAL; 433 434 ret = kstrtoul(buf, 0, &value); 435 if (ret) 436 return ret; 437 438 /* impose some basic bounds on the timer interval */ 439 if (value >= 5 && value <= 10000) { 440 cancel_delayed_work_sync(&trigger_data->work); 441 442 atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); 443 set_baseline_state(trigger_data); /* resets timer */ 444 } 445 446 return size; 447 } 448 449 static DEVICE_ATTR_RW(interval); 450 451 static ssize_t offloaded_show(struct device *dev, 452 struct device_attribute *attr, char *buf) 453 { 454 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 455 456 return sprintf(buf, "%d\n", trigger_data->hw_control); 457 } 458 459 static DEVICE_ATTR_RO(offloaded); 460 461 static struct attribute *netdev_trig_attrs[] = { 462 &dev_attr_device_name.attr, 463 &dev_attr_link.attr, 464 &dev_attr_link_10.attr, 465 &dev_attr_link_100.attr, 466 &dev_attr_link_1000.attr, 467 &dev_attr_link_2500.attr, 468 &dev_attr_link_5000.attr, 469 &dev_attr_link_10000.attr, 470 &dev_attr_full_duplex.attr, 471 &dev_attr_half_duplex.attr, 472 &dev_attr_rx.attr, 473 &dev_attr_tx.attr, 474 &dev_attr_interval.attr, 475 &dev_attr_offloaded.attr, 476 NULL 477 }; 478 ATTRIBUTE_GROUPS(netdev_trig); 479 480 static int netdev_trig_notify(struct notifier_block *nb, 481 unsigned long evt, void *dv) 482 { 483 struct net_device *dev = 484 netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); 485 struct led_netdev_data *trigger_data = 486 container_of(nb, struct led_netdev_data, notifier); 487 488 if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE 489 && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER 490 && evt != NETDEV_CHANGENAME) 491 return NOTIFY_DONE; 492 493 if (!(dev == trigger_data->net_dev || 494 (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) || 495 (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name)))) 496 return NOTIFY_DONE; 497 498 cancel_delayed_work_sync(&trigger_data->work); 499 500 mutex_lock(&trigger_data->lock); 501 502 trigger_data->carrier_link_up = false; 503 trigger_data->link_speed = SPEED_UNKNOWN; 504 trigger_data->duplex = DUPLEX_UNKNOWN; 505 switch (evt) { 506 case NETDEV_CHANGENAME: 507 get_device_state(trigger_data); 508 fallthrough; 509 case NETDEV_REGISTER: 510 dev_put(trigger_data->net_dev); 511 dev_hold(dev); 512 trigger_data->net_dev = dev; 513 break; 514 case NETDEV_UNREGISTER: 515 dev_put(trigger_data->net_dev); 516 trigger_data->net_dev = NULL; 517 break; 518 case NETDEV_UP: 519 case NETDEV_CHANGE: 520 get_device_state(trigger_data); 521 break; 522 } 523 524 set_baseline_state(trigger_data); 525 526 mutex_unlock(&trigger_data->lock); 527 528 return NOTIFY_DONE; 529 } 530 531 /* here's the real work! */ 532 static void netdev_trig_work(struct work_struct *work) 533 { 534 struct led_netdev_data *trigger_data = 535 container_of(work, struct led_netdev_data, work.work); 536 struct rtnl_link_stats64 *dev_stats; 537 unsigned int new_activity; 538 struct rtnl_link_stats64 temp; 539 unsigned long interval; 540 int invert; 541 542 /* If we dont have a device, insure we are off */ 543 if (!trigger_data->net_dev) { 544 led_set_brightness(trigger_data->led_cdev, LED_OFF); 545 return; 546 } 547 548 /* If we are not looking for RX/TX then return */ 549 if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && 550 !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) 551 return; 552 553 dev_stats = dev_get_stats(trigger_data->net_dev, &temp); 554 new_activity = 555 (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? 556 dev_stats->tx_packets : 0) + 557 (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? 558 dev_stats->rx_packets : 0); 559 560 if (trigger_data->last_activity != new_activity) { 561 led_stop_software_blink(trigger_data->led_cdev); 562 563 invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || 564 test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || 565 test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || 566 test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || 567 test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) || 568 test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) || 569 test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) || 570 test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || 571 test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); 572 interval = jiffies_to_msecs( 573 atomic_read(&trigger_data->interval)); 574 /* base state is ON (link present) */ 575 led_blink_set_oneshot(trigger_data->led_cdev, 576 &interval, 577 &interval, 578 invert); 579 trigger_data->last_activity = new_activity; 580 } 581 582 schedule_delayed_work(&trigger_data->work, 583 (atomic_read(&trigger_data->interval)*2)); 584 } 585 586 static int netdev_trig_activate(struct led_classdev *led_cdev) 587 { 588 struct led_netdev_data *trigger_data; 589 unsigned long mode = 0; 590 struct device *dev; 591 int rc; 592 593 trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); 594 if (!trigger_data) 595 return -ENOMEM; 596 597 mutex_init(&trigger_data->lock); 598 599 trigger_data->notifier.notifier_call = netdev_trig_notify; 600 trigger_data->notifier.priority = 10; 601 602 INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work); 603 604 trigger_data->led_cdev = led_cdev; 605 trigger_data->net_dev = NULL; 606 trigger_data->device_name[0] = 0; 607 608 trigger_data->mode = 0; 609 atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); 610 trigger_data->last_activity = 0; 611 612 /* Check if hw control is active by default on the LED. 613 * Init already enabled mode in hw control. 614 */ 615 if (supports_hw_control(led_cdev)) { 616 dev = led_cdev->hw_control_get_device(led_cdev); 617 if (dev) { 618 const char *name = dev_name(dev); 619 620 set_device_name(trigger_data, name, strlen(name)); 621 trigger_data->hw_control = true; 622 623 rc = led_cdev->hw_control_get(led_cdev, &mode); 624 if (!rc) 625 trigger_data->mode = mode; 626 } 627 } 628 629 led_set_trigger_data(led_cdev, trigger_data); 630 631 rc = register_netdevice_notifier(&trigger_data->notifier); 632 if (rc) 633 kfree(trigger_data); 634 635 return rc; 636 } 637 638 static void netdev_trig_deactivate(struct led_classdev *led_cdev) 639 { 640 struct led_netdev_data *trigger_data = led_get_trigger_data(led_cdev); 641 642 unregister_netdevice_notifier(&trigger_data->notifier); 643 644 cancel_delayed_work_sync(&trigger_data->work); 645 646 led_set_brightness(led_cdev, LED_OFF); 647 648 dev_put(trigger_data->net_dev); 649 650 kfree(trigger_data); 651 } 652 653 static struct led_trigger netdev_led_trigger = { 654 .name = "netdev", 655 .activate = netdev_trig_activate, 656 .deactivate = netdev_trig_deactivate, 657 .groups = netdev_trig_groups, 658 }; 659 660 module_led_trigger(netdev_led_trigger); 661 662 MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>"); 663 MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>"); 664 MODULE_DESCRIPTION("Netdev LED trigger"); 665 MODULE_LICENSE("GPL v2"); 666