Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41b7e4c3 authored by Steve Hodgson's avatar Steve Hodgson Committed by David S. Miller
Browse files

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b7b40eeb
Loading
Loading
Loading
Loading
+9 −14
Original line number Diff line number Diff line
@@ -1356,33 +1356,28 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
		}
		result = IRQ_HANDLED;

	} else if (EFX_WORKAROUND_15783(efx) &&
		   efx->irq_zero_count++ == 0) {
	} else if (EFX_WORKAROUND_15783(efx)) {
		efx_qword_t *event;

		/* Ensure we rearm all event queues */
		/* We can't return IRQ_HANDLED more than once on seeing ISR=0
		 * because this might be a shared interrupt. */
		if (efx->irq_zero_count++ == 0)
			result = IRQ_HANDLED;

		/* Ensure we schedule or rearm all event queues */
		efx_for_each_channel(channel, efx) {
			event = efx_event(channel, channel->eventq_read_ptr);
			if (efx_event_present(event))
				efx_schedule_channel(channel);
			else
				efx_nic_eventq_read_ack(channel);
		}

		result = IRQ_HANDLED;
	}

	if (result == IRQ_HANDLED) {
		efx->last_irq_cpu = raw_smp_processor_id();
		EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
			  irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
	} else if (EFX_WORKAROUND_15783(efx)) {
		/* We can't return IRQ_HANDLED more than once on seeing ISR0=0
		 * because this might be a shared interrupt, but we do need to
		 * check the channel every time and preemptively rearm it if
		 * it's idle. */
		efx_for_each_channel(channel, efx) {
			if (!channel->work_pending)
				efx_nic_eventq_read_ack(channel);
		}
	}

	return result;
+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@
/* Truncated IPv4 packets can confuse the TX packet parser */
#define EFX_WORKAROUND_15592 EFX_WORKAROUND_FALCON_AB
/* Legacy ISR read can return zero once */
#define EFX_WORKAROUND_15783 EFX_WORKAROUND_SIENA
#define EFX_WORKAROUND_15783 EFX_WORKAROUND_ALWAYS
/* Legacy interrupt storm when interrupt fifo fills */
#define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA