forked from Minki/linux
sfc: Use a single blink implementation
Only some PHYs have firmware support for a LED blink mode, so we currently blink the others in a timer function. Since all PHYs have simple on and off modes, we don't gain anything by using multiple blink implementations. Also, since we have a process context there is no need to use a timer. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
dcf477b2d2
commit
398468ed1b
@ -1890,7 +1890,9 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
|
||||
return 0;
|
||||
}
|
||||
void efx_port_dummy_op_void(struct efx_nic *efx) {}
|
||||
void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {}
|
||||
void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
|
||||
{
|
||||
}
|
||||
|
||||
static struct efx_mac_operations efx_dummy_mac_operations = {
|
||||
.reconfigure = efx_port_dummy_op_void,
|
||||
@ -1909,9 +1911,8 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
|
||||
static struct efx_board efx_dummy_board_info = {
|
||||
.init = efx_port_dummy_op_int,
|
||||
.init_leds = efx_port_dummy_op_void,
|
||||
.set_id_led = efx_port_dummy_op_blink,
|
||||
.set_id_led = efx_port_dummy_op_set_id_led,
|
||||
.monitor = efx_port_dummy_op_int,
|
||||
.blink = efx_port_dummy_op_blink,
|
||||
.fini = efx_port_dummy_op_void,
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,8 @@ extern void efx_hex_dump(const u8 *, unsigned int, const char *);
|
||||
/* Dummy PHY ops for PHY drivers */
|
||||
extern int efx_port_dummy_op_int(struct efx_nic *efx);
|
||||
extern void efx_port_dummy_op_void(struct efx_nic *efx);
|
||||
extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink);
|
||||
extern void
|
||||
efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
|
||||
|
||||
/* MTD */
|
||||
#ifdef CONFIG_SFC_MTD
|
||||
|
@ -187,13 +187,15 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count)
|
||||
{
|
||||
struct efx_nic *efx = netdev_priv(net_dev);
|
||||
|
||||
efx->board_info.blink(efx, 1);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (count)
|
||||
schedule_timeout(count * HZ);
|
||||
else
|
||||
schedule();
|
||||
efx->board_info.blink(efx, 0);
|
||||
do {
|
||||
efx->board_info.set_id_led(efx, EFX_LED_ON);
|
||||
schedule_timeout_interruptible(HZ / 2);
|
||||
|
||||
efx->board_info.set_id_led(efx, EFX_LED_OFF);
|
||||
schedule_timeout_interruptible(HZ / 2);
|
||||
} while (!signal_pending(current) && --count != 0);
|
||||
|
||||
efx->board_info.set_id_led(efx, EFX_LED_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -29,40 +29,6 @@
|
||||
#define FALCON_BOARD_SFN4111T 0x51
|
||||
#define FALCON_BOARD_SFN4112F 0x52
|
||||
|
||||
/* Blink support. If the PHY has no auto-blink mode so we hang it off a timer */
|
||||
#define BLINK_INTERVAL (HZ/2)
|
||||
|
||||
static void blink_led_timer(unsigned long context)
|
||||
{
|
||||
struct efx_nic *efx = (struct efx_nic *)context;
|
||||
struct efx_board *board = &efx->board_info;
|
||||
|
||||
board->set_id_led(efx, board->blink_state);
|
||||
board->blink_state = !board->blink_state;
|
||||
if (board->blink_resubmit)
|
||||
mod_timer(&board->blink_timer, jiffies + BLINK_INTERVAL);
|
||||
}
|
||||
|
||||
static void board_blink(struct efx_nic *efx, bool blink)
|
||||
{
|
||||
struct efx_board *board = &efx->board_info;
|
||||
|
||||
/* The rtnl mutex serialises all ethtool ioctls, so
|
||||
* nothing special needs doing here. */
|
||||
if (blink) {
|
||||
board->blink_resubmit = true;
|
||||
board->blink_state = false;
|
||||
setup_timer(&board->blink_timer, blink_led_timer,
|
||||
(unsigned long)efx);
|
||||
mod_timer(&board->blink_timer, jiffies + BLINK_INTERVAL);
|
||||
} else {
|
||||
board->blink_resubmit = false;
|
||||
if (board->blink_timer.function)
|
||||
del_timer_sync(&board->blink_timer);
|
||||
board->init_leds(efx);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Support for LM87 sensor chip used on several boards
|
||||
*/
|
||||
@ -469,7 +435,7 @@ static int sfe4001_init(struct efx_nic *efx)
|
||||
|
||||
/* 10Xpress has fixed-function LED pins, so there is no board-specific
|
||||
* blink code. */
|
||||
efx->board_info.blink = tenxpress_phy_blink;
|
||||
efx->board_info.set_id_led = tenxpress_set_id_led;
|
||||
|
||||
efx->board_info.monitor = sfe4001_check_hw;
|
||||
efx->board_info.fini = sfe4001_fini;
|
||||
@ -546,7 +512,7 @@ static int sfn4111t_init(struct efx_nic *efx)
|
||||
if (!efx->board_info.hwmon_client)
|
||||
return -EIO;
|
||||
|
||||
efx->board_info.blink = tenxpress_phy_blink;
|
||||
efx->board_info.set_id_led = tenxpress_set_id_led;
|
||||
efx->board_info.monitor = sfn4111t_check_hw;
|
||||
efx->board_info.fini = sfn4111t_fini;
|
||||
|
||||
@ -619,10 +585,11 @@ static void sfe4002_init_leds(struct efx_nic *efx)
|
||||
falcon_qt202x_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF);
|
||||
}
|
||||
|
||||
static void sfe4002_set_id_led(struct efx_nic *efx, bool state)
|
||||
static void sfe4002_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
|
||||
{
|
||||
falcon_qt202x_set_led(efx, SFE4002_FAULT_LED, state ? QUAKE_LED_ON :
|
||||
QUAKE_LED_OFF);
|
||||
falcon_qt202x_set_led(
|
||||
efx, SFE4002_FAULT_LED,
|
||||
(mode == EFX_LED_ON) ? QUAKE_LED_ON : QUAKE_LED_OFF);
|
||||
}
|
||||
|
||||
static int sfe4002_check_hw(struct efx_nic *efx)
|
||||
@ -644,7 +611,6 @@ static int sfe4002_init(struct efx_nic *efx)
|
||||
efx->board_info.monitor = sfe4002_check_hw;
|
||||
efx->board_info.init_leds = sfe4002_init_leds;
|
||||
efx->board_info.set_id_led = sfe4002_set_id_led;
|
||||
efx->board_info.blink = board_blink;
|
||||
efx->board_info.fini = efx_fini_lm87;
|
||||
return 0;
|
||||
}
|
||||
@ -683,10 +649,23 @@ static void sfn4112f_init_leds(struct efx_nic *efx)
|
||||
QUAKE_LED_RXLINK | QUAKE_LED_LINK_STAT);
|
||||
}
|
||||
|
||||
static void sfn4112f_set_id_led(struct efx_nic *efx, bool state)
|
||||
static void sfn4112f_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
|
||||
{
|
||||
falcon_qt202x_set_led(efx, SFN4112F_LINK_LED,
|
||||
state ? QUAKE_LED_ON : QUAKE_LED_OFF);
|
||||
int reg;
|
||||
|
||||
switch (mode) {
|
||||
case EFX_LED_OFF:
|
||||
reg = QUAKE_LED_OFF;
|
||||
break;
|
||||
case EFX_LED_ON:
|
||||
reg = QUAKE_LED_ON;
|
||||
break;
|
||||
default:
|
||||
reg = QUAKE_LED_RXLINK | QUAKE_LED_LINK_STAT;
|
||||
break;
|
||||
}
|
||||
|
||||
falcon_qt202x_set_led(efx, SFN4112F_LINK_LED, reg);
|
||||
}
|
||||
|
||||
static int sfn4112f_check_hw(struct efx_nic *efx)
|
||||
@ -703,7 +682,6 @@ static int sfn4112f_init(struct efx_nic *efx)
|
||||
efx->board_info.monitor = sfn4112f_check_hw;
|
||||
efx->board_info.init_leds = sfn4112f_init_leds;
|
||||
efx->board_info.set_id_led = sfn4112f_set_id_led;
|
||||
efx->board_info.blink = board_blink;
|
||||
efx->board_info.fini = efx_fini_lm87;
|
||||
return 0;
|
||||
}
|
||||
|
@ -388,6 +388,12 @@ struct efx_channel {
|
||||
|
||||
};
|
||||
|
||||
enum efx_led_mode {
|
||||
EFX_LED_OFF = 0,
|
||||
EFX_LED_ON = 1,
|
||||
EFX_LED_DEFAULT = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* struct efx_board - board information
|
||||
* @type: Board model type
|
||||
@ -395,13 +401,9 @@ struct efx_channel {
|
||||
* @minor: Minor rev. (0, 1, ...)
|
||||
* @init: Initialisation function
|
||||
* @init_leds: Sets up board LEDs. May be called repeatedly.
|
||||
* @set_id_led: Turns the identification LED on or off
|
||||
* @blink: Starts/stops blinking
|
||||
* @set_id_led: Set state of identifying LED or revert to automatic function
|
||||
* @monitor: Board-specific health check function
|
||||
* @fini: Cleanup function
|
||||
* @blink_state: Current blink state
|
||||
* @blink_resubmit: Blink timer resubmission flag
|
||||
* @blink_timer: Blink timer
|
||||
* @hwmon_client: I2C client for hardware monitor
|
||||
* @ioexp_client: I2C client for power/port control
|
||||
*/
|
||||
@ -414,13 +416,9 @@ struct efx_board {
|
||||
* have a separate init callback that happens later than
|
||||
* board init. */
|
||||
void (*init_leds)(struct efx_nic *efx);
|
||||
void (*set_id_led) (struct efx_nic *efx, bool state);
|
||||
void (*set_id_led) (struct efx_nic *efx, enum efx_led_mode mode);
|
||||
int (*monitor) (struct efx_nic *nic);
|
||||
void (*blink) (struct efx_nic *efx, bool start);
|
||||
void (*fini) (struct efx_nic *nic);
|
||||
bool blink_state;
|
||||
bool blink_resubmit;
|
||||
struct timer_list blink_timer;
|
||||
struct i2c_client *hwmon_client, *ioexp_client;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
extern struct efx_phy_operations falcon_sfx7101_phy_ops;
|
||||
extern struct efx_phy_operations falcon_sft9001_phy_ops;
|
||||
|
||||
extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
|
||||
extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
|
||||
|
||||
/* Wait for the PHY to boot. Return 0 on success, -EINVAL if the PHY failed
|
||||
* to boot due to corrupt flash, or some other negative error code. */
|
||||
|
@ -228,9 +228,6 @@ static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecm
|
||||
|
||||
static void qt202x_phy_fini(struct efx_nic *efx)
|
||||
{
|
||||
/* Clobber the LED if it was blinking */
|
||||
efx->board_info.blink(efx, false);
|
||||
|
||||
/* Free the context block */
|
||||
kfree(efx->phy_data);
|
||||
efx->phy_data = NULL;
|
||||
|
@ -613,21 +613,29 @@ static void tenxpress_phy_fini(struct efx_nic *efx)
|
||||
}
|
||||
|
||||
|
||||
/* Set the RX and TX LEDs and Link LED flashing. The other LEDs
|
||||
* (which probably aren't wired anyway) are left in AUTO mode */
|
||||
void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
|
||||
/* Override the RX, TX and link LEDs */
|
||||
void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
|
||||
{
|
||||
int reg;
|
||||
|
||||
if (blink)
|
||||
reg = (PMA_PMD_LED_FLASH << PMA_PMD_LED_TX_LBN) |
|
||||
(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) |
|
||||
(PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN);
|
||||
else
|
||||
switch (mode) {
|
||||
case EFX_LED_OFF:
|
||||
reg = (PMA_PMD_LED_OFF << PMA_PMD_LED_TX_LBN) |
|
||||
(PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
|
||||
(PMA_PMD_LED_OFF << PMA_PMD_LED_LINK_LBN);
|
||||
break;
|
||||
case EFX_LED_ON:
|
||||
reg = (PMA_PMD_LED_ON << PMA_PMD_LED_TX_LBN) |
|
||||
(PMA_PMD_LED_ON << PMA_PMD_LED_RX_LBN) |
|
||||
(PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
|
||||
break;
|
||||
default:
|
||||
if (efx->phy_type == PHY_TYPE_SFX7101)
|
||||
reg = SFX7101_PMA_PMD_LED_DEFAULT;
|
||||
else
|
||||
reg = SFT9001_PMA_PMD_LED_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user