qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PULL 20/37] net/cadence_gem: Prefetch rx descriptors ASAP


From: Peter Maydell
Subject: [Qemu-devel] [PULL 20/37] net/cadence_gem: Prefetch rx descriptors ASAP
Date: Tue, 10 Dec 2013 14:43:16 +0000

From: Peter Crosthwaite <address@hidden>

The real hardware prefetches rx buffer descriptors ASAP and
potentially throws relevant interrupts following the fetch
even in the absence of a received packet.

Reported-by: Deepika Dhamija <address@hidden>
Signed-off-by: Peter Crosthwaite <address@hidden>
Message-id: address@hidden
Signed-off-by: Peter Maydell <address@hidden>
---
 hw/net/cadence_gem.c | 62 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 35 insertions(+), 27 deletions(-)

diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 69ad87e..6734a9d 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -346,6 +346,8 @@ typedef struct GemState {
     uint32_t rx_desc_addr;
     uint32_t tx_desc_addr;
 
+    unsigned rx_desc[2];
+
 } GemState;
 
 /* The broadcast MAC address: 0xFFFFFFFFFFFF */
@@ -579,13 +581,30 @@ static int gem_mac_address_filter(GemState *s, const 
uint8_t *packet)
     return GEM_RX_REJECT;
 }
 
+static void gem_get_rx_desc(GemState *s)
+{
+    DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr);
+    /* read current descriptor */
+    cpu_physical_memory_read(s->rx_desc_addr,
+                             (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
+
+    /* Descriptor owned by software ? */
+    if (rx_desc_get_ownership(s->rx_desc) == 1) {
+        DB_PRINT("descriptor 0x%x owned by sw.\n",
+                 (unsigned)s->rx_desc_addr);
+        s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
+        s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
+        /* Handle interrupt consequences */
+        gem_update_int_status(s);
+    }
+}
+
 /*
  * gem_receive:
  * Fit a packet handed to us by QEMU into the receive descriptor ring.
  */
 static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 {
-    unsigned    desc[2];
     GemState *s;
     unsigned   rxbufsize, bytes_to_copy;
     unsigned   rxbuf_offset;
@@ -595,11 +614,6 @@ static ssize_t gem_receive(NetClientState *nc, const 
uint8_t *buf, size_t size)
 
     s = qemu_get_nic_opaque(nc);
 
-    /* Do nothing if receive is not enabled. */
-    if (!gem_can_receive(nc)) {
-        return -1;
-    }
-
     /* Is this destination MAC address "for us" ? */
     if (gem_mac_address_filter(s, buf) == GEM_RX_REJECT) {
         return -1;
@@ -667,53 +681,44 @@ static ssize_t gem_receive(NetClientState *nc, const 
uint8_t *buf, size_t size)
     DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
 
     while (bytes_to_copy) {
-        DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr);
-        /* read current descriptor */
-        cpu_physical_memory_read(s->rx_desc_addr,
-                                 (uint8_t *)&desc[0], sizeof(desc));
-
-        /* Descriptor owned by software ? */
-        if (rx_desc_get_ownership(desc) == 1) {
-            DB_PRINT("descriptor 0x%x owned by sw.\n",
-                     (unsigned)s->rx_desc_addr);
-            s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
-            s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
-            /* Handle interrupt consequences */
-            gem_update_int_status(s);
+        /* Do nothing if receive is not enabled. */
+        if (!gem_can_receive(nc)) {
+            assert(!first_desc);
             return -1;
         }
 
         DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
-                rx_desc_get_buffer(desc));
+                rx_desc_get_buffer(s->rx_desc));
 
         /* Copy packet data to emulated DMA buffer */
-        cpu_physical_memory_write(rx_desc_get_buffer(desc) + rxbuf_offset,
+        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + 
rxbuf_offset,
                                   rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
         bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
         rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
 
         /* Update the descriptor.  */
         if (first_desc) {
-            rx_desc_set_sof(desc);
+            rx_desc_set_sof(s->rx_desc);
             first_desc = false;
         }
         if (bytes_to_copy == 0) {
-            rx_desc_set_eof(desc);
-            rx_desc_set_length(desc, size);
+            rx_desc_set_eof(s->rx_desc);
+            rx_desc_set_length(s->rx_desc, size);
         }
-        rx_desc_set_ownership(desc);
+        rx_desc_set_ownership(s->rx_desc);
         /* Descriptor write-back.  */
         cpu_physical_memory_write(s->rx_desc_addr,
-                                  (uint8_t *)&desc[0], sizeof(desc));
+                                  (uint8_t *)s->rx_desc, sizeof(s->rx_desc));
 
         /* Next descriptor */
-        if (rx_desc_get_wrap(desc)) {
+        if (rx_desc_get_wrap(s->rx_desc)) {
             DB_PRINT("wrapping RX descriptor list\n");
             s->rx_desc_addr = s->regs[GEM_RXQBASE];
         } else {
             DB_PRINT("incrementing RX descriptor list\n");
             s->rx_desc_addr += 8;
         }
+        gem_get_rx_desc(s);
     }
 
     /* Count it */
@@ -1053,6 +1058,9 @@ static void gem_write(void *opaque, hwaddr offset, 
uint64_t val,
     /* Handle register write side effects */
     switch (offset) {
     case GEM_NWCTRL:
+        if (val & GEM_NWCTRL_RXENA) {
+            gem_get_rx_desc(s);
+        }
         if (val & GEM_NWCTRL_TXSTART) {
             gem_transmit(s);
         }
-- 
1.8.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]