aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/falcon.c
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2009-11-28 00:34:05 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-29 02:58:50 -0500
commitfdaa9aed21c8c8b529f3c94a5ffa138bf3360b75 (patch)
tree6db7fd76481b3f87f0f4e94e1bd55c0624fba296 /drivers/net/sfc/falcon.c
parent5e7565930524410f097f5b04f8aba663089a6ffc (diff)
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 'drivers/net/sfc/falcon.c')
-rw-r--r--drivers/net/sfc/falcon.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index e26043eb01b5..e16faad70283 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -893,8 +893,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
893 if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) || 893 if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
894 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) || 894 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
895 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) { 895 EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) {
896 efx->phy_op->clear_interrupt(efx); 896 /* Ignored */
897 queue_work(efx->workqueue, &efx->phy_work);
898 handled = true; 897 handled = true;
899 } 898 }
900 899
@@ -1140,20 +1139,6 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
1140 falcon_generate_event(channel, &test_event); 1139 falcon_generate_event(channel, &test_event);
1141} 1140}
1142 1141
1143void falcon_sim_phy_event(struct efx_nic *efx)
1144{
1145 efx_qword_t phy_event;
1146
1147 EFX_POPULATE_QWORD_1(phy_event, FSF_AZ_EV_CODE,
1148 FSE_AZ_EV_CODE_GLOBAL_EV);
1149 if (EFX_IS10G(efx))
1150 EFX_SET_QWORD_FIELD(phy_event, FSF_AB_GLB_EV_XG_PHY0_INTR, 1);
1151 else
1152 EFX_SET_QWORD_FIELD(phy_event, FSF_AB_GLB_EV_G_PHY0_INTR, 1);
1153
1154 falcon_generate_event(&efx->channel[0], &phy_event);
1155}
1156
1157/************************************************************************** 1142/**************************************************************************
1158 * 1143 *
1159 * Flush handling 1144 * Flush handling
@@ -2063,6 +2048,25 @@ static void falcon_stats_timer_func(unsigned long context)
2063 spin_unlock(&efx->stats_lock); 2048 spin_unlock(&efx->stats_lock);
2064} 2049}
2065 2050
2051static bool falcon_loopback_link_poll(struct efx_nic *efx)
2052{
2053 struct efx_link_state old_state = efx->link_state;
2054
2055 WARN_ON(!mutex_is_locked(&efx->mac_lock));
2056 WARN_ON(!LOOPBACK_INTERNAL(efx));
2057
2058 efx->link_state.fd = true;
2059 efx->link_state.fc = efx->wanted_fc;
2060 efx->link_state.up = true;
2061
2062 if (efx->loopback_mode == LOOPBACK_GMAC)
2063 efx->link_state.speed = 1000;
2064 else
2065 efx->link_state.speed = 10000;
2066
2067 return !efx_link_state_equal(&efx->link_state, &old_state);
2068}
2069
2066/************************************************************************** 2070/**************************************************************************
2067 * 2071 *
2068 * PHY access via GMII 2072 * PHY access via GMII
@@ -2225,15 +2229,6 @@ int falcon_switch_mac(struct efx_nic *efx)
2225 /* Don't try to fetch MAC stats while we're switching MACs */ 2229 /* Don't try to fetch MAC stats while we're switching MACs */
2226 falcon_stop_nic_stats(efx); 2230 falcon_stop_nic_stats(efx);
2227 2231
2228 /* Internal loopbacks override the phy speed setting */
2229 if (efx->loopback_mode == LOOPBACK_GMAC) {
2230 efx->link_state.speed = 1000;
2231 efx->link_state.fd = true;
2232 } else if (LOOPBACK_INTERNAL(efx)) {
2233 efx->link_state.speed = 10000;
2234 efx->link_state.fd = true;
2235 }
2236
2237 WARN_ON(!mutex_is_locked(&efx->mac_lock)); 2232 WARN_ON(!mutex_is_locked(&efx->mac_lock));
2238 efx->mac_op = (EFX_IS10G(efx) ? 2233 efx->mac_op = (EFX_IS10G(efx) ?
2239 &falcon_xmac_operations : &falcon_gmac_operations); 2234 &falcon_xmac_operations : &falcon_gmac_operations);
@@ -2610,16 +2605,36 @@ fail5:
2610 2605
2611void falcon_monitor(struct efx_nic *efx) 2606void falcon_monitor(struct efx_nic *efx)
2612{ 2607{
2608 bool link_changed;
2613 int rc; 2609 int rc;
2614 2610
2611 BUG_ON(!mutex_is_locked(&efx->mac_lock));
2612
2615 rc = falcon_board(efx)->type->monitor(efx); 2613 rc = falcon_board(efx)->type->monitor(efx);
2616 if (rc) { 2614 if (rc) {
2617 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", 2615 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
2618 (rc == -ERANGE) ? "reported fault" : "failed"); 2616 (rc == -ERANGE) ? "reported fault" : "failed");
2619 efx->phy_mode |= PHY_MODE_LOW_POWER; 2617 efx->phy_mode |= PHY_MODE_LOW_POWER;
2620 falcon_sim_phy_event(efx); 2618 __efx_reconfigure_port(efx);
2621 } 2619 }
2622 efx->phy_op->poll(efx); 2620
2621 if (LOOPBACK_INTERNAL(efx))
2622 link_changed = falcon_loopback_link_poll(efx);
2623 else
2624 link_changed = efx->phy_op->poll(efx);
2625
2626 if (link_changed) {
2627 falcon_stop_nic_stats(efx);
2628 falcon_deconfigure_mac_wrapper(efx);
2629
2630 falcon_switch_mac(efx);
2631 efx->mac_op->reconfigure(efx);
2632
2633 falcon_start_nic_stats(efx);
2634
2635 efx_link_status_changed(efx);
2636 }
2637
2623 if (EFX_IS10G(efx)) 2638 if (EFX_IS10G(efx))
2624 falcon_poll_xmac(efx); 2639 falcon_poll_xmac(efx);
2625} 2640}