aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-12-13 00:59:24 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-13 00:59:24 -0500
commit766ca0fa6bf1600bdf4bc7726c74f14c8455c6b8 (patch)
treeb1ea2df622753f2493b1053fda21c0db3f18a043
parent04cc8cacb01c09fba2297faf1477cd570ba43f0b (diff)
sfc: Rework MAC, PHY and board event handling
From: Steve Hodgson <shodgson@solarflare.com> MAC, PHY and board events may be separately enabled and signalled. Our current arrangement of chaining the polling functions can result in events being missed. Change them to be more independent. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/sfc/efx.c63
-rw-r--r--drivers/net/sfc/falcon.c20
-rw-r--r--drivers/net/sfc/falcon_gmac.c8
-rw-r--r--drivers/net/sfc/falcon_hwdefs.h2
-rw-r--r--drivers/net/sfc/falcon_xmac.c42
-rw-r--r--drivers/net/sfc/net_driver.h24
-rw-r--r--drivers/net/sfc/selftest.c6
-rw-r--r--drivers/net/sfc/tenxpress.c44
-rw-r--r--drivers/net/sfc/xfp_phy.c16
9 files changed, 111 insertions, 114 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7214ea6f7e1d..ce1c7d3cd12e 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -612,10 +612,9 @@ void efx_reconfigure_port(struct efx_nic *efx)
612/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all() 612/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
613 * we don't efx_reconfigure_port() if the port is disabled. Care is taken 613 * we don't efx_reconfigure_port() if the port is disabled. Care is taken
614 * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */ 614 * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
615static void efx_reconfigure_work(struct work_struct *data) 615static void efx_phy_work(struct work_struct *data)
616{ 616{
617 struct efx_nic *efx = container_of(data, struct efx_nic, 617 struct efx_nic *efx = container_of(data, struct efx_nic, phy_work);
618 reconfigure_work);
619 618
620 mutex_lock(&efx->mac_lock); 619 mutex_lock(&efx->mac_lock);
621 if (efx->port_enabled) 620 if (efx->port_enabled)
@@ -623,6 +622,16 @@ static void efx_reconfigure_work(struct work_struct *data)
623 mutex_unlock(&efx->mac_lock); 622 mutex_unlock(&efx->mac_lock);
624} 623}
625 624
625static void efx_mac_work(struct work_struct *data)
626{
627 struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
628
629 mutex_lock(&efx->mac_lock);
630 if (efx->port_enabled)
631 efx->mac_op->irq(efx);
632 mutex_unlock(&efx->mac_lock);
633}
634
626static int efx_probe_port(struct efx_nic *efx) 635static int efx_probe_port(struct efx_nic *efx)
627{ 636{
628 int rc; 637 int rc;
@@ -688,7 +697,7 @@ fail:
688 697
689/* Allow efx_reconfigure_port() to be scheduled, and close the window 698/* Allow efx_reconfigure_port() to be scheduled, and close the window
690 * between efx_stop_port and efx_flush_all whereby a previously scheduled 699 * between efx_stop_port and efx_flush_all whereby a previously scheduled
691 * efx_reconfigure_port() may have been cancelled */ 700 * efx_phy_work()/efx_mac_work() may have been cancelled */
692static void efx_start_port(struct efx_nic *efx) 701static void efx_start_port(struct efx_nic *efx)
693{ 702{
694 EFX_LOG(efx, "start port\n"); 703 EFX_LOG(efx, "start port\n");
@@ -697,13 +706,14 @@ static void efx_start_port(struct efx_nic *efx)
697 mutex_lock(&efx->mac_lock); 706 mutex_lock(&efx->mac_lock);
698 efx->port_enabled = true; 707 efx->port_enabled = true;
699 __efx_reconfigure_port(efx); 708 __efx_reconfigure_port(efx);
709 efx->mac_op->irq(efx);
700 mutex_unlock(&efx->mac_lock); 710 mutex_unlock(&efx->mac_lock);
701} 711}
702 712
703/* Prevent efx_reconfigure_work and efx_monitor() from executing, and 713/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing,
704 * efx_set_multicast_list() from scheduling efx_reconfigure_work. 714 * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work
705 * efx_reconfigure_work can still be scheduled via NAPI processing 715 * and efx_mac_work may still be scheduled via NAPI processing until
706 * until efx_flush_all() is called */ 716 * efx_flush_all() is called */
707static void efx_stop_port(struct efx_nic *efx) 717static void efx_stop_port(struct efx_nic *efx)
708{ 718{
709 EFX_LOG(efx, "stop port\n"); 719 EFX_LOG(efx, "stop port\n");
@@ -1094,7 +1104,8 @@ static void efx_flush_all(struct efx_nic *efx)
1094 cancel_delayed_work_sync(&rx_queue->work); 1104 cancel_delayed_work_sync(&rx_queue->work);
1095 1105
1096 /* Stop scheduled port reconfigurations */ 1106 /* Stop scheduled port reconfigurations */
1097 cancel_work_sync(&efx->reconfigure_work); 1107 cancel_work_sync(&efx->mac_work);
1108 cancel_work_sync(&efx->phy_work);
1098 1109
1099} 1110}
1100 1111
@@ -1131,7 +1142,7 @@ static void efx_stop_all(struct efx_nic *efx)
1131 * window to loose phy events */ 1142 * window to loose phy events */
1132 efx_stop_port(efx); 1143 efx_stop_port(efx);
1133 1144
1134 /* Flush reconfigure_work, refill_workqueue, monitor_work */ 1145 /* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */
1135 efx_flush_all(efx); 1146 efx_flush_all(efx);
1136 1147
1137 /* Isolate the MAC from the TX and RX engines, so that queue 1148 /* Isolate the MAC from the TX and RX engines, so that queue
@@ -1203,24 +1214,31 @@ static void efx_monitor(struct work_struct *data)
1203{ 1214{
1204 struct efx_nic *efx = container_of(data, struct efx_nic, 1215 struct efx_nic *efx = container_of(data, struct efx_nic,
1205 monitor_work.work); 1216 monitor_work.work);
1217 int rc;
1206 1218
1207 EFX_TRACE(efx, "hardware monitor executing on CPU %d\n", 1219 EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
1208 raw_smp_processor_id()); 1220 raw_smp_processor_id());
1209 1221
1210
1211 /* If the mac_lock is already held then it is likely a port 1222 /* If the mac_lock is already held then it is likely a port
1212 * reconfiguration is already in place, which will likely do 1223 * reconfiguration is already in place, which will likely do
1213 * most of the work of check_hw() anyway. */ 1224 * most of the work of check_hw() anyway. */
1214 if (!mutex_trylock(&efx->mac_lock)) { 1225 if (!mutex_trylock(&efx->mac_lock))
1215 queue_delayed_work(efx->workqueue, &efx->monitor_work, 1226 goto out_requeue;
1216 efx_monitor_interval); 1227 if (!efx->port_enabled)
1217 return; 1228 goto out_unlock;
1229 rc = efx->board_info.monitor(efx);
1230 if (rc) {
1231 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
1232 (rc == -ERANGE) ? "reported fault" : "failed");
1233 efx->phy_mode |= PHY_MODE_LOW_POWER;
1234 falcon_sim_phy_event(efx);
1218 } 1235 }
1236 efx->phy_op->poll(efx);
1237 efx->mac_op->poll(efx);
1219 1238
1220 if (efx->port_enabled) 1239out_unlock:
1221 efx->mac_op->check_hw(efx);
1222 mutex_unlock(&efx->mac_lock); 1240 mutex_unlock(&efx->mac_lock);
1223 1241out_requeue:
1224 queue_delayed_work(efx->workqueue, &efx->monitor_work, 1242 queue_delayed_work(efx->workqueue, &efx->monitor_work,
1225 efx_monitor_interval); 1243 efx_monitor_interval);
1226} 1244}
@@ -1477,7 +1495,7 @@ static void efx_set_multicast_list(struct net_device *net_dev)
1477 return; 1495 return;
1478 1496
1479 if (changed) 1497 if (changed)
1480 queue_work(efx->workqueue, &efx->reconfigure_work); 1498 queue_work(efx->workqueue, &efx->phy_work);
1481 1499
1482 /* Create and activate new global multicast hash table */ 1500 /* Create and activate new global multicast hash table */
1483 falcon_set_multicast_hash(efx); 1501 falcon_set_multicast_hash(efx);
@@ -1800,12 +1818,14 @@ void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {}
1800 1818
1801static struct efx_mac_operations efx_dummy_mac_operations = { 1819static struct efx_mac_operations efx_dummy_mac_operations = {
1802 .reconfigure = efx_port_dummy_op_void, 1820 .reconfigure = efx_port_dummy_op_void,
1821 .poll = efx_port_dummy_op_void,
1822 .irq = efx_port_dummy_op_void,
1803}; 1823};
1804 1824
1805static struct efx_phy_operations efx_dummy_phy_operations = { 1825static struct efx_phy_operations efx_dummy_phy_operations = {
1806 .init = efx_port_dummy_op_int, 1826 .init = efx_port_dummy_op_int,
1807 .reconfigure = efx_port_dummy_op_void, 1827 .reconfigure = efx_port_dummy_op_void,
1808 .check_hw = efx_port_dummy_op_int, 1828 .poll = efx_port_dummy_op_void,
1809 .fini = efx_port_dummy_op_void, 1829 .fini = efx_port_dummy_op_void,
1810 .clear_interrupt = efx_port_dummy_op_void, 1830 .clear_interrupt = efx_port_dummy_op_void,
1811}; 1831};
@@ -1857,7 +1877,8 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
1857 efx->mac_op = &efx_dummy_mac_operations; 1877 efx->mac_op = &efx_dummy_mac_operations;
1858 efx->phy_op = &efx_dummy_phy_operations; 1878 efx->phy_op = &efx_dummy_phy_operations;
1859 efx->mii.dev = net_dev; 1879 efx->mii.dev = net_dev;
1860 INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work); 1880 INIT_WORK(&efx->phy_work, efx_phy_work);
1881 INIT_WORK(&efx->mac_work, efx_mac_work);
1861 atomic_set(&efx->netif_stop_count, 1); 1882 atomic_set(&efx->netif_stop_count, 1);
1862 1883
1863 for (i = 0; i < EFX_MAX_CHANNELS; i++) { 1884 for (i = 0; i < EFX_MAX_CHANNELS; i++) {
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index fde4e7912c39..5a70ee7e8142 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -910,22 +910,20 @@ static void falcon_handle_global_event(struct efx_channel *channel,
910 efx_qword_t *event) 910 efx_qword_t *event)
911{ 911{
912 struct efx_nic *efx = channel->efx; 912 struct efx_nic *efx = channel->efx;
913 bool is_phy_event = false, handled = false; 913 bool handled = false;
914 914
915 /* Check for interrupt on either port. Some boards have a
916 * single PHY wired to the interrupt line for port 1. */
917 if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) || 915 if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
918 EFX_QWORD_FIELD(*event, G_PHY1_INTR) || 916 EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
919 EFX_QWORD_FIELD(*event, XG_PHY_INTR)) 917 EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
920 is_phy_event = true; 918 EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
919 efx->phy_op->clear_interrupt(efx);
920 queue_work(efx->workqueue, &efx->phy_work);
921 handled = true;
922 }
921 923
922 if ((falcon_rev(efx) >= FALCON_REV_B0) && 924 if ((falcon_rev(efx) >= FALCON_REV_B0) &&
923 EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) 925 EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
924 is_phy_event = true; 926 queue_work(efx->workqueue, &efx->mac_work);
925
926 if (is_phy_event) {
927 efx->phy_op->clear_interrupt(efx);
928 queue_work(efx->workqueue, &efx->reconfigure_work);
929 handled = true; 927 handled = true;
930 } 928 }
931 929
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
index b6e6eb963905..8865eae20ac5 100644
--- a/drivers/net/sfc/falcon_gmac.c
+++ b/drivers/net/sfc/falcon_gmac.c
@@ -221,13 +221,9 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
221 mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; 221 mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
222} 222}
223 223
224static int falcon_check_gmac(struct efx_nic *efx)
225{
226 return efx->phy_op->check_hw(efx);
227}
228
229struct efx_mac_operations falcon_gmac_operations = { 224struct efx_mac_operations falcon_gmac_operations = {
230 .reconfigure = falcon_reconfigure_gmac, 225 .reconfigure = falcon_reconfigure_gmac,
231 .update_stats = falcon_update_stats_gmac, 226 .update_stats = falcon_update_stats_gmac,
232 .check_hw = falcon_check_gmac, 227 .irq = efx_port_dummy_op_void,
228 .poll = efx_port_dummy_op_void,
233}; 229};
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 5553df888b84..a58c627f51aa 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -1051,6 +1051,8 @@
1051#define XG_MNT_INTR_B0_WIDTH 1 1051#define XG_MNT_INTR_B0_WIDTH 1
1052#define RX_RECOVERY_A1_LBN 11 1052#define RX_RECOVERY_A1_LBN 11
1053#define RX_RECOVERY_A1_WIDTH 1 1053#define RX_RECOVERY_A1_WIDTH 1
1054#define XFP_PHY_INTR_LBN 10
1055#define XFP_PHY_INTR_WIDTH 1
1054#define XG_PHY_INTR_LBN 9 1056#define XG_PHY_INTR_LBN 9
1055#define XG_PHY_INTR_WIDTH 1 1057#define XG_PHY_INTR_WIDTH 1
1056#define G_PHY1_INTR_LBN 8 1058#define G_PHY1_INTR_LBN 8
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index 0ce8f015386c..5a03713685ac 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -342,33 +342,35 @@ static void falcon_update_stats_xmac(struct efx_nic *efx)
342 mac_stats->rx_control * 64); 342 mac_stats->rx_control * 64);
343} 343}
344 344
345static int falcon_check_xmac(struct efx_nic *efx) 345static void falcon_xmac_irq(struct efx_nic *efx)
346{ 346{
347 bool xaui_link_ok; 347 /* The XGMII link has a transient fault, which indicates either:
348 int rc; 348 * - there's a transient xgmii fault
349 * - falcon's end of the xaui link may need a kick
350 * - the wire-side link may have gone down, but the lasi/poll()
351 * hasn't noticed yet.
352 *
353 * We only want to even bother polling XAUI if we're confident it's
354 * not (1) or (3). In both cases, the only reliable way to spot this
355 * is to wait a bit. We do this here by forcing the mac link state
356 * to down, and waiting for the mac poll to come round and check
357 */
358 efx->mac_up = false;
359}
349 360
350 if ((efx->loopback_mode == LOOPBACK_NETWORK) || 361static void falcon_poll_xmac(struct efx_nic *efx)
351 efx_phy_mode_disabled(efx->phy_mode)) 362{
352 return 0; 363 if (!EFX_WORKAROUND_5147(efx) || !efx->link_up || efx->mac_up)
364 return;
353 365
354 falcon_mask_status_intr(efx, false); 366 falcon_mask_status_intr(efx, false);
355 xaui_link_ok = falcon_xaui_link_ok(efx); 367 falcon_check_xaui_link_up(efx, 1);
356 368 falcon_mask_status_intr(efx, true);
357 if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok)
358 falcon_reset_xaui(efx);
359
360 /* Call the PHY check_hw routine */
361 rc = efx->phy_op->check_hw(efx);
362
363 /* Unmask interrupt if everything was (and still is) ok */
364 if (xaui_link_ok && efx->link_up)
365 falcon_mask_status_intr(efx, true);
366
367 return rc;
368} 369}
369 370
370struct efx_mac_operations falcon_xmac_operations = { 371struct efx_mac_operations falcon_xmac_operations = {
371 .reconfigure = falcon_reconfigure_xmac, 372 .reconfigure = falcon_reconfigure_xmac,
372 .update_stats = falcon_update_stats_xmac, 373 .update_stats = falcon_update_stats_xmac,
373 .check_hw = falcon_check_xmac, 374 .irq = falcon_xmac_irq,
375 .poll = falcon_poll_xmac,
374}; 376};
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index fb8d72527a34..61d09a2fa724 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -544,12 +544,14 @@ static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc,
544 * struct efx_mac_operations - Efx MAC operations table 544 * struct efx_mac_operations - Efx MAC operations table
545 * @reconfigure: Reconfigure MAC. Serialised by the mac_lock 545 * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
546 * @update_stats: Update statistics 546 * @update_stats: Update statistics
547 * @check_hw: Check hardware. Serialised by the mac_lock 547 * @irq: Hardware MAC event callback. Serialised by the mac_lock
548 * @poll: Poll for hardware state. Serialised by the mac_lock
548 */ 549 */
549struct efx_mac_operations { 550struct efx_mac_operations {
550 void (*reconfigure) (struct efx_nic *efx); 551 void (*reconfigure) (struct efx_nic *efx);
551 void (*update_stats) (struct efx_nic *efx); 552 void (*update_stats) (struct efx_nic *efx);
552 int (*check_hw) (struct efx_nic *efx); 553 void (*irq) (struct efx_nic *efx);
554 void (*poll) (struct efx_nic *efx);
553}; 555};
554 556
555/** 557/**
@@ -559,7 +561,7 @@ struct efx_mac_operations {
559 * @reconfigure: Reconfigure PHY (e.g. for new link parameters) 561 * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
560 * @clear_interrupt: Clear down interrupt 562 * @clear_interrupt: Clear down interrupt
561 * @blink: Blink LEDs 563 * @blink: Blink LEDs
562 * @check_hw: Check hardware 564 * @poll: Poll for hardware state. Serialised by the mac_lock.
563 * @get_settings: Get ethtool settings. Serialised by the mac_lock. 565 * @get_settings: Get ethtool settings. Serialised by the mac_lock.
564 * @set_settings: Set ethtool settings. Serialised by the mac_lock. 566 * @set_settings: Set ethtool settings. Serialised by the mac_lock.
565 * @set_xnp_advertise: Set abilities advertised in Extended Next Page 567 * @set_xnp_advertise: Set abilities advertised in Extended Next Page
@@ -573,7 +575,7 @@ struct efx_phy_operations {
573 void (*fini) (struct efx_nic *efx); 575 void (*fini) (struct efx_nic *efx);
574 void (*reconfigure) (struct efx_nic *efx); 576 void (*reconfigure) (struct efx_nic *efx);
575 void (*clear_interrupt) (struct efx_nic *efx); 577 void (*clear_interrupt) (struct efx_nic *efx);
576 int (*check_hw) (struct efx_nic *efx); 578 void (*poll) (struct efx_nic *efx);
577 int (*test) (struct efx_nic *efx); 579 int (*test) (struct efx_nic *efx);
578 void (*get_settings) (struct efx_nic *efx, 580 void (*get_settings) (struct efx_nic *efx,
579 struct ethtool_cmd *ecmd); 581 struct ethtool_cmd *ecmd);
@@ -728,10 +730,10 @@ union efx_multicast_hash {
728 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, 730 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
729 * @port_inhibited, efx_monitor() and efx_reconfigure_port() 731 * @port_inhibited, efx_monitor() and efx_reconfigure_port()
730 * @port_enabled: Port enabled indicator. 732 * @port_enabled: Port enabled indicator.
731 * Serialises efx_stop_all(), efx_start_all() and efx_monitor() and 733 * Serialises efx_stop_all(), efx_start_all(), efx_monitor(),
732 * efx_reconfigure_work with kernel interfaces. Safe to read under any 734 * efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read
733 * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must 735 * under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all
734 * be held to modify it. 736 * three must be held to modify it.
735 * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock 737 * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
736 * @port_initialized: Port initialized? 738 * @port_initialized: Port initialized?
737 * @net_dev: Operating system network device. Consider holding the rtnl lock 739 * @net_dev: Operating system network device. Consider holding the rtnl lock
@@ -762,7 +764,8 @@ union efx_multicast_hash {
762 * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. 764 * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
763 * @multicast_hash: Multicast hash table 765 * @multicast_hash: Multicast hash table
764 * @wanted_fc: Wanted flow control flags 766 * @wanted_fc: Wanted flow control flags
765 * @reconfigure_work: work item for dealing with PHY events 767 * @phy_work: work item for dealing with PHY events
768 * @mac_work: work item for dealing with MAC events
766 * @loopback_mode: Loopback status 769 * @loopback_mode: Loopback status
767 * @loopback_modes: Supported loopback mode bitmask 770 * @loopback_modes: Supported loopback mode bitmask
768 * @loopback_selftest: Offline self-test private state 771 * @loopback_selftest: Offline self-test private state
@@ -810,6 +813,7 @@ struct efx_nic {
810 struct falcon_nic_data *nic_data; 813 struct falcon_nic_data *nic_data;
811 814
812 struct mutex mac_lock; 815 struct mutex mac_lock;
816 struct work_struct mac_work;
813 bool port_enabled; 817 bool port_enabled;
814 bool port_inhibited; 818 bool port_inhibited;
815 819
@@ -830,6 +834,7 @@ struct efx_nic {
830 834
831 enum phy_type phy_type; 835 enum phy_type phy_type;
832 spinlock_t phy_lock; 836 spinlock_t phy_lock;
837 struct work_struct phy_work;
833 struct efx_phy_operations *phy_op; 838 struct efx_phy_operations *phy_op;
834 void *phy_data; 839 void *phy_data;
835 struct mii_if_info mii; 840 struct mii_if_info mii;
@@ -845,7 +850,6 @@ struct efx_nic {
845 bool promiscuous; 850 bool promiscuous;
846 union efx_multicast_hash multicast_hash; 851 union efx_multicast_hash multicast_hash;
847 enum efx_fc_type wanted_fc; 852 enum efx_fc_type wanted_fc;
848 struct work_struct reconfigure_work;
849 853
850 atomic_t rx_reset; 854 atomic_t rx_reset;
851 enum efx_loopback_mode loopback_mode; 855 enum efx_loopback_mode loopback_mode;
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 8142e37a518f..578b7f410ed4 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -594,12 +594,14 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
594 efx->loopback_mode = mode; 594 efx->loopback_mode = mode;
595 efx_reconfigure_port(efx); 595 efx_reconfigure_port(efx);
596 596
597 /* Wait for the PHY to signal the link is up */ 597 /* Wait for the PHY to signal the link is up. Interrupts
598 * are enabled for PHY's using LASI, otherwise we poll()
599 * quickly */
598 count = 0; 600 count = 0;
599 do { 601 do {
600 struct efx_channel *channel = &efx->channel[0]; 602 struct efx_channel *channel = &efx->channel[0];
601 603
602 efx->mac_op->check_hw(efx); 604 efx->phy_op->poll(efx);
603 schedule_timeout_uninterruptible(HZ / 10); 605 schedule_timeout_uninterruptible(HZ / 10);
604 if (channel->work_pending) 606 if (channel->work_pending)
605 efx_process_channel_now(channel); 607 efx_process_channel_now(channel);
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 634ff9198823..7256ea4abf9c 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -348,50 +348,34 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
348 efx->link_fc = mdio_clause45_get_pause(efx); 348 efx->link_fc = mdio_clause45_get_pause(efx);
349} 349}
350 350
351static void tenxpress_phy_clear_interrupt(struct efx_nic *efx)
352{
353 /* Nothing done here - LASI interrupts aren't reliable so poll */
354}
355
356
357/* Poll PHY for interrupt */ 351/* Poll PHY for interrupt */
358static int tenxpress_phy_check_hw(struct efx_nic *efx) 352static void tenxpress_phy_poll(struct efx_nic *efx)
359{ 353{
360 struct tenxpress_phy_data *phy_data = efx->phy_data; 354 struct tenxpress_phy_data *phy_data = efx->phy_data;
361 bool link_ok; 355 bool change = false, link_ok;
362 int rc = 0; 356 unsigned link_fc;
363 357
364 link_ok = tenxpress_link_ok(efx); 358 link_ok = tenxpress_link_ok(efx);
359 if (link_ok != efx->link_up) {
360 change = true;
361 } else {
362 link_fc = mdio_clause45_get_pause(efx);
363 if (link_fc != efx->link_fc)
364 change = true;
365 }
365 tenxpress_check_bad_lp(efx, link_ok); 366 tenxpress_check_bad_lp(efx, link_ok);
366 367
367 if (link_ok != efx->link_up) 368 if (change)
368 falcon_sim_phy_event(efx); 369 falcon_sim_phy_event(efx);
369 370
370 if (phy_data->phy_mode != PHY_MODE_NORMAL) 371 if (phy_data->phy_mode != PHY_MODE_NORMAL)
371 return 0; 372 return;
372 373
373 if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) { 374 if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
374 EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n"); 375 EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
375 falcon_reset_xaui(efx); 376 falcon_reset_xaui(efx);
376 atomic_set(&phy_data->bad_crc_count, 0); 377 atomic_set(&phy_data->bad_crc_count, 0);
377 } 378 }
378
379 rc = efx->board_info.monitor(efx);
380 if (rc) {
381 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
382 (rc == -ERANGE) ? "reported fault" : "failed");
383 if (efx->phy_mode & PHY_MODE_OFF) {
384 /* Assume that board has shut PHY off */
385 phy_data->phy_mode = PHY_MODE_OFF;
386 } else {
387 efx->phy_mode |= PHY_MODE_LOW_POWER;
388 mdio_clause45_set_mmds_lpower(efx, true,
389 efx->phy_op->mmds);
390 phy_data->phy_mode |= PHY_MODE_LOW_POWER;
391 }
392 }
393
394 return rc;
395} 379}
396 380
397static void tenxpress_phy_fini(struct efx_nic *efx) 381static void tenxpress_phy_fini(struct efx_nic *efx)
@@ -461,9 +445,9 @@ struct efx_phy_operations falcon_tenxpress_phy_ops = {
461 .macs = EFX_XMAC, 445 .macs = EFX_XMAC,
462 .init = tenxpress_phy_init, 446 .init = tenxpress_phy_init,
463 .reconfigure = tenxpress_phy_reconfigure, 447 .reconfigure = tenxpress_phy_reconfigure,
464 .check_hw = tenxpress_phy_check_hw, 448 .poll = tenxpress_phy_poll,
465 .fini = tenxpress_phy_fini, 449 .fini = tenxpress_phy_fini,
466 .clear_interrupt = tenxpress_phy_clear_interrupt, 450 .clear_interrupt = efx_port_dummy_op_void,
467 .test = tenxpress_phy_test, 451 .test = tenxpress_phy_test,
468 .get_settings = tenxpress_get_settings, 452 .get_settings = tenxpress_get_settings,
469 .set_settings = mdio_clause45_set_settings, 453 .set_settings = mdio_clause45_set_settings,
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index fbe8e25a1ed5..345ffc310dca 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -119,24 +119,12 @@ static int xfp_link_ok(struct efx_nic *efx)
119 return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS); 119 return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS);
120} 120}
121 121
122static int xfp_phy_check_hw(struct efx_nic *efx) 122static void xfp_phy_poll(struct efx_nic *efx)
123{ 123{
124 int rc = 0;
125 int link_up = xfp_link_ok(efx); 124 int link_up = xfp_link_ok(efx);
126 /* Simulate a PHY event if link state has changed */ 125 /* Simulate a PHY event if link state has changed */
127 if (link_up != efx->link_up) 126 if (link_up != efx->link_up)
128 falcon_sim_phy_event(efx); 127 falcon_sim_phy_event(efx);
129
130 rc = efx->board_info.monitor(efx);
131 if (rc) {
132 struct xfp_phy_data *phy_data = efx->phy_data;
133 EFX_ERR(efx, "XFP sensor alert; putting PHY into low power\n");
134 efx->phy_mode |= PHY_MODE_LOW_POWER;
135 mdio_clause45_set_mmds_lpower(efx, 1, XFP_REQUIRED_DEVS);
136 phy_data->phy_mode |= PHY_MODE_LOW_POWER;
137 }
138
139 return rc;
140} 128}
141 129
142static void xfp_phy_reconfigure(struct efx_nic *efx) 130static void xfp_phy_reconfigure(struct efx_nic *efx)
@@ -173,7 +161,7 @@ struct efx_phy_operations falcon_xfp_phy_ops = {
173 .macs = EFX_XMAC, 161 .macs = EFX_XMAC,
174 .init = xfp_phy_init, 162 .init = xfp_phy_init,
175 .reconfigure = xfp_phy_reconfigure, 163 .reconfigure = xfp_phy_reconfigure,
176 .check_hw = xfp_phy_check_hw, 164 .poll = xfp_phy_poll,
177 .fini = xfp_phy_fini, 165 .fini = xfp_phy_fini,
178 .clear_interrupt = xfp_phy_clear_interrupt, 166 .clear_interrupt = xfp_phy_clear_interrupt,
179 .get_settings = mdio_clause45_get_settings, 167 .get_settings = mdio_clause45_get_settings,