diff options
author | Philippe Mathieu-Daudé | 2020-08-28 11:02:45 +0200 |
---|---|---|
committer | Peter Maydell | 2020-08-28 11:02:45 +0200 |
commit | 4757cb857934a5e2dcafe1f41e95233f5c0a878d (patch) | |
tree | 69a8e4c2a6df3f7762f2453917ed81a24b5f2fe8 /hw/net | |
parent | hw/sd/allwinner-sdhost: Use AddressSpace for DMA transfers (diff) | |
download | qemu-4757cb857934a5e2dcafe1f41e95233f5c0a878d.tar.gz qemu-4757cb857934a5e2dcafe1f41e95233f5c0a878d.tar.xz qemu-4757cb857934a5e2dcafe1f41e95233f5c0a878d.zip |
hw/net/allwinner-sun8i-emac: Use AddressSpace for DMA transfers
Allow the device to execute the DMA transfers in a different
AddressSpace.
The H3 SoC keeps using the system_memory address space,
but via the proper dma_memory_access() API.
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
Message-id: 20200814122907.27732-1-f4bug@amsat.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/net')
-rw-r--r-- | hw/net/allwinner-sun8i-emac.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c index 28637ff4c1..38d328587e 100644 --- a/hw/net/allwinner-sun8i-emac.c +++ b/hw/net/allwinner-sun8i-emac.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" +#include "qapi/error.h" #include "hw/sysbus.h" #include "migration/vmstate.h" #include "net/net.h" @@ -29,6 +30,7 @@ #include "net/checksum.h" #include "qemu/module.h" #include "exec/cpu-common.h" +#include "sysemu/dma.h" #include "hw/net/allwinner-sun8i-emac.h" /* EMAC register offsets */ @@ -337,12 +339,13 @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s) qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0); } -static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc, +static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s, + FrameDescriptor *desc, size_t min_size) { uint32_t paddr = desc->next; - cpu_physical_memory_read(paddr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, paddr, desc, sizeof(*desc)); if ((desc->status & DESC_STATUS_CTL) && (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) { @@ -352,7 +355,8 @@ static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc, } } -static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc, +static uint32_t allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s, + FrameDescriptor *desc, uint32_t start_addr, size_t min_size) { @@ -360,7 +364,7 @@ static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc, /* Note that the list is a cycle. Last entry points back to the head. */ while (desc_addr != 0) { - cpu_physical_memory_read(desc_addr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc)); if ((desc->status & DESC_STATUS_CTL) && (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) { @@ -379,20 +383,21 @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s, FrameDescriptor *desc, size_t min_size) { - return allwinner_sun8i_emac_get_desc(desc, s->rx_desc_curr, min_size); + return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size); } static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s, FrameDescriptor *desc, size_t min_size) { - return allwinner_sun8i_emac_get_desc(desc, s->tx_desc_head, min_size); + return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size); } -static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc, +static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s, + FrameDescriptor *desc, uint32_t phys_addr) { - cpu_physical_memory_write(phys_addr, desc, sizeof(*desc)); + dma_memory_write(&s->dma_as, phys_addr, desc, sizeof(*desc)); } static bool allwinner_sun8i_emac_can_receive(NetClientState *nc) @@ -450,8 +455,8 @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc, << RX_DESC_STATUS_FRM_LEN_SHIFT; } - cpu_physical_memory_write(desc.addr, buf, desc_bytes); - allwinner_sun8i_emac_flush_desc(&desc, s->rx_desc_curr); + dma_memory_write(&s->dma_as, desc.addr, buf, desc_bytes); + allwinner_sun8i_emac_flush_desc(s, &desc, s->rx_desc_curr); trace_allwinner_sun8i_emac_receive(s->rx_desc_curr, desc.addr, desc_bytes); @@ -465,7 +470,7 @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc, bytes_left -= desc_bytes; /* Move to the next descriptor */ - s->rx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 64); + s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64); if (!s->rx_desc_curr) { /* Not enough buffer space available */ s->int_sta |= INT_STA_RX_BUF_UA; @@ -501,10 +506,10 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s) desc.status |= TX_DESC_STATUS_LENGTH_ERR; break; } - cpu_physical_memory_read(desc.addr, packet_buf + packet_bytes, bytes); + dma_memory_read(&s->dma_as, desc.addr, packet_buf + packet_bytes, bytes); packet_bytes += bytes; desc.status &= ~DESC_STATUS_CTL; - allwinner_sun8i_emac_flush_desc(&desc, s->tx_desc_curr); + allwinner_sun8i_emac_flush_desc(s, &desc, s->tx_desc_curr); /* After the last descriptor, send the packet */ if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) { @@ -519,7 +524,7 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s) packet_bytes = 0; transmitted++; } - s->tx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 0); + s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0); } /* Raise transmit completed interrupt */ @@ -623,7 +628,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, break; case REG_TX_CUR_BUF: /* Transmit Current Buffer */ if (s->tx_desc_curr != 0) { - cpu_physical_memory_read(s->tx_desc_curr, &desc, sizeof(desc)); + dma_memory_read(&s->dma_as, s->tx_desc_curr, &desc, sizeof(desc)); value = desc.addr; } else { value = 0; @@ -636,7 +641,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, break; case REG_RX_CUR_BUF: /* Receive Current Buffer */ if (s->rx_desc_curr != 0) { - cpu_physical_memory_read(s->rx_desc_curr, &desc, sizeof(desc)); + dma_memory_read(&s->dma_as, s->rx_desc_curr, &desc, sizeof(desc)); value = desc.addr; } else { value = 0; @@ -790,6 +795,13 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) { AwSun8iEmacState *s = AW_SUN8I_EMAC(dev); + if (!s->dma_mr) { + error_setg(errp, TYPE_AW_SUN8I_EMAC " 'dma-memory' link not set"); + return; + } + + address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); + qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); @@ -799,6 +811,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) static Property allwinner_sun8i_emac_properties[] = { DEFINE_NIC_PROPERTIES(AwSun8iEmacState, conf), DEFINE_PROP_UINT8("phy-addr", AwSun8iEmacState, mii_phy_addr, 0), + DEFINE_PROP_LINK("dma-memory", AwSun8iEmacState, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), }; |