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>
This commit is contained in:
@ -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);
|
||||
|
Reference in New Issue
Block a user