Commit 0ffd3d64 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch...


Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2020-05-14.for-upstream' into staging

Upstream

# gpg: Signature made Thu 14 May 2020 15:04:44 BST
# gpg:                using RSA key AC44FEDC14F7F1EBEDBF415129C596780F6BCA83
# gpg: Good signature from "Edgar E. Iglesias (Xilinx key) <edgar.iglesias@xilinx.com>" [unknown]
# gpg:                 aka "Edgar E. Iglesias <edgar.iglesias@gmail.com>" [full]
# Primary key fingerprint: AC44 FEDC 14F7 F1EB EDBF  4151 29C5 9678 0F6B CA83

* remotes/edgar/tags/edgar/xilinx-next-2020-05-14.for-upstream:
  target/microblaze: monitor: Increase the number of registers reported
  target/microblaze: gdb: Fix incorrect SReg reporting
  target/microblaze: gdb: Extend the number of registers presented to GDB
  target/microblaze: Fix FPU2 instruction check
  target/microblaze: Add MFS Rd,EDR translation
  MAINTAINERS: Add myself as streams maintainer
  hw/dma/xilinx_axidma: s2mm: Support stream fragments
  hw/dma/xilinx_axidma: mm2s: Stream descriptor by descriptor
  hw/net/xilinx_axienet: Handle fragmented packets from DMA
  hw/core: stream: Add an end-of-packet flag
  hw/dma/xilinx_axidma: Add DMA memory-region property
  hw/net/xilinx_axienet: Remove unncessary cast
  hw/net/xilinx_axienet: Cleanup stream->push assignment
  hw/net/xilinx_axienet: Auto-clear PHY Autoneg

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 035b448b 2ead1b18
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2315,6 +2315,12 @@ F: net/slirp.c
F: include/net/slirp.h
T: git https://people.debian.org/~sthibault/qemu.git slirp

Streams
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: hw/core/stream.c
F: include/hw/stream.h

Stubs
M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
+2 −2
Original line number Diff line number Diff line
@@ -3,11 +3,11 @@
#include "qemu/module.h"

size_t
stream_push(StreamSlave *sink, uint8_t *buf, size_t len)
stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop)
{
    StreamSlaveClass *k =  STREAM_SLAVE_GET_CLASS(sink);

    return k->push(sink, buf, len);
    return k->push(sink, buf, len, eop);
}

bool
+48 −27
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include "qemu/log.h"
#include "qemu/module.h"

#include "sysemu/dma.h"
#include "hw/stream.h"

#define D(x)
@@ -103,13 +104,14 @@ enum {
};

struct Stream {
    struct XilinxAXIDMA *dma;
    ptimer_state *ptimer;
    qemu_irq irq;

    int nr;

    bool sof;
    struct SDesc desc;
    int pos;
    unsigned int complete_cnt;
    uint32_t regs[R_MAX];
    uint8_t app[20];
@@ -125,6 +127,9 @@ struct XilinxAXIDMAStreamSlave {
struct XilinxAXIDMA {
    SysBusDevice busdev;
    MemoryRegion iomem;
    MemoryRegion *dma_mr;
    AddressSpace as;

    uint32_t freqhz;
    StreamSlave *tx_data_dev;
    StreamSlave *tx_control_dev;
@@ -170,6 +175,7 @@ static void stream_reset(struct Stream *s)
{
    s->regs[R_DMASR] = DMASR_HALTED;  /* starts up halted.  */
    s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold.  */
    s->sof = true;
}

/* Map an offset addr into a channel index.  */
@@ -186,7 +192,7 @@ static void stream_desc_load(struct Stream *s, hwaddr addr)
{
    struct SDesc *d = &s->desc;

    cpu_physical_memory_read(addr, d, sizeof *d);
    address_space_read(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);

    /* Convert from LE into host endianness.  */
    d->buffer_address = le64_to_cpu(d->buffer_address);
@@ -204,7 +210,8 @@ static void stream_desc_store(struct Stream *s, hwaddr addr)
    d->nxtdesc = cpu_to_le64(d->nxtdesc);
    d->control = cpu_to_le32(d->control);
    d->status = cpu_to_le32(d->status);
    cpu_physical_memory_write(addr, d, sizeof *d);
    address_space_write(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED,
                        d, sizeof *d);
}

static void stream_update_irq(struct Stream *s)
@@ -261,7 +268,9 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
                                 StreamSlave *tx_control_dev)
{
    uint32_t prev_d;
    unsigned int txlen;
    uint32_t txlen;
    uint64_t addr;
    bool eop;

    if (!stream_running(s) || stream_idle(s)) {
        return;
@@ -276,23 +285,26 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
        }

        if (stream_desc_sof(&s->desc)) {
            s->pos = 0;
            stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app));
            stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true);
        }

        txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
        if ((txlen + s->pos) > sizeof s->txbuf) {
            hw_error("%s: too small internal txbuf! %d\n", __func__,
                     txlen + s->pos);
        }

        cpu_physical_memory_read(s->desc.buffer_address,
                                 s->txbuf + s->pos, txlen);
        s->pos += txlen;
        eop = stream_desc_eof(&s->desc);
        addr = s->desc.buffer_address;
        while (txlen) {
            unsigned int len;

            len = txlen > sizeof s->txbuf ? sizeof s->txbuf : txlen;
            address_space_read(&s->dma->as, addr,
                               MEMTXATTRS_UNSPECIFIED,
                               s->txbuf, len);
            stream_push(tx_data_dev, s->txbuf, len, eop && len == txlen);
            txlen -= len;
            addr += len;
        }

        if (stream_desc_eof(&s->desc)) {
            stream_push(tx_data_dev, s->txbuf, s->pos);
            s->pos = 0;
        if (eop) {
            stream_complete(s);
        }

@@ -311,12 +323,11 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
}

static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
                                   size_t len)
                                   size_t len, bool eop)
{
    uint32_t prev_d;
    unsigned int rxlen;
    size_t pos = 0;
    int sof = 1;

    if (!stream_running(s) || stream_idle(s)) {
        return 0;
@@ -336,21 +347,22 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
            rxlen = len;
        }

        cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
        address_space_write(&s->dma->as, s->desc.buffer_address,
                            MEMTXATTRS_UNSPECIFIED, buf + pos, rxlen);
        len -= rxlen;
        pos += rxlen;

        /* Update the descriptor.  */
        if (!len) {
        if (eop) {
            stream_complete(s);
            memcpy(s->desc.app, s->app, sizeof(s->desc.app));
            s->desc.status |= SDESC_STATUS_EOF;
        }

        s->desc.status |= sof << SDESC_STATUS_SOF_BIT;
        s->desc.status |= s->sof << SDESC_STATUS_SOF_BIT;
        s->desc.status |= SDESC_STATUS_COMPLETE;
        stream_desc_store(s, s->regs[R_CURDESC]);
        sof = 0;
        s->sof = eop;

        /* Advance.  */
        prev_d = s->regs[R_CURDESC];
@@ -376,7 +388,7 @@ static void xilinx_axidma_reset(DeviceState *dev)

static size_t
xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
                                  size_t len)
                                  size_t len, bool eop)
{
    XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
    struct Stream *s = &cs->dma->streams[1];
@@ -408,13 +420,14 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj,
}

static size_t
xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len)
xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
                               bool eop)
{
    XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
    struct Stream *s = &ds->dma->streams[1];
    size_t ret;

    ret = stream_process_s2mem(s, buf, len);
    ret = stream_process_s2mem(s, buf, len, eop);
    stream_update_irq(s);
    return ret;
}
@@ -525,6 +538,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
    XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
                                                            &s->rx_control_dev);
    Error *local_err = NULL;
    int i;

    object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
                             (Object **)&ds->dma,
@@ -545,17 +559,19 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
        goto xilinx_axidma_realize_fail;
    }

    int i;

    for (i = 0; i < 2; i++) {
        struct Stream *st = &s->streams[i];

        st->dma = s;
        st->nr = i;
        st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
        ptimer_transaction_begin(st->ptimer);
        ptimer_set_freq(st->ptimer, s->freqhz);
        ptimer_transaction_commit(st->ptimer);
    }

    address_space_init(&s->as,
                       s->dma_mr ? s->dma_mr : get_system_memory(), "dma");
    return;

xilinx_axidma_realize_fail:
@@ -575,6 +591,11 @@ static void xilinx_axidma_init(Object *obj)
                            &s->rx_control_dev, sizeof(s->rx_control_dev),
                            TYPE_XILINX_AXI_DMA_CONTROL_STREAM, &error_abort,
                            NULL);
    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);

    sysbus_init_irq(sbd, &s->streams[0].irq);
    sysbus_init_irq(sbd, &s->streams[1].irq);
+53 −17
Original line number Diff line number Diff line
@@ -149,8 +149,8 @@ tdk_write(struct PHY *phy, unsigned int req, unsigned int data)
            break;
    }

    /* Unconditionally clear regs[BMCR][BMCR_RESET] */
    phy->regs[0] &= ~0x8000;
    /* Unconditionally clear regs[BMCR][BMCR_RESET] and auto-neg */
    phy->regs[0] &= ~0x8200;
}

static void
@@ -402,6 +402,9 @@ struct XilinxAXIEnet {

    uint32_t hdr[CONTROL_PAYLOAD_WORDS];

    uint8_t *txmem;
    uint32_t txpos;

    uint8_t *rxmem;
    uint32_t rxsize;
    uint32_t rxpos;
@@ -421,6 +424,7 @@ static void axienet_rx_reset(XilinxAXIEnet *s)
static void axienet_tx_reset(XilinxAXIEnet *s)
{
    s->tc = TC_JUM | TC_TX | TC_VLAN;
    s->txpos = 0;
}

static inline int axienet_rx_resetting(XilinxAXIEnet *s)
@@ -697,14 +701,14 @@ static void axienet_eth_rx_notify(void *opaque)
                                           axienet_eth_rx_notify, s)) {
        size_t ret = stream_push(s->tx_control_dev,
                                 (void *)s->rxapp + CONTROL_PAYLOAD_SIZE
                                 - s->rxappsize, s->rxappsize);
                                 - s->rxappsize, s->rxappsize, true);
        s->rxappsize -= ret;
    }

    while (s->rxsize && stream_can_push(s->tx_data_dev,
                                        axienet_eth_rx_notify, s)) {
        size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos,
                                 s->rxsize);
                                 s->rxsize, true);
        s->rxsize -= ret;
        s->rxpos += ret;
        if (!s->rxsize) {
@@ -874,12 +878,14 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
}

static size_t
xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len,
                                   bool eop)
{
    int i;
    XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj);
    XilinxAXIEnet *s = cs->enet;

    assert(eop);
    if (len != CONTROL_PAYLOAD_SIZE) {
        hw_error("AXI Enet requires %d byte control stream payload\n",
                 (int)CONTROL_PAYLOAD_SIZE);
@@ -894,7 +900,8 @@ xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
}

static size_t
xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
                                bool eop)
{
    XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj);
    XilinxAXIEnet *s = ds->enet;
@@ -904,9 +911,30 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
        return size;
    }

    if (s->txpos + size > s->c_txmem) {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Packet larger than txmem\n",
                      TYPE_XILINX_AXI_ENET);
        s->txpos = 0;
        return size;
    }

    if (s->txpos == 0 && eop) {
        /* Fast path single fragment.  */
        s->txpos = size;
    } else {
        memcpy(s->txmem + s->txpos, buf, size);
        buf = s->txmem;
        s->txpos += size;

        if (!eop) {
            return size;
        }
    }

    /* Jumbo or vlan sizes ?  */
    if (!(s->tc & TC_JUM)) {
        if (size > 1518 && size <= 1522 && !(s->tc & TC_VLAN)) {
        if (s->txpos > 1518 && s->txpos <= 1522 && !(s->tc & TC_VLAN)) {
            s->txpos = 0;
            return size;
        }
    }
@@ -917,8 +945,8 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
        uint32_t tmp_csum;
        uint16_t csum;

        tmp_csum = net_checksum_add(size - start_off,
                                    (uint8_t *)buf + start_off);
        tmp_csum = net_checksum_add(s->txpos - start_off,
                                    buf + start_off);
        /* Accumulate the seed.  */
        tmp_csum += s->hdr[2] & 0xffff;

@@ -930,12 +958,13 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
        buf[write_off + 1] = csum & 0xff;
    }

    qemu_send_packet(qemu_get_queue(s->nic), buf, size);
    qemu_send_packet(qemu_get_queue(s->nic), buf, s->txpos);

    s->stats.tx_bytes += size;
    s->stats.tx_bytes += s->txpos;
    s->regs[R_IS] |= IS_TX_COMPLETE;
    enet_update_irq(s);

    s->txpos = 0;
    return size;
}

@@ -983,6 +1012,7 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
    s->TEMAC.parent = s;

    s->rxmem = g_malloc(s->c_rxmem);
    s->txmem = g_malloc(s->c_txmem);
    return;

xilinx_enet_realize_fail:
@@ -1029,11 +1059,19 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
    dc->reset = xilinx_axienet_reset;
}

static void xilinx_enet_stream_class_init(ObjectClass *klass, void *data)
static void xilinx_enet_control_stream_class_init(ObjectClass *klass,
                                                  void *data)
{
    StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);

    ssc->push = xilinx_axienet_control_stream_push;
}

static void xilinx_enet_data_stream_class_init(ObjectClass *klass, void *data)
{
    StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);

    ssc->push = data;
    ssc->push = xilinx_axienet_data_stream_push;
}

static const TypeInfo xilinx_enet_info = {
@@ -1048,8 +1086,7 @@ static const TypeInfo xilinx_enet_data_stream_info = {
    .name          = TYPE_XILINX_AXI_ENET_DATA_STREAM,
    .parent        = TYPE_OBJECT,
    .instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
    .class_init    = xilinx_enet_stream_class_init,
    .class_data    = xilinx_axienet_data_stream_push,
    .class_init    = xilinx_enet_data_stream_class_init,
    .interfaces = (InterfaceInfo[]) {
            { TYPE_STREAM_SLAVE },
            { }
@@ -1060,8 +1097,7 @@ static const TypeInfo xilinx_enet_control_stream_info = {
    .name          = TYPE_XILINX_AXI_ENET_CONTROL_STREAM,
    .parent        = TYPE_OBJECT,
    .instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
    .class_init    = xilinx_enet_stream_class_init,
    .class_data    = xilinx_axienet_control_stream_push,
    .class_init    = xilinx_enet_control_stream_class_init,
    .interfaces = (InterfaceInfo[]) {
            { TYPE_STREAM_SLAVE },
            { }
+1 −1
Original line number Diff line number Diff line
@@ -868,7 +868,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)

        memcpy(rq->dma_buf, rxd, num);

        ret = stream_push(rq->dma, rq->dma_buf, num);
        ret = stream_push(rq->dma, rq->dma_buf, num, false);
        assert(ret == num);
        xlnx_zynqmp_qspips_check_flush(rq);
    }
Loading