diff options
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 97a6ebdcaf2b..4b5c786f0e2c 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include "mdio_10g.h" | 25 | #include "mdio_10g.h" |
26 | #include "nic.h" | 26 | #include "nic.h" |
27 | 27 | ||
28 | #include "mcdi.h" | ||
29 | |||
28 | /************************************************************************** | 30 | /************************************************************************** |
29 | * | 31 | * |
30 | * Type name strings | 32 | * Type name strings |
@@ -84,6 +86,7 @@ const char *efx_reset_type_names[] = { | |||
84 | [RESET_TYPE_RX_DESC_FETCH] = "RX_DESC_FETCH", | 86 | [RESET_TYPE_RX_DESC_FETCH] = "RX_DESC_FETCH", |
85 | [RESET_TYPE_TX_DESC_FETCH] = "TX_DESC_FETCH", | 87 | [RESET_TYPE_TX_DESC_FETCH] = "TX_DESC_FETCH", |
86 | [RESET_TYPE_TX_SKIP] = "TX_SKIP", | 88 | [RESET_TYPE_TX_SKIP] = "TX_SKIP", |
89 | [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", | ||
87 | }; | 90 | }; |
88 | 91 | ||
89 | #define EFX_MAX_MTU (9 * 1024) | 92 | #define EFX_MAX_MTU (9 * 1024) |
@@ -1191,6 +1194,15 @@ static void efx_start_all(struct efx_nic *efx) | |||
1191 | 1194 | ||
1192 | efx_nic_enable_interrupts(efx); | 1195 | efx_nic_enable_interrupts(efx); |
1193 | 1196 | ||
1197 | /* Switch to event based MCDI completions after enabling interrupts. | ||
1198 | * If a reset has been scheduled, then we need to stay in polled mode. | ||
1199 | * Rather than serialising efx_mcdi_mode_event() [which sleeps] and | ||
1200 | * reset_pending [modified from an atomic context], we instead guarantee | ||
1201 | * that efx_mcdi_mode_poll() isn't reverted erroneously */ | ||
1202 | efx_mcdi_mode_event(efx); | ||
1203 | if (efx->reset_pending != RESET_TYPE_NONE) | ||
1204 | efx_mcdi_mode_poll(efx); | ||
1205 | |||
1194 | /* Start the hardware monitor if there is one. Otherwise (we're link | 1206 | /* Start the hardware monitor if there is one. Otherwise (we're link |
1195 | * event driven), we have to poll the PHY because after an event queue | 1207 | * event driven), we have to poll the PHY because after an event queue |
1196 | * flush, we could have a missed a link state change */ | 1208 | * flush, we could have a missed a link state change */ |
@@ -1242,6 +1254,9 @@ static void efx_stop_all(struct efx_nic *efx) | |||
1242 | 1254 | ||
1243 | efx->type->stop_stats(efx); | 1255 | efx->type->stop_stats(efx); |
1244 | 1256 | ||
1257 | /* Switch to MCDI polling on Siena before disabling interrupts */ | ||
1258 | efx_mcdi_mode_poll(efx); | ||
1259 | |||
1245 | /* Disable interrupts and wait for ISR to complete */ | 1260 | /* Disable interrupts and wait for ISR to complete */ |
1246 | efx_nic_disable_interrupts(efx); | 1261 | efx_nic_disable_interrupts(efx); |
1247 | if (efx->legacy_irq) | 1262 | if (efx->legacy_irq) |
@@ -1445,6 +1460,8 @@ static int efx_net_open(struct net_device *net_dev) | |||
1445 | return -EIO; | 1460 | return -EIO; |
1446 | if (efx->phy_mode & PHY_MODE_SPECIAL) | 1461 | if (efx->phy_mode & PHY_MODE_SPECIAL) |
1447 | return -EBUSY; | 1462 | return -EBUSY; |
1463 | if (efx_mcdi_poll_reboot(efx) && efx_reset(efx, RESET_TYPE_ALL)) | ||
1464 | return -EIO; | ||
1448 | 1465 | ||
1449 | /* Notify the kernel of the link state polled during driver load, | 1466 | /* Notify the kernel of the link state polled during driver load, |
1450 | * before the monitor starts running */ | 1467 | * before the monitor starts running */ |
@@ -1895,6 +1912,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) | |||
1895 | case RESET_TYPE_TX_SKIP: | 1912 | case RESET_TYPE_TX_SKIP: |
1896 | method = RESET_TYPE_INVISIBLE; | 1913 | method = RESET_TYPE_INVISIBLE; |
1897 | break; | 1914 | break; |
1915 | case RESET_TYPE_MC_FAILURE: | ||
1898 | default: | 1916 | default: |
1899 | method = RESET_TYPE_ALL; | 1917 | method = RESET_TYPE_ALL; |
1900 | break; | 1918 | break; |
@@ -1908,6 +1926,10 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) | |||
1908 | 1926 | ||
1909 | efx->reset_pending = method; | 1927 | efx->reset_pending = method; |
1910 | 1928 | ||
1929 | /* efx_process_channel() will no longer read events once a | ||
1930 | * reset is scheduled. So switch back to poll'd MCDI completions. */ | ||
1931 | efx_mcdi_mode_poll(efx); | ||
1932 | |||
1911 | queue_work(reset_workqueue, &efx->reset_work); | 1933 | queue_work(reset_workqueue, &efx->reset_work); |
1912 | } | 1934 | } |
1913 | 1935 | ||
@@ -1923,6 +1945,10 @@ static struct pci_device_id efx_pci_table[] __devinitdata = { | |||
1923 | .driver_data = (unsigned long) &falcon_a1_nic_type}, | 1945 | .driver_data = (unsigned long) &falcon_a1_nic_type}, |
1924 | {PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID), | 1946 | {PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID), |
1925 | .driver_data = (unsigned long) &falcon_b0_nic_type}, | 1947 | .driver_data = (unsigned long) &falcon_b0_nic_type}, |
1948 | {PCI_DEVICE(EFX_VENDID_SFC, BETHPAGE_A_P_DEVID), | ||
1949 | .driver_data = (unsigned long) &siena_a0_nic_type}, | ||
1950 | {PCI_DEVICE(EFX_VENDID_SFC, SIENA_A_P_DEVID), | ||
1951 | .driver_data = (unsigned long) &siena_a0_nic_type}, | ||
1926 | {0} /* end of list */ | 1952 | {0} /* end of list */ |
1927 | }; | 1953 | }; |
1928 | 1954 | ||