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 <npig...@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); + 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 -- 2.47.1