On 2025/05/02 12:17, Nicholas Piggin wrote:
> The msix interrupt throttling timer expiry sends an interrupt even if
> there is no unmasked interrupt causes. This can be observed by seeing
> two interrupts in response to a single event when throttling is active.
>
> The e1000e non-msix paths seem to get this right by masking and testing
> ICR and IMS. Add similar checks for the msix cases in e1000e and igb.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> hw/net/e1000e_core.c | 10 ++++++----
> hw/net/igb_core.c | 11 ++++++++---
> 2 files changed, 14 insertions(+), 7 deletions(-)
>
> diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
> index 022884a2ea0..d53f70065ef 100644
> --- a/hw/net/e1000e_core.c
> +++ b/hw/net/e1000e_core.c
> @@ -230,10 +230,12 @@ e1000e_intrmgr_on_msix_throttling_timer(void *opaque)
>
> timer->running = false;
>
> - causes = find_msix_causes(core, idx);
> - trace_e1000e_irq_msix_notify_postponed_vec(idx);
> - msix_notify(core->owner, idx);
> - e1000e_msix_auto_clear_mask(core, causes);
> + causes = find_msix_causes(core, idx) & core->mac[IMS] & core->mac[ICR];
> + if (causes) {
> + trace_e1000e_irq_msix_notify_postponed_vec(idx);
> + msix_notify(core->owner, causes);
I think this should be: msix_notify(core->owner, idx);
> + e1000e_msix_auto_clear_mask(core, causes);
> + }
> }
>
> static void
> diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
> index 3ae3e53530b..035637f81f8 100644
> --- a/hw/net/igb_core.c
> +++ b/hw/net/igb_core.c
> @@ -171,12 +171,17 @@ static void
> igb_intrmgr_on_msix_throttling_timer(void *opaque)
> {
> IGBIntrDelayTimer *timer = opaque;
> - int idx = timer - &timer->core->eitr[0];
> + IGBCore *core = timer->core;
> + int vector = timer - &core->eitr[0];
> + uint32_t causes;
>
> timer->running = false;
>
> - trace_e1000e_irq_msix_notify_postponed_vec(idx);
> - igb_msix_notify(timer->core, idx);
> + causes = core->mac[EICR] & core->mac[EIMS];
> + if (causes & BIT(vector)) {
> + trace_e1000e_irq_msix_notify_postponed_vec(vector);
> + igb_msix_notify(core, vector);
> + }
> }
>
> static void