Skip to content

Commit cf83318

Browse files
shifty91anguy11
authored andcommitted
igc: Export LEDs
Each i225 has three LEDs. Export them via the LED class framework. Each LED is controllable via sysfs. Example: $ cd /sys/class/leds/igc_led0 $ cat brightness # Current Mode $ cat max_brightness # 15 $ echo 0 > brightness # Mode 0 $ echo 1 > brightness # Mode 1 The brightness field here reflects the different LED modes ranging from 0 to 15. Signed-off-by: Kurt Kanzenbach <[email protected]> Reviewed-by: Sebastian Andrzej Siewior <[email protected]> Tested-by: Dvora Fuxbrumer <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 7374426 commit cf83318

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

drivers/net/ethernet/intel/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ config IGC
335335
tristate "Intel(R) Ethernet Controller I225-LM/I225-V support"
336336
default n
337337
depends on PCI
338+
depends on LEDS_CLASS
338339
help
339340
This driver supports Intel(R) Ethernet Controller I225-LM/I225-V
340341
family of adapters.

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/ptp_clock_kernel.h>
1414
#include <linux/timecounter.h>
1515
#include <linux/net_tstamp.h>
16+
#include <linux/leds.h>
1617

1718
#include "igc_hw.h"
1819

@@ -239,8 +240,17 @@ struct igc_adapter {
239240
struct timespec64 start;
240241
struct timespec64 period;
241242
} perout[IGC_N_PEROUT];
243+
244+
/* LEDs */
245+
struct mutex led_mutex;
246+
struct led_classdev led0;
247+
struct led_classdev led1;
248+
struct led_classdev led2;
242249
};
243250

251+
#define led_to_igc(ldev, led) \
252+
container_of(ldev, struct igc_adapter, led)
253+
244254
void igc_up(struct igc_adapter *adapter);
245255
void igc_down(struct igc_adapter *adapter);
246256
int igc_open(struct net_device *netdev);

drivers/net/ethernet/intel/igc/igc_defines.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@
144144
#define IGC_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */
145145
#define IGC_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */
146146

147+
/* LED Control */
148+
#define IGC_LEDCTL_LED0_MODE_SHIFT 0
149+
#define IGC_LEDCTL_LED0_MODE_MASK GENMASK(3, 0)
150+
#define IGC_LEDCTL_LED1_MODE_SHIFT 8
151+
#define IGC_LEDCTL_LED1_MODE_MASK GENMASK(11, 8)
152+
#define IGC_LEDCTL_LED2_MODE_SHIFT 16
153+
#define IGC_LEDCTL_LED2_MODE_MASK GENMASK(19, 16)
154+
155+
#define IGC_CONNSW_AUTOSENSE_EN 0x1
156+
147157
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
148158
#define MAX_JUMBO_FRAME_SIZE 0x2600
149159

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6130,6 +6130,134 @@ int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx)
61306130
return -EINVAL;
61316131
}
61326132

6133+
static void igc_select_led(struct igc_adapter *adapter, int led,
6134+
u32 *mask, u32 *shift)
6135+
{
6136+
switch (led) {
6137+
case 0:
6138+
*mask = IGC_LEDCTL_LED0_MODE_MASK;
6139+
*shift = IGC_LEDCTL_LED0_MODE_SHIFT;
6140+
break;
6141+
case 1:
6142+
*mask = IGC_LEDCTL_LED1_MODE_MASK;
6143+
*shift = IGC_LEDCTL_LED1_MODE_SHIFT;
6144+
break;
6145+
case 2:
6146+
*mask = IGC_LEDCTL_LED2_MODE_MASK;
6147+
*shift = IGC_LEDCTL_LED2_MODE_SHIFT;
6148+
break;
6149+
default:
6150+
*mask = *shift = 0;
6151+
dev_err(&adapter->pdev->dev, "Unknown led %d selected!", led);
6152+
}
6153+
}
6154+
6155+
static void igc_led_set(struct igc_adapter *adapter, int led, u16 brightness)
6156+
{
6157+
struct igc_hw *hw = &adapter->hw;
6158+
u32 shift, mask, ledctl;
6159+
6160+
igc_select_led(adapter, led, &mask, &shift);
6161+
6162+
mutex_lock(&adapter->led_mutex);
6163+
ledctl = rd32(IGC_LEDCTL);
6164+
ledctl &= ~mask;
6165+
ledctl |= brightness << shift;
6166+
wr32(IGC_LEDCTL, ledctl);
6167+
mutex_unlock(&adapter->led_mutex);
6168+
}
6169+
6170+
static enum led_brightness igc_led_get(struct igc_adapter *adapter, int led)
6171+
{
6172+
struct igc_hw *hw = &adapter->hw;
6173+
u32 shift, mask, ledctl;
6174+
6175+
igc_select_led(adapter, led, &mask, &shift);
6176+
6177+
mutex_lock(&adapter->led_mutex);
6178+
ledctl = rd32(IGC_LEDCTL);
6179+
mutex_unlock(&adapter->led_mutex);
6180+
6181+
return (ledctl & mask) >> shift;
6182+
}
6183+
6184+
static void igc_led0_set(struct led_classdev *ldev, enum led_brightness b)
6185+
{
6186+
struct igc_adapter *adapter = led_to_igc(ldev, led0);
6187+
6188+
igc_led_set(adapter, 0, b);
6189+
}
6190+
6191+
static enum led_brightness igc_led0_get(struct led_classdev *ldev)
6192+
{
6193+
struct igc_adapter *adapter = led_to_igc(ldev, led0);
6194+
6195+
return igc_led_get(adapter, 0);
6196+
}
6197+
6198+
static void igc_led1_set(struct led_classdev *ldev, enum led_brightness b)
6199+
{
6200+
struct igc_adapter *adapter = led_to_igc(ldev, led1);
6201+
6202+
igc_led_set(adapter, 1, b);
6203+
}
6204+
6205+
static enum led_brightness igc_led1_get(struct led_classdev *ldev)
6206+
{
6207+
struct igc_adapter *adapter = led_to_igc(ldev, led1);
6208+
6209+
return igc_led_get(adapter, 1);
6210+
}
6211+
6212+
static void igc_led2_set(struct led_classdev *ldev, enum led_brightness b)
6213+
{
6214+
struct igc_adapter *adapter = led_to_igc(ldev, led2);
6215+
6216+
igc_led_set(adapter, 2, b);
6217+
}
6218+
6219+
static enum led_brightness igc_led2_get(struct led_classdev *ldev)
6220+
{
6221+
struct igc_adapter *adapter = led_to_igc(ldev, led2);
6222+
6223+
return igc_led_get(adapter, 2);
6224+
}
6225+
6226+
static int igc_led_setup(struct igc_adapter *adapter)
6227+
{
6228+
/* Setup */
6229+
mutex_init(&adapter->led_mutex);
6230+
6231+
adapter->led0.name = "igc_led0";
6232+
adapter->led0.max_brightness = 15;
6233+
adapter->led0.brightness_set = igc_led0_set;
6234+
adapter->led0.brightness_get = igc_led0_get;
6235+
6236+
adapter->led1.name = "igc_led1";
6237+
adapter->led1.max_brightness = 15;
6238+
adapter->led1.brightness_set = igc_led1_set;
6239+
adapter->led1.brightness_get = igc_led1_get;
6240+
6241+
adapter->led2.name = "igc_led2";
6242+
adapter->led2.max_brightness = 15;
6243+
adapter->led2.brightness_set = igc_led2_set;
6244+
adapter->led2.brightness_get = igc_led2_get;
6245+
6246+
/* Register leds */
6247+
led_classdev_register(&adapter->pdev->dev, &adapter->led0);
6248+
led_classdev_register(&adapter->pdev->dev, &adapter->led1);
6249+
led_classdev_register(&adapter->pdev->dev, &adapter->led2);
6250+
6251+
return 0;
6252+
}
6253+
6254+
static void igc_led_destroy(struct igc_adapter *adapter)
6255+
{
6256+
led_classdev_unregister(&adapter->led0);
6257+
led_classdev_unregister(&adapter->led1);
6258+
led_classdev_unregister(&adapter->led2);
6259+
}
6260+
61336261
/**
61346262
* igc_probe - Device Initialization Routine
61356263
* @pdev: PCI device information struct
@@ -6357,6 +6485,8 @@ static int igc_probe(struct pci_dev *pdev,
63576485

63586486
pm_runtime_put_noidle(&pdev->dev);
63596487

6488+
igc_led_setup(adapter);
6489+
63606490
return 0;
63616491

63626492
err_register:
@@ -6398,6 +6528,8 @@ static void igc_remove(struct pci_dev *pdev)
63986528

63996529
igc_ptp_stop(adapter);
64006530

6531+
igc_led_destroy(adapter);
6532+
64016533
set_bit(__IGC_DOWN, &adapter->state);
64026534

64036535
del_timer_sync(&adapter->watchdog_timer);

drivers/net/ethernet/intel/igc/igc_regs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#define IGC_EECD 0x00010 /* EEPROM/Flash Control - RW */
1111
#define IGC_CTRL_EXT 0x00018 /* Extended Device Control - RW */
1212
#define IGC_MDIC 0x00020 /* MDI Control - RW */
13+
#define IGC_LEDCTL 0x00E00 /* LED Control - RW */
14+
#define IGC_MDICNFG 0x00E04 /* MDC/MDIO Configuration - RW */
1315
#define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
1416
#define IGC_VET 0x00038 /* VLAN Ether Type - RW */
1517
#define IGC_I225_PHPM 0x00E14 /* I225 PHY Power Management */

0 commit comments

Comments
 (0)