diff options
-rw-r--r-- | drivers/net/sfc/efx.c | 63 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 20 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_gmac.c | 8 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_hwdefs.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 42 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 24 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 6 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 44 | ||||
-rw-r--r-- | drivers/net/sfc/xfp_phy.c | 16 |
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 */ |
615 | static void efx_reconfigure_work(struct work_struct *data) | 615 | static 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 | ||
625 | static 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 | |||
626 | static int efx_probe_port(struct efx_nic *efx) | 635 | static 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 */ |
692 | static void efx_start_port(struct efx_nic *efx) | 701 | static 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 */ |
707 | static void efx_stop_port(struct efx_nic *efx) | 717 | static 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) | 1239 | out_unlock: |
1221 | efx->mac_op->check_hw(efx); | ||
1222 | mutex_unlock(&efx->mac_lock); | 1240 | mutex_unlock(&efx->mac_lock); |
1223 | 1241 | out_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 | ||
1801 | static struct efx_mac_operations efx_dummy_mac_operations = { | 1819 | static 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 | ||
1805 | static struct efx_phy_operations efx_dummy_phy_operations = { | 1825 | static 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 | ||
224 | static int falcon_check_gmac(struct efx_nic *efx) | ||
225 | { | ||
226 | return efx->phy_op->check_hw(efx); | ||
227 | } | ||
228 | |||
229 | struct efx_mac_operations falcon_gmac_operations = { | 224 | struct 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 | ||
345 | static int falcon_check_xmac(struct efx_nic *efx) | 345 | static 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) || | 361 | static 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 | ||
370 | struct efx_mac_operations falcon_xmac_operations = { | 371 | struct 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 | */ |
549 | struct efx_mac_operations { | 550 | struct 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 | ||
351 | static 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 */ |
358 | static int tenxpress_phy_check_hw(struct efx_nic *efx) | 352 | static 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 | ||
397 | static void tenxpress_phy_fini(struct efx_nic *efx) | 381 | static 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 | ||
122 | static int xfp_phy_check_hw(struct efx_nic *efx) | 122 | static 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 | ||
142 | static void xfp_phy_reconfigure(struct efx_nic *efx) | 130 | static 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, |