In loopback mode, e1000e RX can DMA into TX doorbell which requires TX to be reentrant. This patch make e1000e's TX routine reentrant by introducing a per device boolean for recording whether or not a TX rountine is being called and return early.
Signed-off-by: Jason Wang <jasow...@redhat.com> --- hw/net/e1000e_core.c | 8 ++++++++ hw/net/e1000e_core.h | 1 + 2 files changed, 9 insertions(+) diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index bcd186cac5..8126a644a5 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -923,6 +923,12 @@ e1000e_start_xmit(E1000ECore *core, const E1000E_TxRing *txr) return; } + if (core->sending) { + return; + } + + core->sending = true; + while (!e1000e_ring_empty(core, txi)) { base = e1000e_ring_head_descr(core, txi); @@ -940,6 +946,8 @@ e1000e_start_xmit(E1000ECore *core, const E1000E_TxRing *txr) if (!ide || !e1000e_intrmgr_delay_tx_causes(core, &cause)) { e1000e_set_interrupt_cause(core, cause); } + + core->sending = false; } static bool diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h index aee32f7e48..4679c1761f 100644 --- a/hw/net/e1000e_core.h +++ b/hw/net/e1000e_core.h @@ -114,6 +114,7 @@ struct E1000Core { void (*owner_start_recv)(PCIDevice *d); uint32_t msi_causes_pending; + bool sending; }; void -- 2.20.1