diff options
author | Steve Hodgson <shodgson@solarflare.com> | 2010-04-28 05:28:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-28 15:44:35 -0400 |
commit | 41b7e4c3268d9d2056b9c94cceb386649f7b185b (patch) | |
tree | 706d46fdd10943ba86d4eda2ff210bc506997144 | |
parent | b7b40eeb0f76e73503a7e5a98d1353c2e42d9a18 (diff) |
sfc: Extend the legacy interrupt workarounds
Siena has two problems with legacy interrupts:
1. There is no synchronisation between the ISR read completion,
and the interrupt deassert message.
2. A downstream read at the "wrong" moment can return 0, and
suppress generating the next interrupt.
Falcon should suffer from both of these, and it appears it does.
Enable EFX_WORKAROUND_15783 on Falcon as well.
Also, when we see queues == 0, ensure we always schedule or rearm
every event queue.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/sfc/nic.c | 23 | ||||
-rw-r--r-- | drivers/net/sfc/workarounds.h | 2 |
2 files changed, 10 insertions, 15 deletions
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index 23738f80835b..b61674cb0c19 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c | |||
@@ -1356,33 +1356,28 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) | |||
1356 | } | 1356 | } |
1357 | result = IRQ_HANDLED; | 1357 | result = IRQ_HANDLED; |
1358 | 1358 | ||
1359 | } else if (EFX_WORKAROUND_15783(efx) && | 1359 | } else if (EFX_WORKAROUND_15783(efx)) { |
1360 | efx->irq_zero_count++ == 0) { | ||
1361 | efx_qword_t *event; | 1360 | efx_qword_t *event; |
1362 | 1361 | ||
1363 | /* Ensure we rearm all event queues */ | 1362 | /* We can't return IRQ_HANDLED more than once on seeing ISR=0 |
1363 | * because this might be a shared interrupt. */ | ||
1364 | if (efx->irq_zero_count++ == 0) | ||
1365 | result = IRQ_HANDLED; | ||
1366 | |||
1367 | /* Ensure we schedule or rearm all event queues */ | ||
1364 | efx_for_each_channel(channel, efx) { | 1368 | efx_for_each_channel(channel, efx) { |
1365 | event = efx_event(channel, channel->eventq_read_ptr); | 1369 | event = efx_event(channel, channel->eventq_read_ptr); |
1366 | if (efx_event_present(event)) | 1370 | if (efx_event_present(event)) |
1367 | efx_schedule_channel(channel); | 1371 | efx_schedule_channel(channel); |
1372 | else | ||
1373 | efx_nic_eventq_read_ack(channel); | ||
1368 | } | 1374 | } |
1369 | |||
1370 | result = IRQ_HANDLED; | ||
1371 | } | 1375 | } |
1372 | 1376 | ||
1373 | if (result == IRQ_HANDLED) { | 1377 | if (result == IRQ_HANDLED) { |
1374 | efx->last_irq_cpu = raw_smp_processor_id(); | 1378 | efx->last_irq_cpu = raw_smp_processor_id(); |
1375 | EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", | 1379 | EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", |
1376 | irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); | 1380 | irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); |
1377 | } else if (EFX_WORKAROUND_15783(efx)) { | ||
1378 | /* We can't return IRQ_HANDLED more than once on seeing ISR0=0 | ||
1379 | * because this might be a shared interrupt, but we do need to | ||
1380 | * check the channel every time and preemptively rearm it if | ||
1381 | * it's idle. */ | ||
1382 | efx_for_each_channel(channel, efx) { | ||
1383 | if (!channel->work_pending) | ||
1384 | efx_nic_eventq_read_ack(channel); | ||
1385 | } | ||
1386 | } | 1381 | } |
1387 | 1382 | ||
1388 | return result; | 1383 | return result; |
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index acd9c734e483..518f7fc91473 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h | |||
@@ -37,7 +37,7 @@ | |||
37 | /* Truncated IPv4 packets can confuse the TX packet parser */ | 37 | /* Truncated IPv4 packets can confuse the TX packet parser */ |
38 | #define EFX_WORKAROUND_15592 EFX_WORKAROUND_FALCON_AB | 38 | #define EFX_WORKAROUND_15592 EFX_WORKAROUND_FALCON_AB |
39 | /* Legacy ISR read can return zero once */ | 39 | /* Legacy ISR read can return zero once */ |
40 | #define EFX_WORKAROUND_15783 EFX_WORKAROUND_SIENA | 40 | #define EFX_WORKAROUND_15783 EFX_WORKAROUND_ALWAYS |
41 | /* Legacy interrupt storm when interrupt fifo fills */ | 41 | /* Legacy interrupt storm when interrupt fifo fills */ |
42 | #define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA | 42 | #define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA |
43 | 43 | ||