diff options
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 63 |
1 files changed, 42 insertions, 21 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++) { |