Commit 398468ed authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dcf477b2
...@@ -1890,7 +1890,9 @@ int efx_port_dummy_op_int(struct efx_nic *efx) ...@@ -1890,7 +1890,9 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
return 0; return 0;
} }
void efx_port_dummy_op_void(struct efx_nic *efx) {} 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 = { static struct efx_mac_operations efx_dummy_mac_operations = {
.reconfigure = efx_port_dummy_op_void, .reconfigure = efx_port_dummy_op_void,
...@@ -1909,9 +1911,8 @@ static struct efx_phy_operations efx_dummy_phy_operations = { ...@@ -1909,9 +1911,8 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
static struct efx_board efx_dummy_board_info = { static struct efx_board efx_dummy_board_info = {
.init = efx_port_dummy_op_int, .init = efx_port_dummy_op_int,
.init_leds = efx_port_dummy_op_void, .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, .monitor = efx_port_dummy_op_int,
.blink = efx_port_dummy_op_blink,
.fini = efx_port_dummy_op_void, .fini = efx_port_dummy_op_void,
}; };
......
...@@ -69,7 +69,8 @@ extern void efx_hex_dump(const u8 *, unsigned int, const char *); ...@@ -69,7 +69,8 @@ extern void efx_hex_dump(const u8 *, unsigned int, const char *);
/* Dummy PHY ops for PHY drivers */ /* Dummy PHY ops for PHY drivers */
extern int efx_port_dummy_op_int(struct efx_nic *efx); 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_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 */ /* MTD */
#ifdef CONFIG_SFC_MTD #ifdef CONFIG_SFC_MTD
......
...@@ -187,13 +187,15 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count) ...@@ -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); struct efx_nic *efx = netdev_priv(net_dev);
efx->board_info.blink(efx, 1); do {
set_current_state(TASK_INTERRUPTIBLE); efx->board_info.set_id_led(efx, EFX_LED_ON);
if (count) schedule_timeout_interruptible(HZ / 2);
schedule_timeout(count * HZ);
else efx->board_info.set_id_led(efx, EFX_LED_OFF);
schedule(); schedule_timeout_interruptible(HZ / 2);
efx->board_info.blink(efx, 0); } while (!signal_pending(current) && --count != 0);
efx->board_info.set_id_led(efx, EFX_LED_DEFAULT);
return 0; return 0;
} }
......
...@@ -29,40 +29,6 @@ ...@@ -29,40 +29,6 @@
#define FALCON_BOARD_SFN4111T 0x51 #define FALCON_BOARD_SFN4111T 0x51
#define FALCON_BOARD_SFN4112F 0x52 #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 * Support for LM87 sensor chip used on several boards
*/ */
...@@ -469,7 +435,7 @@ static int sfe4001_init(struct efx_nic *efx) ...@@ -469,7 +435,7 @@ static int sfe4001_init(struct efx_nic *efx)
/* 10Xpress has fixed-function LED pins, so there is no board-specific /* 10Xpress has fixed-function LED pins, so there is no board-specific
* blink code. */ * 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.monitor = sfe4001_check_hw;
efx->board_info.fini = sfe4001_fini; efx->board_info.fini = sfe4001_fini;
...@@ -546,7 +512,7 @@ static int sfn4111t_init(struct efx_nic *efx) ...@@ -546,7 +512,7 @@ static int sfn4111t_init(struct efx_nic *efx)
if (!efx->board_info.hwmon_client) if (!efx->board_info.hwmon_client)
return -EIO; 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.monitor = sfn4111t_check_hw;
efx->board_info.fini = sfn4111t_fini; efx->board_info.fini = sfn4111t_fini;
...@@ -619,10 +585,11 @@ static void sfe4002_init_leds(struct efx_nic *efx) ...@@ -619,10 +585,11 @@ static void sfe4002_init_leds(struct efx_nic *efx)
falcon_qt202x_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF); 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 : falcon_qt202x_set_led(
QUAKE_LED_OFF); efx, SFE4002_FAULT_LED,
(mode == EFX_LED_ON) ? QUAKE_LED_ON : QUAKE_LED_OFF);
} }
static int sfe4002_check_hw(struct efx_nic *efx) static int sfe4002_check_hw(struct efx_nic *efx)
...@@ -644,7 +611,6 @@ static int sfe4002_init(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.monitor = sfe4002_check_hw;
efx->board_info.init_leds = sfe4002_init_leds; efx->board_info.init_leds = sfe4002_init_leds;
efx->board_info.set_id_led = sfe4002_set_id_led; efx->board_info.set_id_led = sfe4002_set_id_led;
efx->board_info.blink = board_blink;
efx->board_info.fini = efx_fini_lm87; efx->board_info.fini = efx_fini_lm87;
return 0; return 0;
} }
...@@ -683,10 +649,23 @@ static void sfn4112f_init_leds(struct efx_nic *efx) ...@@ -683,10 +649,23 @@ static void sfn4112f_init_leds(struct efx_nic *efx)
QUAKE_LED_RXLINK | QUAKE_LED_LINK_STAT); 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, int reg;
state ? QUAKE_LED_ON : QUAKE_LED_OFF);
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) static int sfn4112f_check_hw(struct efx_nic *efx)
...@@ -703,7 +682,6 @@ static int sfn4112f_init(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.monitor = sfn4112f_check_hw;
efx->board_info.init_leds = sfn4112f_init_leds; efx->board_info.init_leds = sfn4112f_init_leds;
efx->board_info.set_id_led = sfn4112f_set_id_led; efx->board_info.set_id_led = sfn4112f_set_id_led;
efx->board_info.blink = board_blink;
efx->board_info.fini = efx_fini_lm87; efx->board_info.fini = efx_fini_lm87;
return 0; return 0;
} }
......
...@@ -388,6 +388,12 @@ struct efx_channel { ...@@ -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 * struct efx_board - board information
* @type: Board model type * @type: Board model type
...@@ -395,13 +401,9 @@ struct efx_channel { ...@@ -395,13 +401,9 @@ struct efx_channel {
* @minor: Minor rev. (0, 1, ...) * @minor: Minor rev. (0, 1, ...)
* @init: Initialisation function * @init: Initialisation function
* @init_leds: Sets up board LEDs. May be called repeatedly. * @init_leds: Sets up board LEDs. May be called repeatedly.
* @set_id_led: Turns the identification LED on or off * @set_id_led: Set state of identifying LED or revert to automatic function
* @blink: Starts/stops blinking
* @monitor: Board-specific health check function * @monitor: Board-specific health check function
* @fini: Cleanup 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 * @hwmon_client: I2C client for hardware monitor
* @ioexp_client: I2C client for power/port control * @ioexp_client: I2C client for power/port control
*/ */
...@@ -414,13 +416,9 @@ struct efx_board { ...@@ -414,13 +416,9 @@ struct efx_board {
* have a separate init callback that happens later than * have a separate init callback that happens later than
* board init. */ * board init. */
void (*init_leds)(struct efx_nic *efx); 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); int (*monitor) (struct efx_nic *nic);
void (*blink) (struct efx_nic *efx, bool start);
void (*fini) (struct efx_nic *nic); void (*fini) (struct efx_nic *nic);
bool blink_state;
bool blink_resubmit;
struct timer_list blink_timer;
struct i2c_client *hwmon_client, *ioexp_client; struct i2c_client *hwmon_client, *ioexp_client;
}; };
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
extern struct efx_phy_operations falcon_sfx7101_phy_ops; extern struct efx_phy_operations falcon_sfx7101_phy_ops;
extern struct efx_phy_operations falcon_sft9001_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 /* 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. */ * 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 ...@@ -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) 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 */ /* Free the context block */
kfree(efx->phy_data); kfree(efx->phy_data);
efx->phy_data = NULL; efx->phy_data = NULL;
......
...@@ -613,21 +613,29 @@ static void tenxpress_phy_fini(struct efx_nic *efx) ...@@ -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 /* Override the RX, TX and link LEDs */
* (which probably aren't wired anyway) are left in AUTO mode */ void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
{ {
int reg; int reg;
if (blink) switch (mode) {
reg = (PMA_PMD_LED_FLASH << PMA_PMD_LED_TX_LBN) | case EFX_LED_OFF:
(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) | reg = (PMA_PMD_LED_OFF << PMA_PMD_LED_TX_LBN) |
(PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN); (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
else (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) if (efx->phy_type == PHY_TYPE_SFX7101)
reg = SFX7101_PMA_PMD_LED_DEFAULT; reg = SFX7101_PMA_PMD_LED_DEFAULT;
else else
reg = SFT9001_PMA_PMD_LED_DEFAULT; reg = SFT9001_PMA_PMD_LED_DEFAULT;
break;
}
efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg); efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment