Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christian Marangi and committed by
Jakub Kicinski
f22f95b9 d5e01266

+27 -2
+25 -2
drivers/leds/trigger/ledtrig-netdev.c
··· 55 55 56 56 unsigned long mode; 57 57 int link_speed; 58 + u8 duplex; 58 59 59 60 bool carrier_link_up; 60 61 bool hw_control; ··· 97 96 98 97 if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && 99 98 trigger_data->link_speed == SPEED_1000) 99 + blink_on = true; 100 + 101 + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && 102 + trigger_data->duplex == DUPLEX_HALF) 103 + blink_on = true; 104 + 105 + if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && 106 + trigger_data->duplex == DUPLEX_FULL) 100 107 blink_on = true; 101 108 102 109 if (blink_on) ··· 199 190 if (!trigger_data->carrier_link_up) 200 191 return; 201 192 202 - if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) 193 + if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { 203 194 trigger_data->link_speed = cmd.base.speed; 195 + trigger_data->duplex = cmd.base.duplex; 196 + } 204 197 } 205 198 206 199 static ssize_t device_name_show(struct device *dev, ··· 241 230 242 231 trigger_data->carrier_link_up = false; 243 232 trigger_data->link_speed = SPEED_UNKNOWN; 233 + trigger_data->duplex = DUPLEX_UNKNOWN; 244 234 if (trigger_data->net_dev != NULL) { 245 235 rtnl_lock(); 246 236 get_device_state(trigger_data); ··· 286 274 case TRIGGER_NETDEV_LINK_10: 287 275 case TRIGGER_NETDEV_LINK_100: 288 276 case TRIGGER_NETDEV_LINK_1000: 277 + case TRIGGER_NETDEV_HALF_DUPLEX: 278 + case TRIGGER_NETDEV_FULL_DUPLEX: 289 279 case TRIGGER_NETDEV_TX: 290 280 case TRIGGER_NETDEV_RX: 291 281 bit = attr; ··· 316 302 case TRIGGER_NETDEV_LINK_10: 317 303 case TRIGGER_NETDEV_LINK_100: 318 304 case TRIGGER_NETDEV_LINK_1000: 305 + case TRIGGER_NETDEV_HALF_DUPLEX: 306 + case TRIGGER_NETDEV_FULL_DUPLEX: 319 307 case TRIGGER_NETDEV_TX: 320 308 case TRIGGER_NETDEV_RX: 321 309 bit = attr; ··· 364 348 DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); 365 349 DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); 366 350 DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); 351 + DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); 352 + DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); 367 353 DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); 368 354 DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); 369 355 ··· 412 394 &dev_attr_link_10.attr, 413 395 &dev_attr_link_100.attr, 414 396 &dev_attr_link_1000.attr, 397 + &dev_attr_full_duplex.attr, 398 + &dev_attr_half_duplex.attr, 415 399 &dev_attr_rx.attr, 416 400 &dev_attr_tx.attr, 417 401 &dev_attr_interval.attr, ··· 445 425 446 426 trigger_data->carrier_link_up = false; 447 427 trigger_data->link_speed = SPEED_UNKNOWN; 428 + trigger_data->duplex = DUPLEX_UNKNOWN; 448 429 switch (evt) { 449 430 case NETDEV_CHANGENAME: 450 431 get_device_state(trigger_data); ··· 508 487 invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || 509 488 test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || 510 489 test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || 511 - test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode); 490 + test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || 491 + test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || 492 + test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); 512 493 interval = jiffies_to_msecs( 513 494 atomic_read(&trigger_data->interval)); 514 495 /* base state is ON (link present) */
+2
include/linux/leds.h
··· 558 558 TRIGGER_NETDEV_LINK_10, 559 559 TRIGGER_NETDEV_LINK_100, 560 560 TRIGGER_NETDEV_LINK_1000, 561 + TRIGGER_NETDEV_HALF_DUPLEX, 562 + TRIGGER_NETDEV_FULL_DUPLEX, 561 563 TRIGGER_NETDEV_TX, 562 564 TRIGGER_NETDEV_RX, 563 565