summaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/tenxpress.c
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2009-11-28 06:34:05 +0100
committerDavid S. Miller <davem@davemloft.net>2009-11-29 08:58:50 +0100
commitfdaa9aed21c8c8b529f3c94a5ffa138bf3360b75 (patch)
tree6db7fd76481b3f87f0f4e94e1bd55c0624fba296 /drivers/net/sfc/tenxpress.c
parentvlan: support "loose binding" to the underlying network device (diff)
downloadlinux-fdaa9aed21c8c8b529f3c94a5ffa138bf3360b75.tar.xz
linux-fdaa9aed21c8c8b529f3c94a5ffa138bf3360b75.zip
sfc: Simplify PHY polling
Falcon can generate events for LASI interrupts from the PHY, but in practice we have never implemented this in reference designs. Instead we have polled, inserted the appropriate events, and then handled the events later. This is a waste of time and code. Instead, make PHY poll functions update the link state synchronously and report whether it changed. We can still make use of the LASI registers as a shortcut on the SFT9001. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/sfc/tenxpress.c69
1 files changed, 27 insertions, 42 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index e6232fe26072..1bd79650a00f 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -503,7 +503,6 @@ static void tenxpress_low_power(struct efx_nic *efx)
static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
- struct efx_link_state *link_state = &efx->link_state;
struct ethtool_cmd ecmd;
bool phy_mode_change, loop_reset;
@@ -544,53 +543,41 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
phy_data->loopback_mode = efx->loopback_mode;
phy_data->phy_mode = efx->phy_mode;
-
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- link_state->speed = 10000;
- link_state->fd = true;
- link_state->up = sfx7101_link_ok(efx);
- } else {
- efx->phy_op->get_settings(efx, &ecmd);
- link_state->speed = ecmd.speed;
- link_state->fd = ecmd.duplex == DUPLEX_FULL;
- link_state->up = sft9001_link_ok(efx, &ecmd);
- }
- link_state->fc = efx_mdio_get_pause(efx);
}
-/* Poll PHY for interrupt */
-static void tenxpress_phy_poll(struct efx_nic *efx)
+static void
+tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
+
+/* Poll for link state changes */
+static bool tenxpress_phy_poll(struct efx_nic *efx)
{
- struct tenxpress_phy_data *phy_data = efx->phy_data;
- struct efx_link_state *link_state = &efx->link_state;
- bool change = false;
+ struct efx_link_state old_state = efx->link_state;
if (efx->phy_type == PHY_TYPE_SFX7101) {
- bool link_ok = sfx7101_link_ok(efx);
- if (link_ok != link_state->up) {
- change = true;
- } else {
- unsigned int link_fc = efx_mdio_get_pause(efx);
- if (link_fc != link_state->fc)
- change = true;
- }
- sfx7101_check_bad_lp(efx, link_ok);
- } else if (efx->loopback_mode) {
- bool link_ok = sft9001_link_ok(efx, NULL);
- if (link_ok != link_state->up)
- change = true;
+ efx->link_state.up = sfx7101_link_ok(efx);
+ efx->link_state.speed = 10000;
+ efx->link_state.fd = true;
+ efx->link_state.fc = efx_mdio_get_pause(efx);
+
+ sfx7101_check_bad_lp(efx, efx->link_state.up);
} else {
- int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- MDIO_PMA_LASI_STAT);
- if (status & MDIO_PMA_LASI_LSALARM)
- change = true;
- }
+ struct ethtool_cmd ecmd;
- if (change)
- falcon_sim_phy_event(efx);
+ /* Check the LASI alarm first */
+ if (efx->loopback_mode == LOOPBACK_NONE &&
+ !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
+ MDIO_PMA_LASI_LSALARM))
+ return false;
- if (phy_data->phy_mode != PHY_MODE_NORMAL)
- return;
+ tenxpress_get_settings(efx, &ecmd);
+
+ efx->link_state.up = sft9001_link_ok(efx, &ecmd);
+ efx->link_state.speed = ecmd.speed;
+ efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
+ efx->link_state.fc = efx_mdio_get_pause(efx);
+ }
+
+ return !efx_link_state_equal(&efx->link_state, &old_state);
}
static void tenxpress_phy_fini(struct efx_nic *efx)
@@ -818,7 +805,6 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.reconfigure = tenxpress_phy_reconfigure,
.poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini,
- .clear_interrupt = efx_port_dummy_op_void,
.get_settings = tenxpress_get_settings,
.set_settings = tenxpress_set_settings,
.set_npage_adv = sfx7101_set_npage_adv,
@@ -835,7 +821,6 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
.reconfigure = tenxpress_phy_reconfigure,
.poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini,
- .clear_interrupt = efx_port_dummy_op_void,
.get_settings = tenxpress_get_settings,
.set_settings = tenxpress_set_settings,
.set_npage_adv = sft9001_set_npage_adv,