sunhme: ensure that RX descriptor ring overflow is indicated to client driver
authorMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Sun, 30 Jun 2019 17:21:50 +0000 (18:21 +0100)
committerMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Tue, 2 Jul 2019 21:49:08 +0000 (22:49 +0100)
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>
hw/net/sunhme.c
hw/net/trace-events

index cd076d642b3324441f12f23b44906270a45fee0b..8b8603e6962f92074dab715c289e581049e2cdd0 100644 (file)
@@ -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;
 
index d16273c5796b80949064b4f6223c12e76fe76c5d..58665655cc760d9f8a834d8e54e8a12883123c01 100644 (file)
@@ -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