diff mbox series

[v1,05/12] net: cadence_gem: Add support for extended descriptors

Message ID 1538579266-8389-6-git-send-email-edgar.iglesias@gmail.com (mailing list archive)
State New, archived
Headers show
Series arm: Add first models of Xilinx Versal SoC | expand

Commit Message

Edgar E. Iglesias Oct. 3, 2018, 3:07 p.m. UTC
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Add support for extended descriptors with optional 64bit
addressing and timestamping. QEMU will not yet provide
timestamps (always leaving the valid timestamp bit as zero).

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 hw/net/cadence_gem.c         | 69 ++++++++++++++++++++++++++++++++------------
 include/hw/net/cadence_gem.h |  2 +-
 2 files changed, 52 insertions(+), 19 deletions(-)

Comments

Alistair Francis Oct. 4, 2018, 10:29 p.m. UTC | #1
On 10/03/2018 08:07 AM, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> 
> Add support for extended descriptors with optional 64bit
> addressing and timestamping. QEMU will not yet provide
> timestamps (always leaving the valid timestamp bit as zero).
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>   hw/net/cadence_gem.c         | 69 ++++++++++++++++++++++++++++++++------------
>   include/hw/net/cadence_gem.h |  2 +-
>   2 files changed, 52 insertions(+), 19 deletions(-)
> 
> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
> index 4d769b0..759c1d7 100644
> --- a/hw/net/cadence_gem.c
> +++ b/hw/net/cadence_gem.c
> @@ -207,6 +207,9 @@
>   #define GEM_NWCFG_BCAST_REJ    0x00000020 /* Reject broadcast packets */
>   #define GEM_NWCFG_PROMISC      0x00000010 /* Accept all packets */
>   
> +#define GEM_DMACFG_ADDR_64B    (1U << 30)
> +#define GEM_DMACFG_TX_BD_EXT   (1U << 29)
> +#define GEM_DMACFG_RX_BD_EXT   (1U << 28)
>   #define GEM_DMACFG_RBUFSZ_M    0x00FF0000 /* DMA RX Buffer Size mask */
>   #define GEM_DMACFG_RBUFSZ_S    16         /* DMA RX Buffer Size shift */
>   #define GEM_DMACFG_RBUFSZ_MUL  64         /* DMA RX Buffer Size multiplier */
> @@ -302,9 +305,14 @@
>   
>   #define GEM_MODID_VALUE 0x00020118
>   
> -static inline unsigned tx_desc_get_buffer(uint32_t *desc)
> +static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc)
>   {
> -    return desc[0];
> +    uint64_t ret = desc[0];
> +
> +    if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
> +        ret |= (uint64_t)desc[2] << 32;
> +    }
> +    return ret;
>   }
>   
>   static inline unsigned tx_desc_get_used(uint32_t *desc)
> @@ -347,9 +355,30 @@ static inline void print_gem_tx_desc(uint32_t *desc, uint8_t queue)
>       DB_PRINT("length:  %d\n", tx_desc_get_length(desc));
>   }
>   
> -static inline unsigned rx_desc_get_buffer(uint32_t *desc)
> +static inline uint64_t rx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc)
>   {
> -    return desc[0] & ~0x3UL;
> +    uint64_t ret = desc[0] & ~0x3UL;
> +
> +    if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
> +        ret |= (uint64_t)desc[2] << 32;
> +    }
> +    return ret;
> +}
> +
> +static inline int gem_get_desc_len(CadenceGEMState *s, bool rx_n_tx)
> +{
> +    int ret = 2;
> +
> +    if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
> +        ret += 2;
> +    }
> +    if (s->regs[GEM_DMACFG] & (rx_n_tx ? GEM_DMACFG_RX_BD_EXT
> +                                       : GEM_DMACFG_TX_BD_EXT)) {
> +        ret += 2;
> +    }
> +
> +    assert(ret <= DESC_MAX_NUM_WORDS);
> +    return ret;
>   }
>   
>   static inline unsigned rx_desc_get_wrap(uint32_t *desc)
> @@ -419,7 +448,7 @@ static void gem_init_register_masks(CadenceGEMState *s)
>       memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
>       s->regs_ro[GEM_NWCTRL]   = 0xFFF80000;
>       s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF;
> -    s->regs_ro[GEM_DMACFG]   = 0xFE00F000;
> +    s->regs_ro[GEM_DMACFG]   = 0x8E00F000;
>       s->regs_ro[GEM_TXSTATUS] = 0xFFFFFE08;
>       s->regs_ro[GEM_RXQBASE]  = 0x00000003;
>       s->regs_ro[GEM_TXQBASE]  = 0x00000003;
> @@ -807,7 +836,8 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q)
>       DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]);
>       /* read current descriptor */
>       cpu_physical_memory_read(s->rx_desc_addr[q],
> -                             (uint8_t *)s->rx_desc[q], sizeof(s->rx_desc[q]));
> +                             (uint8_t *)s->rx_desc[q],
> +                             sizeof(uint32_t) * gem_get_desc_len(s, true));
>   
>       /* Descriptor owned by software ? */
>       if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
> @@ -926,9 +956,10 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
>                   rx_desc_get_buffer(s->rx_desc[q]));
>   
>           /* Copy packet data to emulated DMA buffer */
> -        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc[q]) +
> -                                                                 rxbuf_offset,
> -                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
> +        cpu_physical_memory_write(rx_desc_get_buffer(s, s->rx_desc[q]) +
> +                                                                  rxbuf_offset,
> +                                  rxbuf_ptr,
> +                                  MIN(bytes_to_copy, rxbufsize));
>           rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
>           bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
>   
> @@ -964,7 +995,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
>           /* Descriptor write-back.  */
>           cpu_physical_memory_write(s->rx_desc_addr[q],
>                                     (uint8_t *)s->rx_desc[q],
> -                                  sizeof(s->rx_desc[q]));
> +                                  sizeof(uint32_t) * gem_get_desc_len(s, true));
>   
>           /* Next descriptor */
>           if (rx_desc_get_wrap(s->rx_desc[q])) {
> @@ -972,7 +1003,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
>               s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
>           } else {
>               DB_PRINT("incrementing RX descriptor list\n");
> -            s->rx_desc_addr[q] += 8;
> +            s->rx_desc_addr[q] += 4 * gem_get_desc_len(s, true);
>           }
>   
>           gem_get_rx_desc(s, q);
> @@ -1069,7 +1100,8 @@ static void gem_transmit(CadenceGEMState *s)
>   
>           DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
>           cpu_physical_memory_read(packet_desc_addr,
> -                                 (uint8_t *)desc, sizeof(desc));
> +                                 (uint8_t *)desc,
> +                                 sizeof(uint32_t) * gem_get_desc_len(s, false));
>           /* Handle all descriptors owned by hardware */
>           while (tx_desc_get_used(desc) == 0) {
>   
> @@ -1082,7 +1114,7 @@ static void gem_transmit(CadenceGEMState *s)
>               /* The real hardware would eat this (and possibly crash).
>                * For QEMU let's lend a helping hand.
>                */
> -            if ((tx_desc_get_buffer(desc) == 0) ||
> +            if ((tx_desc_get_buffer(s, desc) == 0) ||
>                   (tx_desc_get_length(desc) == 0)) {
>                   DB_PRINT("Invalid TX descriptor @ 0x%x\n",
>                            (unsigned)packet_desc_addr);
> @@ -1101,7 +1133,7 @@ static void gem_transmit(CadenceGEMState *s)
>               /* Gather this fragment of the packet from "dma memory" to our
>                * contig buffer.
>                */
> -            cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
> +            cpu_physical_memory_read(tx_desc_get_buffer(s, desc), p,
>                                        tx_desc_get_length(desc));
>               p += tx_desc_get_length(desc);
>               total_bytes += tx_desc_get_length(desc);
> @@ -1124,7 +1156,8 @@ static void gem_transmit(CadenceGEMState *s)
>                   if (tx_desc_get_wrap(desc)) {
>                       s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
>                   } else {
> -                    s->tx_desc_addr[q] = packet_desc_addr + 8;
> +                    s->tx_desc_addr[q] = packet_desc_addr +
> +                                         4 * gem_get_desc_len(s, false);
>                   }
>                   DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
>   
> @@ -1168,11 +1201,11 @@ static void gem_transmit(CadenceGEMState *s)
>                   tx_desc_set_last(desc);
>                   packet_desc_addr = s->regs[GEM_TXQBASE];
>               } else {
> -                packet_desc_addr += 8;
> +                packet_desc_addr += 4 * gem_get_desc_len(s, false);
>               }
>               DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
> -            cpu_physical_memory_read(packet_desc_addr,
> -                                     (uint8_t *)desc, sizeof(desc));
> +            cpu_physical_memory_read(packet_desc_addr, (uint8_t *)desc,
> +                                sizeof(uint32_t) * gem_get_desc_len(s, false));
>           }
>   
>           if (tx_desc_get_used(desc)) {
> diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
> index b33ef65..00dbf4f 100644
> --- a/include/hw/net/cadence_gem.h
> +++ b/include/hw/net/cadence_gem.h
> @@ -33,7 +33,7 @@
>   #define CADENCE_GEM_MAXREG        (0x00000800 / 4) /* Last valid GEM address */
>   
>   /* Max number of words in a DMA descriptor.  */
> -#define DESC_MAX_NUM_WORDS              2
> +#define DESC_MAX_NUM_WORDS              6
>   
>   #define MAX_PRIORITY_QUEUES             8
>   #define MAX_TYPE1_SCREENERS             16
>
diff mbox series

Patch

diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 4d769b0..759c1d7 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -207,6 +207,9 @@ 
 #define GEM_NWCFG_BCAST_REJ    0x00000020 /* Reject broadcast packets */
 #define GEM_NWCFG_PROMISC      0x00000010 /* Accept all packets */
 
+#define GEM_DMACFG_ADDR_64B    (1U << 30)
+#define GEM_DMACFG_TX_BD_EXT   (1U << 29)
+#define GEM_DMACFG_RX_BD_EXT   (1U << 28)
 #define GEM_DMACFG_RBUFSZ_M    0x00FF0000 /* DMA RX Buffer Size mask */
 #define GEM_DMACFG_RBUFSZ_S    16         /* DMA RX Buffer Size shift */
 #define GEM_DMACFG_RBUFSZ_MUL  64         /* DMA RX Buffer Size multiplier */
@@ -302,9 +305,14 @@ 
 
 #define GEM_MODID_VALUE 0x00020118
 
-static inline unsigned tx_desc_get_buffer(uint32_t *desc)
+static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc)
 {
-    return desc[0];
+    uint64_t ret = desc[0];
+
+    if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
+        ret |= (uint64_t)desc[2] << 32;
+    }
+    return ret;
 }
 
 static inline unsigned tx_desc_get_used(uint32_t *desc)
@@ -347,9 +355,30 @@  static inline void print_gem_tx_desc(uint32_t *desc, uint8_t queue)
     DB_PRINT("length:  %d\n", tx_desc_get_length(desc));
 }
 
-static inline unsigned rx_desc_get_buffer(uint32_t *desc)
+static inline uint64_t rx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc)
 {
-    return desc[0] & ~0x3UL;
+    uint64_t ret = desc[0] & ~0x3UL;
+
+    if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
+        ret |= (uint64_t)desc[2] << 32;
+    }
+    return ret;
+}
+
+static inline int gem_get_desc_len(CadenceGEMState *s, bool rx_n_tx)
+{
+    int ret = 2;
+
+    if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
+        ret += 2;
+    }
+    if (s->regs[GEM_DMACFG] & (rx_n_tx ? GEM_DMACFG_RX_BD_EXT
+                                       : GEM_DMACFG_TX_BD_EXT)) {
+        ret += 2;
+    }
+
+    assert(ret <= DESC_MAX_NUM_WORDS);
+    return ret;
 }
 
 static inline unsigned rx_desc_get_wrap(uint32_t *desc)
@@ -419,7 +448,7 @@  static void gem_init_register_masks(CadenceGEMState *s)
     memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
     s->regs_ro[GEM_NWCTRL]   = 0xFFF80000;
     s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF;
-    s->regs_ro[GEM_DMACFG]   = 0xFE00F000;
+    s->regs_ro[GEM_DMACFG]   = 0x8E00F000;
     s->regs_ro[GEM_TXSTATUS] = 0xFFFFFE08;
     s->regs_ro[GEM_RXQBASE]  = 0x00000003;
     s->regs_ro[GEM_TXQBASE]  = 0x00000003;
@@ -807,7 +836,8 @@  static void gem_get_rx_desc(CadenceGEMState *s, int q)
     DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]);
     /* read current descriptor */
     cpu_physical_memory_read(s->rx_desc_addr[q],
-                             (uint8_t *)s->rx_desc[q], sizeof(s->rx_desc[q]));
+                             (uint8_t *)s->rx_desc[q],
+                             sizeof(uint32_t) * gem_get_desc_len(s, true));
 
     /* Descriptor owned by software ? */
     if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
@@ -926,9 +956,10 @@  static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
                 rx_desc_get_buffer(s->rx_desc[q]));
 
         /* Copy packet data to emulated DMA buffer */
-        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc[q]) +
-                                                                 rxbuf_offset,
-                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
+        cpu_physical_memory_write(rx_desc_get_buffer(s, s->rx_desc[q]) +
+                                                                  rxbuf_offset,
+                                  rxbuf_ptr,
+                                  MIN(bytes_to_copy, rxbufsize));
         rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
         bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
 
@@ -964,7 +995,7 @@  static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
         /* Descriptor write-back.  */
         cpu_physical_memory_write(s->rx_desc_addr[q],
                                   (uint8_t *)s->rx_desc[q],
-                                  sizeof(s->rx_desc[q]));
+                                  sizeof(uint32_t) * gem_get_desc_len(s, true));
 
         /* Next descriptor */
         if (rx_desc_get_wrap(s->rx_desc[q])) {
@@ -972,7 +1003,7 @@  static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
             s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
         } else {
             DB_PRINT("incrementing RX descriptor list\n");
-            s->rx_desc_addr[q] += 8;
+            s->rx_desc_addr[q] += 4 * gem_get_desc_len(s, true);
         }
 
         gem_get_rx_desc(s, q);
@@ -1069,7 +1100,8 @@  static void gem_transmit(CadenceGEMState *s)
 
         DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
         cpu_physical_memory_read(packet_desc_addr,
-                                 (uint8_t *)desc, sizeof(desc));
+                                 (uint8_t *)desc,
+                                 sizeof(uint32_t) * gem_get_desc_len(s, false));
         /* Handle all descriptors owned by hardware */
         while (tx_desc_get_used(desc) == 0) {
 
@@ -1082,7 +1114,7 @@  static void gem_transmit(CadenceGEMState *s)
             /* The real hardware would eat this (and possibly crash).
              * For QEMU let's lend a helping hand.
              */
-            if ((tx_desc_get_buffer(desc) == 0) ||
+            if ((tx_desc_get_buffer(s, desc) == 0) ||
                 (tx_desc_get_length(desc) == 0)) {
                 DB_PRINT("Invalid TX descriptor @ 0x%x\n",
                          (unsigned)packet_desc_addr);
@@ -1101,7 +1133,7 @@  static void gem_transmit(CadenceGEMState *s)
             /* Gather this fragment of the packet from "dma memory" to our
              * contig buffer.
              */
-            cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
+            cpu_physical_memory_read(tx_desc_get_buffer(s, desc), p,
                                      tx_desc_get_length(desc));
             p += tx_desc_get_length(desc);
             total_bytes += tx_desc_get_length(desc);
@@ -1124,7 +1156,8 @@  static void gem_transmit(CadenceGEMState *s)
                 if (tx_desc_get_wrap(desc)) {
                     s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
                 } else {
-                    s->tx_desc_addr[q] = packet_desc_addr + 8;
+                    s->tx_desc_addr[q] = packet_desc_addr +
+                                         4 * gem_get_desc_len(s, false);
                 }
                 DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
 
@@ -1168,11 +1201,11 @@  static void gem_transmit(CadenceGEMState *s)
                 tx_desc_set_last(desc);
                 packet_desc_addr = s->regs[GEM_TXQBASE];
             } else {
-                packet_desc_addr += 8;
+                packet_desc_addr += 4 * gem_get_desc_len(s, false);
             }
             DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
-            cpu_physical_memory_read(packet_desc_addr,
-                                     (uint8_t *)desc, sizeof(desc));
+            cpu_physical_memory_read(packet_desc_addr, (uint8_t *)desc,
+                                sizeof(uint32_t) * gem_get_desc_len(s, false));
         }
 
         if (tx_desc_get_used(desc)) {
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
index b33ef65..00dbf4f 100644
--- a/include/hw/net/cadence_gem.h
+++ b/include/hw/net/cadence_gem.h
@@ -33,7 +33,7 @@ 
 #define CADENCE_GEM_MAXREG        (0x00000800 / 4) /* Last valid GEM address */
 
 /* Max number of words in a DMA descriptor.  */
-#define DESC_MAX_NUM_WORDS              2
+#define DESC_MAX_NUM_WORDS              6
 
 #define MAX_PRIORITY_QUEUES             8
 #define MAX_TYPE1_SCREENERS             16