diff options
-rw-r--r-- | drivers/net/sfc/falcon.c | 13 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/nic.c | 35 |
3 files changed, 29 insertions, 21 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d294d66fd600..d09ad1b1cd8b 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -175,16 +175,19 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) | |||
175 | EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", | 175 | EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", |
176 | irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); | 176 | irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); |
177 | 177 | ||
178 | /* Check to see if we have a serious error condition */ | ||
179 | syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); | ||
180 | if (unlikely(syserr)) | ||
181 | return efx_nic_fatal_interrupt(efx); | ||
182 | |||
183 | /* Determine interrupting queues, clear interrupt status | 178 | /* Determine interrupting queues, clear interrupt status |
184 | * register and acknowledge the device interrupt. | 179 | * register and acknowledge the device interrupt. |
185 | */ | 180 | */ |
186 | BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS); | 181 | BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS); |
187 | queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q); | 182 | queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q); |
183 | |||
184 | /* Check to see if we have a serious error condition */ | ||
185 | if (queues & (1U << efx->fatal_irq_level)) { | ||
186 | syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); | ||
187 | if (unlikely(syserr)) | ||
188 | return efx_nic_fatal_interrupt(efx); | ||
189 | } | ||
190 | |||
188 | EFX_ZERO_OWORD(*int_ker); | 191 | EFX_ZERO_OWORD(*int_ker); |
189 | wmb(); /* Ensure the vector is cleared before interrupt ack */ | 192 | wmb(); /* Ensure the vector is cleared before interrupt ack */ |
190 | falcon_irq_ack_a1(efx); | 193 | falcon_irq_ack_a1(efx); |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index cb018e272097..70aea3af9ae7 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -672,6 +672,7 @@ union efx_multicast_hash { | |||
672 | * This register is written with the SMP processor ID whenever an | 672 | * This register is written with the SMP processor ID whenever an |
673 | * interrupt is handled. It is used by efx_nic_test_interrupt() | 673 | * interrupt is handled. It is used by efx_nic_test_interrupt() |
674 | * to verify that an interrupt has occurred. | 674 | * to verify that an interrupt has occurred. |
675 | * @fatal_irq_level: IRQ level (bit number) used for serious errors | ||
675 | * @spi_flash: SPI flash device | 676 | * @spi_flash: SPI flash device |
676 | * This field will be %NULL if no flash device is present (or for Siena). | 677 | * This field will be %NULL if no flash device is present (or for Siena). |
677 | * @spi_eeprom: SPI EEPROM device | 678 | * @spi_eeprom: SPI EEPROM device |
@@ -756,6 +757,7 @@ struct efx_nic { | |||
756 | struct efx_buffer irq_status; | 757 | struct efx_buffer irq_status; |
757 | volatile signed int last_irq_cpu; | 758 | volatile signed int last_irq_cpu; |
758 | unsigned long irq_zero_count; | 759 | unsigned long irq_zero_count; |
760 | unsigned fatal_irq_level; | ||
759 | 761 | ||
760 | struct efx_spi_device *spi_flash; | 762 | struct efx_spi_device *spi_flash; |
761 | struct efx_spi_device *spi_eeprom; | 763 | struct efx_spi_device *spi_eeprom; |
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 | } |
1327 | out: | 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()). |