diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2012-01-05 20:14:10 +0000 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2012-01-27 00:10:52 +0000 |
commit | 1646a6f352a6f70fcca828589ed04797aa09d494 (patch) | |
tree | 7f39f32e75140e831c26dd57caa7c28515252053 /drivers/net/ethernet/sfc/selftest.c | |
parent | f70d1847348e9548a9a56e4434946315bca297c8 (diff) | |
download | op-kernel-dev-1646a6f352a6f70fcca828589ed04797aa09d494.zip op-kernel-dev-1646a6f352a6f70fcca828589ed04797aa09d494.tar.gz |
sfc: Clean up test interrupt handling
Interrupts are normally generated by the event queues, moderated by
timers. However, they may also be triggered by detection of a 'fatal'
error condition (e.g. memory parity error) or by the host writing to
certain CSR fields as part of a self-test.
The IRQ level/index used for these on Falcon rev B0 and Siena is set
by the KER_INT_LEVE_SEL field and cached by the driver in
efx_nic::fatal_irq_level. Since this value is also relevant to
self-tests rename the field to just 'irq_level'.
Avoid unnecessary cache traffic by using a per-channel 'last_irq_cpu'
field and only writing to the per-controller field when the interrupt
matches efx_nic::irq_level. Remove the volatile qualifier and use
ACCESS_ONCE in the places we read these fields.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/selftest.c')
-rw-r--r-- | drivers/net/ethernet/sfc/selftest.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 0f84789..7def480 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -130,6 +130,8 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) static int efx_test_interrupts(struct efx_nic *efx, struct efx_self_tests *tests) { + int cpu; + netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); tests->interrupt = -1; @@ -142,7 +144,8 @@ static int efx_test_interrupts(struct efx_nic *efx, /* Wait for arrival of test interrupt. */ netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n"); schedule_timeout_uninterruptible(HZ / 10); - if (efx->last_irq_cpu >= 0) + cpu = ACCESS_ONCE(efx->last_irq_cpu); + if (cpu >= 0) goto success; netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n"); @@ -150,8 +153,7 @@ static int efx_test_interrupts(struct efx_nic *efx, success: netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n", - INT_MODE(efx), - efx->last_irq_cpu); + INT_MODE(efx), cpu); tests->interrupt = 1; return 0; } @@ -165,7 +167,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, bool napi_ran, dma_seen, int_seen; read_ptr = channel->eventq_read_ptr; - channel->efx->last_irq_cpu = -1; + channel->last_irq_cpu = -1; smp_wmb(); efx_nic_generate_test_event(channel); @@ -182,7 +184,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, } else { napi_ran = false; dma_seen = efx_nic_event_present(channel); - int_seen = efx->last_irq_cpu >= 0; + int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0; } napi_enable(&channel->napi_str); efx_nic_eventq_read_ack(channel); |