|
|
76daa3 |
From fbe69a4c6ee947f375ac5b2572e0fc4ea9763095 Mon Sep 17 00:00:00 2001
|
|
|
76daa3 |
From: "sjubran@redhat.com" <sjubran@redhat.com>
|
|
|
76daa3 |
Date: Tue, 23 May 2017 14:35:59 +0200
|
|
|
76daa3 |
Subject: [PATCH 1/6] e1000e: Fix ICR "Other" causes clear logic
|
|
|
76daa3 |
|
|
|
76daa3 |
RH-Author: sjubran@redhat.com
|
|
|
76daa3 |
Message-id: <20170523143559.28622-1-sjubran@redhat.com>
|
|
|
76daa3 |
Patchwork-id: 75399
|
|
|
76daa3 |
O-Subject: [PATCH] e1000e: Fix ICR "Other" causes clear logic
|
|
|
76daa3 |
Bugzilla: 1449490
|
|
|
76daa3 |
RH-Acked-by: Dmitry Fleytman <dfleytma@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Vlad Yasevich <vyasevic@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
|
|
|
76daa3 |
|
|
|
76daa3 |
From: Sameeh Jubran <sameeh@daynix.com>
|
|
|
76daa3 |
|
|
|
76daa3 |
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1449490
|
|
|
76daa3 |
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=13256116
|
|
|
76daa3 |
upstream: maintainer's tree
|
|
|
76daa3 |
|
|
|
76daa3 |
This commit fixes a bug which causes the guest to hang. The bug was
|
|
|
76daa3 |
observed upon a "receive overrun" (bit #6 of the ICR register)
|
|
|
76daa3 |
interrupt which could be triggered post migration in a heavy traffic
|
|
|
76daa3 |
environment. Even though the "receive overrun" bit (#6) is masked out
|
|
|
76daa3 |
by the IMS register (refer to the log below) the driver still receives
|
|
|
76daa3 |
an interrupt as the "receive overrun" bit (#6) causes the "Other" -
|
|
|
76daa3 |
bit #24 of the ICR register - bit to be set as documented below. The
|
|
|
76daa3 |
driver handles the interrupt and clears the "Other" bit (#24) but
|
|
|
76daa3 |
doesn't clear the "receive overrun" bit (#6) which leads to an
|
|
|
76daa3 |
infinite loop. Apparently the Windows driver expects that the "receive
|
|
|
76daa3 |
overrun" bit and other ones - documented below - to be cleared when
|
|
|
76daa3 |
the "Other" bit (#24) is cleared.
|
|
|
76daa3 |
|
|
|
76daa3 |
So to sum that up:
|
|
|
76daa3 |
1. Bit #6 of the ICR register is set by heavy traffic
|
|
|
76daa3 |
2. As a results of setting bit #6, bit #24 is set
|
|
|
76daa3 |
3. The driver receives an interrupt for bit 24 (it doesn't receieve an
|
|
|
76daa3 |
interrupt for bit #6 as it is masked out by IMS)
|
|
|
76daa3 |
4. The driver handles and clears the interrupt of bit #24
|
|
|
76daa3 |
5. Bit #6 is still set.
|
|
|
76daa3 |
6. 2 happens all over again
|
|
|
76daa3 |
|
|
|
76daa3 |
The Interrupt Cause Read - ICR register:
|
|
|
76daa3 |
|
|
|
76daa3 |
The ICR has the "Other" bit - bit #24 - that is set when one or more
|
|
|
76daa3 |
of the following ICR register's bits are set:
|
|
|
76daa3 |
|
|
|
76daa3 |
LSC - bit #2, RXO - bit #6, MDAC - bit #9, SRPD - bit #16, ACK - bit
|
|
|
76daa3 |
|
|
|
76daa3 |
This bug can occur with any of these bits depending on the driver's
|
|
|
76daa3 |
behaviour and the way it configures the device. However, trying to
|
|
|
76daa3 |
reproduce it with any bit other than RX0 is challenging and came to
|
|
|
76daa3 |
failure as the drivers don't implement most of these bits, trying to
|
|
|
76daa3 |
reproduce it with LSC (Link Status Change - bit #2) bit didn't succeed
|
|
|
76daa3 |
too as it seems that Windows handles this bit differently.
|
|
|
76daa3 |
|
|
|
76daa3 |
Log sample of the storm:
|
|
|
76daa3 |
|
|
|
76daa3 |
27563@1494850819.411877:e1000e_irq_pending_interrupts ICR PENDING: 0x1000000 (ICR: 0x815000c2, IMS: 0x1a00004)
|
|
|
76daa3 |
27563@1494850819.411900:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
|
|
|
76daa3 |
27563@1494850819.411915:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
|
|
|
76daa3 |
27563@1494850819.412380:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
|
|
|
76daa3 |
27563@1494850819.412395:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
|
|
|
76daa3 |
27563@1494850819.412436:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
|
|
|
76daa3 |
27563@1494850819.412441:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
|
|
|
76daa3 |
27563@1494850819.412998:e1000e_irq_pending_interrupts ICR PENDING: 0x1000000 (ICR: 0x815000c2, IMS: 0x1a00004)
|
|
|
76daa3 |
|
|
|
76daa3 |
* This bug behaviour wasn't observed with the Linux driver.
|
|
|
76daa3 |
|
|
|
76daa3 |
This commit solves:
|
|
|
76daa3 |
https://bugzilla.redhat.com/show_bug.cgi?id=1447935
|
|
|
76daa3 |
https://bugzilla.redhat.com/show_bug.cgi?id=1449490
|
|
|
76daa3 |
|
|
|
76daa3 |
Cc: qemu-stable@nongnu.org
|
|
|
76daa3 |
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
|
|
|
76daa3 |
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
|
|
76daa3 |
(cherry picked from commit 82342e91b60a4a078811df4e1a545e57abffa11d)
|
|
|
76daa3 |
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
|
|
|
76daa3 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
76daa3 |
---
|
|
|
76daa3 |
hw/net/e1000e_core.c | 10 ++++++++--
|
|
|
76daa3 |
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
76daa3 |
|
|
|
76daa3 |
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
|
|
|
76daa3 |
index 28c5be1..8140564 100644
|
|
|
76daa3 |
--- a/hw/net/e1000e_core.c
|
|
|
76daa3 |
+++ b/hw/net/e1000e_core.c
|
|
|
76daa3 |
@@ -2454,14 +2454,20 @@ e1000e_set_ics(E1000ECore *core, int index, uint32_t val)
|
|
|
76daa3 |
static void
|
|
|
76daa3 |
e1000e_set_icr(E1000ECore *core, int index, uint32_t val)
|
|
|
76daa3 |
{
|
|
|
76daa3 |
+ uint32_t icr = 0;
|
|
|
76daa3 |
if ((core->mac[ICR] & E1000_ICR_ASSERTED) &&
|
|
|
76daa3 |
(core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
|
|
|
76daa3 |
trace_e1000e_irq_icr_process_iame();
|
|
|
76daa3 |
e1000e_clear_ims_bits(core, core->mac[IAM]);
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
- trace_e1000e_irq_icr_write(val, core->mac[ICR], core->mac[ICR] & ~val);
|
|
|
76daa3 |
- core->mac[ICR] &= ~val;
|
|
|
76daa3 |
+ icr = core->mac[ICR] & ~val;
|
|
|
76daa3 |
+ /* Windows driver expects that the "receive overrun" bit and other
|
|
|
76daa3 |
+ * ones to be cleared when the "Other" bit (#24) is cleared.
|
|
|
76daa3 |
+ */
|
|
|
76daa3 |
+ icr = (val & E1000_ICR_OTHER) ? (icr & ~E1000_ICR_OTHER_CAUSES) : icr;
|
|
|
76daa3 |
+ trace_e1000e_irq_icr_write(val, core->mac[ICR], icr);
|
|
|
76daa3 |
+ core->mac[ICR] = icr;
|
|
|
76daa3 |
e1000e_update_interrupt_state(core);
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
--
|
|
|
76daa3 |
1.8.3.1
|
|
|
76daa3 |
|