aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/nic.c
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2010-04-28 05:27:36 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-28 15:44:32 -0400
commit6369545945b90daa1a73fca174da9194c398417c (patch)
tree1331418d5c6b547eed8154fedceed68585506aa5 /drivers/net/sfc/nic.c
parent00bbb4a5344a5f81cf5d48e781e5c0df3e588d17 (diff)
sfc: Handle serious errors in exactly one interrupt handler
'Fatal' errors set an interrupt flag associated with a specific event queue; only read the syndrome vector if we see that queue's flag set (legacy interrupts) or in the interrupt handler for that queue (MSI). Do not ignore an interrupt if the fatal error flag is set but specific error flags are all zero. Even if we don't schedule a reset, we must respect the queue mask and rearm the appropriate event queues. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/nic.c')
-rw-r--r--drivers/net/sfc/nic.c35
1 files changed, 19 insertions, 16 deletions
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index 664fd6ceed55..23738f80835b 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -1229,15 +1229,9 @@ static inline void efx_nic_interrupts(struct efx_nic *efx,
1229 bool enabled, bool force) 1229 bool enabled, bool force)
1230{ 1230{
1231 efx_oword_t int_en_reg_ker; 1231 efx_oword_t int_en_reg_ker;
1232 unsigned int level = 0;
1233
1234 if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx))
1235 /* Set the level always even if we're generating a test
1236 * interrupt, because our legacy interrupt handler is safe */
1237 level = 0x1f;
1238 1232
1239 EFX_POPULATE_OWORD_3(int_en_reg_ker, 1233 EFX_POPULATE_OWORD_3(int_en_reg_ker,
1240 FRF_AZ_KER_INT_LEVE_SEL, level, 1234 FRF_AZ_KER_INT_LEVE_SEL, efx->fatal_irq_level,
1241 FRF_AZ_KER_INT_KER, force, 1235 FRF_AZ_KER_INT_KER, force,
1242 FRF_AZ_DRV_INT_EN_KER, enabled); 1236 FRF_AZ_DRV_INT_EN_KER, enabled);
1243 efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER); 1237 efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER);
@@ -1291,8 +1285,6 @@ irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
1291 EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker), 1285 EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker),
1292 EFX_OWORD_VAL(fatal_intr), 1286 EFX_OWORD_VAL(fatal_intr),
1293 error ? "disabling bus mastering" : "no recognised error"); 1287 error ? "disabling bus mastering" : "no recognised error");
1294 if (error == 0)
1295 goto out;
1296 1288
1297 /* If this is a memory parity error dump which blocks are offending */ 1289 /* If this is a memory parity error dump which blocks are offending */
1298 mem_perr = EFX_OWORD_FIELD(fatal_intr, FRF_AZ_MEM_PERR_INT_KER); 1290 mem_perr = EFX_OWORD_FIELD(fatal_intr, FRF_AZ_MEM_PERR_INT_KER);
@@ -1324,7 +1316,7 @@ irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
1324 "NIC will be disabled\n"); 1316 "NIC will be disabled\n");
1325 efx_schedule_reset(efx, RESET_TYPE_DISABLE); 1317 efx_schedule_reset(efx, RESET_TYPE_DISABLE);
1326 } 1318 }
1327out: 1319
1328 return IRQ_HANDLED; 1320 return IRQ_HANDLED;
1329} 1321}
1330 1322
@@ -1346,9 +1338,11 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
1346 queues = EFX_EXTRACT_DWORD(reg, 0, 31); 1338 queues = EFX_EXTRACT_DWORD(reg, 0, 31);
1347 1339
1348 /* Check to see if we have a serious error condition */ 1340 /* Check to see if we have a serious error condition */
1349 syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); 1341 if (queues & (1U << efx->fatal_irq_level)) {
1350 if (unlikely(syserr)) 1342 syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
1351 return efx_nic_fatal_interrupt(efx); 1343 if (unlikely(syserr))
1344 return efx_nic_fatal_interrupt(efx);
1345 }
1352 1346
1353 if (queues != 0) { 1347 if (queues != 0) {
1354 if (EFX_WORKAROUND_15783(efx)) 1348 if (EFX_WORKAROUND_15783(efx))
@@ -1413,9 +1407,11 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
1413 irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); 1407 irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
1414 1408
1415 /* Check to see if we have a serious error condition */ 1409 /* Check to see if we have a serious error condition */
1416 syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); 1410 if (channel->channel == efx->fatal_irq_level) {
1417 if (unlikely(syserr)) 1411 syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
1418 return efx_nic_fatal_interrupt(efx); 1412 if (unlikely(syserr))
1413 return efx_nic_fatal_interrupt(efx);
1414 }
1419 1415
1420 /* Schedule processing of the channel */ 1416 /* Schedule processing of the channel */
1421 efx_schedule_channel(channel); 1417 efx_schedule_channel(channel);
@@ -1553,6 +1549,13 @@ void efx_nic_init_common(struct efx_nic *efx)
1553 FRF_AZ_INT_ADR_KER, efx->irq_status.dma_addr); 1549 FRF_AZ_INT_ADR_KER, efx->irq_status.dma_addr);
1554 efx_writeo(efx, &temp, FR_AZ_INT_ADR_KER); 1550 efx_writeo(efx, &temp, FR_AZ_INT_ADR_KER);
1555 1551
1552 if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx))
1553 /* Use an interrupt level unused by event queues */
1554 efx->fatal_irq_level = 0x1f;
1555 else
1556 /* Use a valid MSI-X vector */
1557 efx->fatal_irq_level = 0;
1558
1556 /* Enable all the genuinely fatal interrupts. (They are still 1559 /* Enable all the genuinely fatal interrupts. (They are still
1557 * masked by the overall interrupt mask, controlled by 1560 * masked by the overall interrupt mask, controlled by
1558 * falcon_interrupts()). 1561 * falcon_interrupts()).