From f02361822f73f28a4279783fdfb581c500660a36 Mon Sep 17 00:00:00 2001 From: Edgar E. Iglesias Date: Thu, 11 Oct 2018 04:19:22 +0200 Subject: net: cadence_gem: Use uint32_t for 32bit descriptor words Use uint32_t instead of unsigned to describe 32bit descriptor words. Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Edgar E. Iglesias Message-id: 20181011021931.4249-4-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- include/hw/net/cadence_gem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h index 35de622063..633d564dc3 100644 --- a/include/hw/net/cadence_gem.h +++ b/include/hw/net/cadence_gem.h @@ -74,7 +74,7 @@ typedef struct CadenceGEMState { uint8_t can_rx_state; /* Debug only */ - unsigned rx_desc[MAX_PRIORITY_QUEUES][2]; + uint32_t rx_desc[MAX_PRIORITY_QUEUES][2]; bool sar_active[4]; } CadenceGEMState; -- cgit v1.2.3-55-g7522 From 8568313f3bdf4bc1de7ace0eb5b92343fc19f3c8 Mon Sep 17 00:00:00 2001 From: Edgar E. Iglesias Date: Thu, 11 Oct 2018 04:19:23 +0200 Subject: net: cadence_gem: Add macro with max number of descriptor words Add macro with max number of DMA descriptor words. No functional change. Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Edgar E. Iglesias Message-id: 20181011021931.4249-5-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 4 ++-- include/hw/net/cadence_gem.h | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index d67249393c..a59a36eb5a 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1042,7 +1042,7 @@ static void gem_transmit_updatestats(CadenceGEMState *s, const uint8_t *packet, */ static void gem_transmit(CadenceGEMState *s) { - uint32_t desc[2]; + uint32_t desc[DESC_MAX_NUM_WORDS]; hwaddr packet_desc_addr; uint8_t tx_packet[2048]; uint8_t *p; @@ -1108,7 +1108,7 @@ static void gem_transmit(CadenceGEMState *s) /* Last descriptor for this packet; hand the whole thing off */ if (tx_desc_get_last(desc)) { - uint32_t desc_first[2]; + uint32_t desc_first[DESC_MAX_NUM_WORDS]; /* Modify the 1st descriptor of this packet to be owned by * the processor. diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h index 633d564dc3..b33ef6513b 100644 --- a/include/hw/net/cadence_gem.h +++ b/include/hw/net/cadence_gem.h @@ -32,6 +32,9 @@ #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 MAX_PRIORITY_QUEUES 8 #define MAX_TYPE1_SCREENERS 16 #define MAX_TYPE2_SCREENERS 16 @@ -74,7 +77,7 @@ typedef struct CadenceGEMState { uint8_t can_rx_state; /* Debug only */ - uint32_t rx_desc[MAX_PRIORITY_QUEUES][2]; + uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS]; bool sar_active[4]; } CadenceGEMState; -- cgit v1.2.3-55-g7522 From e48fdd9d90423d1530b49bbd61b4bbcb49198b33 Mon Sep 17 00:00:00 2001 From: Edgar E. Iglesias Date: Thu, 11 Oct 2018 04:19:24 +0200 Subject: net: cadence_gem: Add support for extended descriptors 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). Reviewed-by: Alistair Francis Signed-off-by: Edgar E. Iglesias Message-id: 20181011021931.4249-6-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 69 ++++++++++++++++++++++++++++++++------------ include/hw/net/cadence_gem.h | 2 +- 2 files changed, 52 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index a59a36eb5a..fa79baf608 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 b33ef6513b..00dbf4f72e 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 -- cgit v1.2.3-55-g7522 From 84aec8efd62052f6aeda570b328bc3ac484a1d30 Mon Sep 17 00:00:00 2001 From: Edgar E. Iglesias Date: Thu, 11 Oct 2018 04:19:25 +0200 Subject: net: cadence_gem: Add support for selecting the DMA MemoryRegion Add support for selecting the Memory Region that the GEM will do DMA to. Signed-off-by: Edgar E. Iglesias Reviewed-by: Alistair Francis Message-id: 20181011021931.4249-7-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 59 +++++++++++++++++++++++++++----------------- include/hw/net/cadence_gem.h | 2 ++ 2 files changed, 39 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index fa79baf608..3ea20d4b4f 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -28,6 +28,7 @@ #include "hw/net/cadence_gem.h" #include "qapi/error.h" #include "qemu/log.h" +#include "sysemu/dma.h" #include "net/checksum.h" #ifdef CADENCE_GEM_ERR_DEBUG @@ -835,9 +836,9 @@ 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(uint32_t) * gem_get_desc_len(s, true)); + address_space_read(&s->dma_as, s->rx_desc_addr[q], MEMTXATTRS_UNSPECIFIED, + (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) { @@ -956,10 +957,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, s->rx_desc[q]) + + address_space_write(&s->dma_as, rx_desc_get_buffer(s, s->rx_desc[q]) + rxbuf_offset, - rxbuf_ptr, - MIN(bytes_to_copy, rxbufsize)); + MEMTXATTRS_UNSPECIFIED, rxbuf_ptr, + MIN(bytes_to_copy, rxbufsize)); rxbuf_ptr += MIN(bytes_to_copy, rxbufsize); bytes_to_copy -= MIN(bytes_to_copy, rxbufsize); @@ -993,9 +994,10 @@ 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(uint32_t) * gem_get_desc_len(s, true)); + address_space_write(&s->dma_as, s->rx_desc_addr[q], + MEMTXATTRS_UNSPECIFIED, + (uint8_t *)s->rx_desc[q], + sizeof(uint32_t) * gem_get_desc_len(s, true)); /* Next descriptor */ if (rx_desc_get_wrap(s->rx_desc[q])) { @@ -1099,9 +1101,9 @@ static void gem_transmit(CadenceGEMState *s) packet_desc_addr = s->tx_desc_addr[q]; DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr); - cpu_physical_memory_read(packet_desc_addr, - (uint8_t *)desc, - sizeof(uint32_t) * gem_get_desc_len(s, false)); + address_space_read(&s->dma_as, packet_desc_addr, + MEMTXATTRS_UNSPECIFIED, (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) { @@ -1133,8 +1135,9 @@ 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(s, desc), p, - tx_desc_get_length(desc)); + address_space_read(&s->dma_as, tx_desc_get_buffer(s, desc), + MEMTXATTRS_UNSPECIFIED, + p, tx_desc_get_length(desc)); p += tx_desc_get_length(desc); total_bytes += tx_desc_get_length(desc); @@ -1145,13 +1148,15 @@ static void gem_transmit(CadenceGEMState *s) /* Modify the 1st descriptor of this packet to be owned by * the processor. */ - cpu_physical_memory_read(s->tx_desc_addr[q], - (uint8_t *)desc_first, - sizeof(desc_first)); + address_space_read(&s->dma_as, s->tx_desc_addr[q], + MEMTXATTRS_UNSPECIFIED, + (uint8_t *)desc_first, + sizeof(desc_first)); tx_desc_set_used(desc_first); - cpu_physical_memory_write(s->tx_desc_addr[q], - (uint8_t *)desc_first, - sizeof(desc_first)); + address_space_write(&s->dma_as, s->tx_desc_addr[q], + MEMTXATTRS_UNSPECIFIED, + (uint8_t *)desc_first, + sizeof(desc_first)); /* Advance the hardware current descriptor past this packet */ if (tx_desc_get_wrap(desc)) { s->tx_desc_addr[q] = s->regs[GEM_TXQBASE]; @@ -1204,8 +1209,9 @@ static void gem_transmit(CadenceGEMState *s) 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(uint32_t) * gem_get_desc_len(s, false)); + address_space_read(&s->dma_as, packet_desc_addr, + MEMTXATTRS_UNSPECIFIED, (uint8_t *)desc, + sizeof(uint32_t) * gem_get_desc_len(s, false)); } if (tx_desc_get_used(desc)) { @@ -1496,6 +1502,9 @@ static void gem_realize(DeviceState *dev, Error **errp) CadenceGEMState *s = CADENCE_GEM(dev); int i; + address_space_init(&s->dma_as, + s->dma_mr ? s->dma_mr : get_system_memory(), "dma"); + if (s->num_priority_queues == 0 || s->num_priority_queues > MAX_PRIORITY_QUEUES) { error_setg(errp, "Invalid num-priority-queues value: %" PRIx8, @@ -1533,6 +1542,12 @@ static void gem_init(Object *obj) "enet", sizeof(s->regs)); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + + object_property_add_link(obj, "dma", TYPE_MEMORY_REGION, + (Object **)&s->dma_mr, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG, + &error_abort); } static const VMStateDescription vmstate_cadence_gem = { diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h index 00dbf4f72e..5426961d91 100644 --- a/include/hw/net/cadence_gem.h +++ b/include/hw/net/cadence_gem.h @@ -45,6 +45,8 @@ typedef struct CadenceGEMState { /*< public >*/ MemoryRegion iomem; + MemoryRegion *dma_mr; + AddressSpace dma_as; NICState *nic; NICConf conf; qemu_irq irq[MAX_PRIORITY_QUEUES]; -- cgit v1.2.3-55-g7522