[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH 03/13] imx_fec: Change queue flushing heuristics
From: |
Andrey Smirnov |
Subject: |
[Qemu-arm] [PATCH 03/13] imx_fec: Change queue flushing heuristics |
Date: |
Mon, 11 Dec 2017 13:29:57 -0800 |
In current implementation, packet queue flushing logic seem to suffer
from a deadlock like scenario if a packet is received by the interface
before before Rx ring is initialized by Guest's driver. Consider the
following sequence of events:
1. A QEMU instance is started against a TAP device on Linux
host, running Linux guest, e. g., something to the effect
of:
qemu-system-arm \
-net nic,model=imx.fec,netdev=lan0 \
netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
... rest of the arguments ...
2. Once QEMU starts, but before guest reaches the point where
FEC deriver is done initializing the HW, Guest, via TAP
interface, receives a number of multicast MDNS packets from
Host (not necessarily true for every OS, but it happens at
least on Fedora 25)
3. Recieving a packet in such a state results in
imx_eth_can_receive() returning '0', which in turn causes
tap_send() to disable corresponding event (tap.c:203)
4. Once Guest's driver reaches the point where it is ready to
recieve packets it prepares Rx ring descriptors and writes
ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
more descriptors are ready. And at this points emulation
layer does this:
s->regs[index] = ENET_RDAR_RDAR;
imx_eth_enable_rx(s);
which, combined with:
if (!s->regs[ENET_RDAR]) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
results in Rx queue never being flushed and corresponding
I/O event beign disabled.
To prevent the problem, change the code to always flush packet queue
when ENET_RDAR transitions 0 -> ENET_RDAR_RDAR.
Cc: Peter Maydell <address@hidden>
Cc: Jason Wang <address@hidden>
Cc: Philippe Mathieu-Daudé <address@hidden>
Cc: address@hidden
Cc: address@hidden
Cc: address@hidden
Reviewed-by: Peter Maydell <address@hidden>
Signed-off-by: Andrey Smirnov <address@hidden>
---
hw/net/imx_fec.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 8b2e4b8ffe..eb034ffd0c 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -533,7 +533,7 @@ static void imx_eth_do_tx(IMXFECState *s)
}
}
-static void imx_eth_enable_rx(IMXFECState *s)
+static void imx_eth_enable_rx(IMXFECState *s, bool flush)
{
IMXFECBufDesc bd;
bool rx_ring_full;
@@ -544,7 +544,7 @@ static void imx_eth_enable_rx(IMXFECState *s)
if (rx_ring_full) {
FEC_PRINTF("RX buffer full\n");
- } else if (!s->regs[ENET_RDAR]) {
+ } else if (flush) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
@@ -807,7 +807,7 @@ static void imx_eth_write(void *opaque, hwaddr offset,
uint64_t value,
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
if (!s->regs[index]) {
s->regs[index] = ENET_RDAR_RDAR;
- imx_eth_enable_rx(s);
+ imx_eth_enable_rx(s, true);
}
} else {
s->regs[index] = 0;
@@ -930,7 +930,7 @@ static int imx_eth_can_receive(NetClientState *nc)
FEC_PRINTF("\n");
- return s->regs[ENET_RDAR] ? 1 : 0;
+ return !!s->regs[ENET_RDAR];
}
static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
@@ -1020,7 +1020,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const
uint8_t *buf,
}
}
s->rx_descriptor = addr;
- imx_eth_enable_rx(s);
+ imx_eth_enable_rx(s, false);
imx_eth_update(s);
return len;
}
@@ -1116,7 +1116,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const
uint8_t *buf,
}
}
s->rx_descriptor = addr;
- imx_eth_enable_rx(s);
+ imx_eth_enable_rx(s, false);
imx_eth_update(s);
return len;
}
--
2.14.3
- [Qemu-arm] [PATCH 00/13] i.MX FEC and SD changes, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 01/13] imx_fec: Do not link to netdev, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 02/13] imx_fec: Refactor imx_eth_enable_rx(), Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 04/13] imx_fec: Move Tx frame buffer away from the stack, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 05/13] imx_fec: Use ENET_FTRL to determine truncation length, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 03/13] imx_fec: Change queue flushing heuristics,
Andrey Smirnov <=
- [Qemu-arm] [PATCH 06/13] imx_fec: Use MIN instead of explicit ternary operator, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 07/13] imx_fec: Emulate SHIFT16 in ENETx_RACC, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 08/13] imx_fec: Add support for multiple Tx DMA rings, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 09/13] imx_fec: Use correct length for packet size, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 13/13] sdhci: Implement write method of ACMD12ERRSTS register, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 11/13] imx_fec: Reserve full FSL_IMX25_FEC_SIZE page for the register file, Andrey Smirnov, 2017/12/11
- [Qemu-arm] [PATCH 12/13] sdhci: Add i.MX specific subtype of SDHCI, Andrey Smirnov, 2017/12/11