aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/efx.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-12-07 14:24:45 -0500
committerBen Hutchings <bhutchings@solarflare.com>2010-12-07 14:30:19 -0500
commit94dec6a2d20a26a779b63bb584e48db5fb0ddb53 (patch)
tree3911c0883429411e27f22db1e34436d75fbb937b /drivers/net/sfc/efx.c
parent46bcf14f44d8f31ecfdc8b6708ec15a3b33316d9 (diff)
sfc: Fix crash in legacy onterrupt handler during ring reallocation
If we are using a legacy interrupt, our IRQ may be shared and our interrupt handler may be called even though interrupts are disabled on the NIC. When we change ring sizes, we reallocate the event queue and the interrupt handler may use an invalid pointer when called for another device's interrupt. Maintain a legacy_irq_enabled flag and test that at the top of the interrupt handler. Note that this problem results from the need to work around broken INT_ISR0 reads, and does not affect the legacy interrupt handler for Falcon A1. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r--drivers/net/sfc/efx.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 05df20e47976..d06cb742164b 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -335,8 +335,10 @@ void efx_process_channel_now(struct efx_channel *channel)
335 335
336 /* Disable interrupts and wait for ISRs to complete */ 336 /* Disable interrupts and wait for ISRs to complete */
337 efx_nic_disable_interrupts(efx); 337 efx_nic_disable_interrupts(efx);
338 if (efx->legacy_irq) 338 if (efx->legacy_irq) {
339 synchronize_irq(efx->legacy_irq); 339 synchronize_irq(efx->legacy_irq);
340 efx->legacy_irq_enabled = false;
341 }
340 if (channel->irq) 342 if (channel->irq)
341 synchronize_irq(channel->irq); 343 synchronize_irq(channel->irq);
342 344
@@ -351,6 +353,8 @@ void efx_process_channel_now(struct efx_channel *channel)
351 efx_channel_processed(channel); 353 efx_channel_processed(channel);
352 354
353 napi_enable(&channel->napi_str); 355 napi_enable(&channel->napi_str);
356 if (efx->legacy_irq)
357 efx->legacy_irq_enabled = true;
354 efx_nic_enable_interrupts(efx); 358 efx_nic_enable_interrupts(efx);
355} 359}
356 360
@@ -1400,6 +1404,8 @@ static void efx_start_all(struct efx_nic *efx)
1400 efx_start_channel(channel); 1404 efx_start_channel(channel);
1401 } 1405 }
1402 1406
1407 if (efx->legacy_irq)
1408 efx->legacy_irq_enabled = true;
1403 efx_nic_enable_interrupts(efx); 1409 efx_nic_enable_interrupts(efx);
1404 1410
1405 /* Switch to event based MCDI completions after enabling interrupts. 1411 /* Switch to event based MCDI completions after enabling interrupts.
@@ -1460,8 +1466,10 @@ static void efx_stop_all(struct efx_nic *efx)
1460 1466
1461 /* Disable interrupts and wait for ISR to complete */ 1467 /* Disable interrupts and wait for ISR to complete */
1462 efx_nic_disable_interrupts(efx); 1468 efx_nic_disable_interrupts(efx);
1463 if (efx->legacy_irq) 1469 if (efx->legacy_irq) {
1464 synchronize_irq(efx->legacy_irq); 1470 synchronize_irq(efx->legacy_irq);
1471 efx->legacy_irq_enabled = false;
1472 }
1465 efx_for_each_channel(channel, efx) { 1473 efx_for_each_channel(channel, efx) {
1466 if (channel->irq) 1474 if (channel->irq)
1467 synchronize_irq(channel->irq); 1475 synchronize_irq(channel->irq);