aboutsummaryrefslogtreecommitdiff
path: root/hw/net
diff options
context:
space:
mode:
authorMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2019-06-30 18:21:50 +0100
committerMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2019-07-02 22:49:08 +0100
commit09340f497e96a62d076b2f223e7b16a7358cfecb (patch)
treed719603d5767d08482925e092698fb8bbdbe6617 /hw/net
parent29df47a5cc4133a31259c24ffdf26bf25080558a (diff)
downloadqemu-09340f497e96a62d076b2f223e7b16a7358cfecb.zip
qemu-09340f497e96a62d076b2f223e7b16a7358cfecb.tar.gz
qemu-09340f497e96a62d076b2f223e7b16a7358cfecb.tar.bz2
sunhme: ensure that RX descriptor ring overflow is indicated to client driver
On very busy networks connected via a tap interface, it is possible to overflow the RX descriptor ring in the time between the client driver enabling the RX MAC and finishing writing the final configuration to the NIC registers. Ensure that we detect this condition and update the status register accordingly to indicate an overflow has occurred (and the incoming packet dropped) in order to prevent the client driver becoming confused. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Diffstat (limited to 'hw/net')
-rw-r--r--hw/net/sunhme.c9
-rw-r--r--hw/net/trace-events1
2 files changed, 10 insertions, 0 deletions
diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c
index cd076d6..8b8603e 100644
--- a/hw/net/sunhme.c
+++ b/hw/net/sunhme.c
@@ -44,6 +44,7 @@
#define HME_SEBI_STAT 0x100
#define HME_SEBI_STAT_LINUXBUG 0x108
#define HME_SEB_STAT_RXTOHOST 0x10000
+#define HME_SEB_STAT_NORXD 0x20000
#define HME_SEB_STAT_MIFIRQ 0x800000
#define HME_SEB_STAT_HOSTTOTX 0x1000000
#define HME_SEB_STAT_TXALL 0x2000000
@@ -787,6 +788,14 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,
pci_dma_read(d, rb + cr * HME_DESC_SIZE, &status, 4);
pci_dma_read(d, rb + cr * HME_DESC_SIZE + 4, &buffer, 4);
+ /* If we don't own the current descriptor then indicate overflow error */
+ if (!(status & HME_XD_OWN)) {
+ s->sebregs[HME_SEBI_STAT >> 2] |= HME_SEB_STAT_NORXD;
+ sunhme_update_irq(s);
+ trace_sunhme_rx_norxd();
+ return -1;
+ }
+
rxoffset = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_BYTEOFFSET) >>
HME_ERX_CFG_BYTEOFFSET_SHIFT;
diff --git a/hw/net/trace-events b/hw/net/trace-events
index d16273c..5866565 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -359,6 +359,7 @@ sunhme_rx_filter_reject(void) "rejecting incoming frame"
sunhme_rx_filter_accept(void) "accepting incoming frame"
sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int nr) "addr 0x%"PRIx32"(+0x%x) status 0x%"PRIx32 " len %d (ring %d/%d)"
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"
+sunhme_rx_norxd(void) "no free rx descriptors available"
sunhme_update_irq(uint32_t mifmask, uint32_t mif, uint32_t sebmask, uint32_t seb, int level) "mifmask: 0x%x mif: 0x%x sebmask: 0x%x seb: 0x%x level: %d"
# virtio-net.c