diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2009-11-25 11:12:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-26 18:59:43 -0500 |
commit | 9007b9fa368b172e6b9a985899080fbebb7d3204 (patch) | |
tree | 3d725a55e193fe9763fcd514a6b4246eae8da957 /drivers/net | |
parent | fe75820b99ff2de713de23252432f0f9d0ca1d35 (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')
-rw-r--r-- | drivers/net/sfc/efx.c | 5 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 7 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_boards.c | 4 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_gmac.c | 8 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 50 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 10 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 9 |
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 | ||
1904 | static struct efx_mac_operations efx_dummy_mac_operations = { | 1901 | static 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 | ||
1910 | static struct efx_phy_operations efx_dummy_phy_operations = { | 1905 | static 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); |
2257 | out: | 2257 | out: |
@@ -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); | |||
209 | extern void falcon_generate_event(struct efx_channel *channel, | 209 | extern void falcon_generate_event(struct efx_channel *channel, |
210 | efx_qword_t *event); | 210 | efx_qword_t *event); |
211 | 211 | ||
212 | extern 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 | ||
219 | static bool falcon_gmac_check_fault(struct efx_nic *efx) | ||
220 | { | ||
221 | return false; | ||
222 | } | ||
223 | |||
219 | struct efx_mac_operations falcon_gmac_operations = { | 224 | struct 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 */ | 247 | static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) |
248 | static 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 | |||
272 | static bool falcon_xmac_check_fault(struct efx_nic *efx) | ||
273 | { | ||
274 | return !falcon_check_xaui_link_up(efx, 5); | ||
269 | } | 275 | } |
270 | 276 | ||
271 | static void falcon_reconfigure_xmac(struct efx_nic *efx) | 277 | static 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 | ||
344 | static void falcon_xmac_irq(struct efx_nic *efx) | 350 | void 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 | |||
360 | static 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 | ||
370 | struct efx_mac_operations falcon_xmac_operations = { | 361 | struct 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 | */ |
513 | struct efx_mac_operations { | 512 | struct 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 | ||