aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/falcon.c
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2010-04-28 05:27:36 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-28 15:44:32 -0400
commit6369545945b90daa1a73fca174da9194c398417c (patch)
tree1331418d5c6b547eed8154fedceed68585506aa5 /drivers/net/sfc/falcon.c
parent00bbb4a5344a5f81cf5d48e781e5c0df3e588d17 (diff)
sfc: Handle serious errors in exactly one interrupt handler
'Fatal' errors set an interrupt flag associated with a specific event queue; only read the syndrome vector if we see that queue's flag set (legacy interrupts) or in the interrupt handler for that queue (MSI). Do not ignore an interrupt if the fatal error flag is set but specific error flags are all zero. Even if we don't schedule a reset, we must respect the queue mask and rearm the appropriate event queues. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r--drivers/net/sfc/falcon.c13
1 files changed, 8 insertions, 5 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);