aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-11-25 11:12:01 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-26 18:59:43 -0500
commit9007b9fa368b172e6b9a985899080fbebb7d3204 (patch)
tree3d725a55e193fe9763fcd514a6b4246eae8da957 /drivers/net/sfc
parentfe75820b99ff2de713de23252432f0f9d0ca1d35 (diff)
sfc: Simplify XMAC link polling
From: Steve Hodgson <shodgson@solarflare.com> Only the XMAC on Falcon needs help from the driver to poll and reset the MAC-PHY link (XAUI); GMII is a simple parallel bus and on later NICs firmware takes care of the XAUI link. Also, an XMAC interrupt currently schedules a work item which simply clears a flag (efx_nic::mac_up) to be checked by the regular monitor (or the next link reconfiguration, if that is sooner). Rename the flag to xmac_poll_required, changing its sense. Remove the needless indirection and just set the flag immediately. Call falcon_xmac_poll() directly where required. Add a new generic operation mac_op::check_fault to check the link outside of regular monitoring, as required during self-tests. (Note that this leaves us with an unused work item, but we will immediately have another use for it.) Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c5
-rw-r--r--drivers/net/sfc/falcon.c7
-rw-r--r--drivers/net/sfc/falcon.h2
-rw-r--r--drivers/net/sfc/falcon_boards.c4
-rw-r--r--drivers/net/sfc/falcon_gmac.c8
-rw-r--r--drivers/net/sfc/falcon_xmac.c50
-rw-r--r--drivers/net/sfc/net_driver.h10
-rw-r--r--drivers/net/sfc/selftest.c9
8 files changed, 41 insertions, 54 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index d17cea9f4e88..15616dd9ed41 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -693,8 +693,6 @@ static void efx_mac_work(struct work_struct *data)
693 struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); 693 struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
694 694
695 mutex_lock(&efx->mac_lock); 695 mutex_lock(&efx->mac_lock);
696 if (efx->port_enabled)
697 efx->mac_op->irq(efx);
698 mutex_unlock(&efx->mac_lock); 696 mutex_unlock(&efx->mac_lock);
699} 697}
700 698
@@ -774,7 +772,6 @@ static void efx_start_port(struct efx_nic *efx)
774 mutex_lock(&efx->mac_lock); 772 mutex_lock(&efx->mac_lock);
775 efx->port_enabled = true; 773 efx->port_enabled = true;
776 __efx_reconfigure_port(efx); 774 __efx_reconfigure_port(efx);
777 efx->mac_op->irq(efx);
778 mutex_unlock(&efx->mac_lock); 775 mutex_unlock(&efx->mac_lock);
779} 776}
780 777
@@ -1903,8 +1900,6 @@ void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
1903 1900
1904static struct efx_mac_operations efx_dummy_mac_operations = { 1901static struct efx_mac_operations efx_dummy_mac_operations = {
1905 .reconfigure = efx_port_dummy_op_void, 1902 .reconfigure = efx_port_dummy_op_void,
1906 .poll = efx_port_dummy_op_void,
1907 .irq = efx_port_dummy_op_void,
1908}; 1903};
1909 1904
1910static struct efx_phy_operations efx_dummy_phy_operations = { 1905static struct efx_phy_operations efx_dummy_phy_operations = {
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index c43c5e6f077b..fac534a274c8 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -900,7 +900,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
900 900
901 if ((falcon_rev(efx) >= FALCON_REV_B0) && 901 if ((falcon_rev(efx) >= FALCON_REV_B0) &&
902 EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) { 902 EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
903 queue_work(efx->workqueue, &efx->mac_work); 903 efx->xmac_poll_required = true;
904 handled = true; 904 handled = true;
905 } 905 }
906 906
@@ -2251,7 +2251,7 @@ int falcon_switch_mac(struct efx_nic *efx)
2251 2251
2252 EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); 2252 EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
2253 /* Not all macs support a mac-level link state */ 2253 /* Not all macs support a mac-level link state */
2254 efx->mac_up = true; 2254 efx->xmac_poll_required = false;
2255 2255
2256 rc = falcon_reset_macs(efx); 2256 rc = falcon_reset_macs(efx);
2257out: 2257out:
@@ -2624,7 +2624,8 @@ void falcon_monitor(struct efx_nic *efx)
2624 falcon_sim_phy_event(efx); 2624 falcon_sim_phy_event(efx);
2625 } 2625 }
2626 efx->phy_op->poll(efx); 2626 efx->phy_op->poll(efx);
2627 efx->mac_op->poll(efx); 2627 if (EFX_IS10G(efx))
2628 falcon_poll_xmac(efx);
2628} 2629}
2629 2630
2630/* Zeroes out the SRAM contents. This routine must be called in 2631/* Zeroes out the SRAM contents. This routine must be called in
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 05e51c2a6d8a..9ae1b6c8474e 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -209,4 +209,6 @@ extern int falcon_test_registers(struct efx_nic *efx);
209extern void falcon_generate_event(struct efx_channel *channel, 209extern void falcon_generate_event(struct efx_channel *channel,
210 efx_qword_t *event); 210 efx_qword_t *event);
211 211
212extern void falcon_poll_xmac(struct efx_nic *efx);
213
212#endif /* EFX_FALCON_H */ 214#endif /* EFX_FALCON_H */
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index 72d1c7834e6b..da750959c61a 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -380,7 +380,7 @@ static int sfe4001_check_hw(struct efx_nic *efx)
380 s32 status; 380 s32 status;
381 381
382 /* If XAUI link is up then do not monitor */ 382 /* If XAUI link is up then do not monitor */
383 if (EFX_WORKAROUND_7884(efx) && efx->mac_up) 383 if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
384 return 0; 384 return 0;
385 385
386 /* Check the powered status of the PHY. Lack of power implies that 386 /* Check the powered status of the PHY. Lack of power implies that
@@ -468,7 +468,7 @@ static int sfn4111t_check_hw(struct efx_nic *efx)
468 s32 status; 468 s32 status;
469 469
470 /* If XAUI link is up then do not monitor */ 470 /* If XAUI link is up then do not monitor */
471 if (EFX_WORKAROUND_7884(efx) && efx->mac_up) 471 if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
472 return 0; 472 return 0;
473 473
474 /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */ 474 /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
index 2aeb3fc02786..66d499cc23f2 100644
--- a/drivers/net/sfc/falcon_gmac.c
+++ b/drivers/net/sfc/falcon_gmac.c
@@ -216,9 +216,13 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
216 mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; 216 mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
217} 217}
218 218
219static bool falcon_gmac_check_fault(struct efx_nic *efx)
220{
221 return false;
222}
223
219struct efx_mac_operations falcon_gmac_operations = { 224struct efx_mac_operations falcon_gmac_operations = {
220 .reconfigure = falcon_reconfigure_gmac, 225 .reconfigure = falcon_reconfigure_gmac,
221 .update_stats = falcon_update_stats_gmac, 226 .update_stats = falcon_update_stats_gmac,
222 .irq = efx_port_dummy_op_void, 227 .check_fault = falcon_gmac_check_fault,
223 .poll = efx_port_dummy_op_void,
224}; 228};
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index e57545de60ff..784260f63d4c 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -98,7 +98,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
98 98
99 /* We can only use this interrupt to signal the negative edge of 99 /* We can only use this interrupt to signal the negative edge of
100 * xaui_align [we have to poll the positive edge]. */ 100 * xaui_align [we have to poll the positive edge]. */
101 if (!efx->mac_up) 101 if (efx->xmac_poll_required)
102 return; 102 return;
103 103
104 /* Flush the ISR */ 104 /* Flush the ISR */
@@ -243,29 +243,35 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
243} 243}
244 244
245 245
246/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails 246/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
247 * to come back up. Bash it until it comes back up */ 247static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
248static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
249{ 248{
250 efx->mac_up = falcon_xaui_link_ok(efx); 249 bool mac_up = falcon_xaui_link_ok(efx);
251 250
252 if ((efx->loopback_mode == LOOPBACK_NETWORK) || 251 if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
253 efx_phy_mode_disabled(efx->phy_mode)) 252 efx_phy_mode_disabled(efx->phy_mode))
254 /* XAUI link is expected to be down */ 253 /* XAUI link is expected to be down */
255 return; 254 return mac_up;
256 255
257 falcon_stop_nic_stats(efx); 256 falcon_stop_nic_stats(efx);
258 257
259 while (!efx->mac_up && tries) { 258 while (!mac_up && tries) {
260 EFX_LOG(efx, "bashing xaui\n"); 259 EFX_LOG(efx, "bashing xaui\n");
261 falcon_reset_xaui(efx); 260 falcon_reset_xaui(efx);
262 udelay(200); 261 udelay(200);
263 262
264 efx->mac_up = falcon_xaui_link_ok(efx); 263 mac_up = falcon_xaui_link_ok(efx);
265 --tries; 264 --tries;
266 } 265 }
267 266
268 falcon_start_nic_stats(efx); 267 falcon_start_nic_stats(efx);
268
269 return mac_up;
270}
271
272static bool falcon_xmac_check_fault(struct efx_nic *efx)
273{
274 return !falcon_check_xaui_link_up(efx, 5);
269} 275}
270 276
271static void falcon_reconfigure_xmac(struct efx_nic *efx) 277static void falcon_reconfigure_xmac(struct efx_nic *efx)
@@ -277,7 +283,7 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx)
277 283
278 falcon_reconfigure_mac_wrapper(efx); 284 falcon_reconfigure_mac_wrapper(efx);
279 285
280 falcon_check_xaui_link_up(efx, 5); 286 efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5);
281 falcon_mask_status_intr(efx, true); 287 falcon_mask_status_intr(efx, true);
282} 288}
283 289
@@ -341,35 +347,19 @@ static void falcon_update_stats_xmac(struct efx_nic *efx)
341 mac_stats->rx_control * 64); 347 mac_stats->rx_control * 64);
342} 348}
343 349
344static void falcon_xmac_irq(struct efx_nic *efx) 350void falcon_poll_xmac(struct efx_nic *efx)
345{
346 /* The XGMII link has a transient fault, which indicates either:
347 * - there's a transient xgmii fault
348 * - falcon's end of the xaui link may need a kick
349 * - the wire-side link may have gone down, but the lasi/poll()
350 * hasn't noticed yet.
351 *
352 * We only want to even bother polling XAUI if we're confident it's
353 * not (1) or (3). In both cases, the only reliable way to spot this
354 * is to wait a bit. We do this here by forcing the mac link state
355 * to down, and waiting for the mac poll to come round and check
356 */
357 efx->mac_up = false;
358}
359
360static void falcon_poll_xmac(struct efx_nic *efx)
361{ 351{
362 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || efx->mac_up) 352 if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up ||
353 !efx->xmac_poll_required)
363 return; 354 return;
364 355
365 falcon_mask_status_intr(efx, false); 356 falcon_mask_status_intr(efx, false);
366 falcon_check_xaui_link_up(efx, 1); 357 efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1);
367 falcon_mask_status_intr(efx, true); 358 falcon_mask_status_intr(efx, true);
368} 359}
369 360
370struct efx_mac_operations falcon_xmac_operations = { 361struct efx_mac_operations falcon_xmac_operations = {
371 .reconfigure = falcon_reconfigure_xmac, 362 .reconfigure = falcon_reconfigure_xmac,
372 .update_stats = falcon_update_stats_xmac, 363 .update_stats = falcon_update_stats_xmac,
373 .irq = falcon_xmac_irq, 364 .check_fault = falcon_xmac_check_fault,
374 .poll = falcon_poll_xmac,
375}; 365};
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 262aeabdcab7..cc1a97b0a0d3 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -507,14 +507,12 @@ struct efx_link_state {
507 * struct efx_mac_operations - Efx MAC operations table 507 * struct efx_mac_operations - Efx MAC operations table
508 * @reconfigure: Reconfigure MAC. Serialised by the mac_lock 508 * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
509 * @update_stats: Update statistics 509 * @update_stats: Update statistics
510 * @irq: Hardware MAC event callback. Serialised by the mac_lock 510 * @check_fault: Check fault state. True if fault present.
511 * @poll: Poll for hardware state. Serialised by the mac_lock
512 */ 511 */
513struct efx_mac_operations { 512struct efx_mac_operations {
514 void (*reconfigure) (struct efx_nic *efx); 513 void (*reconfigure) (struct efx_nic *efx);
515 void (*update_stats) (struct efx_nic *efx); 514 void (*update_stats) (struct efx_nic *efx);
516 void (*irq) (struct efx_nic *efx); 515 bool (*check_fault)(struct efx_nic *efx);
517 void (*poll) (struct efx_nic *efx);
518}; 516};
519 517
520/** 518/**
@@ -725,7 +723,7 @@ union efx_multicast_hash {
725 * @phy_data: PHY private data (including PHY-specific stats) 723 * @phy_data: PHY private data (including PHY-specific stats)
726 * @mdio: PHY MDIO interface 724 * @mdio: PHY MDIO interface
727 * @phy_mode: PHY operating mode. Serialised by @mac_lock. 725 * @phy_mode: PHY operating mode. Serialised by @mac_lock.
728 * @mac_up: MAC link state 726 * @xmac_poll_required: XMAC link state needs polling
729 * @link_state: Current state of the link 727 * @link_state: Current state of the link
730 * @n_link_state_changes: Number of times the link has changed state 728 * @n_link_state_changes: Number of times the link has changed state
731 * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. 729 * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
@@ -810,7 +808,7 @@ struct efx_nic {
810 struct mdio_if_info mdio; 808 struct mdio_if_info mdio;
811 enum efx_phy_mode phy_mode; 809 enum efx_phy_mode phy_mode;
812 810
813 bool mac_up; 811 bool xmac_poll_required;
814 struct efx_link_state link_state; 812 struct efx_link_state link_state;
815 unsigned int n_link_state_changes; 813 unsigned int n_link_state_changes;
816 814
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 63ff295334e4..23e646a6c2cf 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -610,13 +610,10 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
610 flush_workqueue(efx->workqueue); 610 flush_workqueue(efx->workqueue);
611 rmb(); 611 rmb();
612 612
613 /* We need both the phy and xaui links to be ok. 613 /* We need both the PHY and MAC-PHY links to be OK */
614 * rather than relying on the falcon_xmac irq/poll
615 * regime, just poll xaui directly */
616 link_up = efx->link_state.up; 614 link_up = efx->link_state.up;
617 if (link_up && EFX_IS10G(efx) && 615 if (link_up)
618 !falcon_xaui_link_ok(efx)) 616 link_up = !efx->mac_op->check_fault(efx);
619 link_up = false;
620 617
621 } while ((++count < 20) && !link_up); 618 } while ((++count < 20) && !link_up);
622 619