aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/efx.c
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 /drivers/net/sfc/efx.c
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>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r--drivers/net/sfc/efx.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7214ea6f7e1..ce1c7d3cd12 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++) {