* [Qemu-devel] [PATCH v5 00/16] Stream Patches
@ 2013-04-03 5:17 Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 01/16] xilinx_axienet: typedef XilinxAXIEnet struct Peter Crosthwaite
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Hi all. The Xilinx AXIEnet and DMA devices have two AXI stream connections
(control and data), only one of which is currently modelled (data). AXI stream
is modelled using the stream QOM interface described in stream.h. Unfortunately,
interfaces have no nice way of modelling multiple connections of the same type.
So to overcome this I created a secondary object which acts as a proxy for the
stream connection. Multiple connections can be implemented using multiple
proxies and stream masters link to the relevant proxy, rather than the ethernet
device itself. This Series changes AXI Enet and DMA to be connected as such.
Also changed the stream interface to implement flow control handshaking. This
is needed for the AXIEnet to be be able to implement the net can_receive() flow
control.
Patches 1-10 are low-impact cleanup of axienet/dma as per the current QOM
styling guidelines and can be cherry-picked off the front.
changed from v4:
resynchronized control flow stream API
reordered series for better consistency.
Folded patch 17 in 16 (app array length fix)
Fixed DMA tx path halted bit
changed from v3:
Changed from asynchronous flow control to synchronous (Edgar review)
changed from v2:
Reordered patches (from low impact -> high impact)
Added styling refactoring of AXIDMA
Added asynchronous patches
Removed dummy second stream connection patch (former patch 8)
Added (functional) second stream connection
changed from v1:
Removed former P1&2 (already merged)
Address Andreas review
Refactor axienet to be more QOM friendly.
Peter Crosthwaite (16):
xilinx_axienet: typedef XilinxAXIEnet struct
xilinx_axienet: Defined and use type cast macro
xilinx_axienet: Register reset properly
xilinx_axienet: converted init->realize
xilinx_axidma: typedef XilinxAXIDMA struct
xilinx_axidma: Defined and use type cast macro
xilinx_axidma: Register reset properly
xilinx_axidma: converted init->realize
petalogix_ml605_mmu: Fix machine node attachment
petalogix_ml605_mmu: Attach ethernet to machine
xilinx_axienet: Create Proxy object for stream
xilinx_axidma: Create Proxy object for stream
xilinx_axidma: Fix rx/tx halted bit.
stream: Add flow control API
xilinx_axienet/dma: Implement rx path flow control
stream: Remove app argument hack
hw/microblaze/petalogix_ml605_mmu.c | 28 +++-
hw/stream.c | 15 ++-
hw/stream.h | 36 ++++-
hw/xilinx.h | 21 ++-
hw/xilinx_axidma.c | 261 +++++++++++++++++++++++++++--------
hw/xilinx_axienet.c | 255 +++++++++++++++++++++++++++-------
6 files changed, 483 insertions(+), 133 deletions(-)
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 01/16] xilinx_axienet: typedef XilinxAXIEnet struct
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 02/16] xilinx_axienet: Defined and use type cast macro Peter Crosthwaite
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Typedef xilinx_axienets object state struct to shorten the repeated usages of
struct XilinxAXIEnet.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axienet.c | 44 +++++++++++++++++++++++---------------------
1 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 5785290..c3c0663 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -306,6 +306,8 @@ struct TEMAC {
void *parent;
};
+typedef struct XilinxAXIEnet XilinxAXIEnet;
+
struct XilinxAXIEnet {
SysBusDevice busdev;
MemoryRegion iomem;
@@ -365,37 +367,37 @@ struct XilinxAXIEnet {
uint8_t *rxmem;
};
-static void axienet_rx_reset(struct XilinxAXIEnet *s)
+static void axienet_rx_reset(XilinxAXIEnet *s)
{
s->rcw[1] = RCW1_JUM | RCW1_FCS | RCW1_RX | RCW1_VLAN;
}
-static void axienet_tx_reset(struct XilinxAXIEnet *s)
+static void axienet_tx_reset(XilinxAXIEnet *s)
{
s->tc = TC_JUM | TC_TX | TC_VLAN;
}
-static inline int axienet_rx_resetting(struct XilinxAXIEnet *s)
+static inline int axienet_rx_resetting(XilinxAXIEnet *s)
{
return s->rcw[1] & RCW1_RST;
}
-static inline int axienet_rx_enabled(struct XilinxAXIEnet *s)
+static inline int axienet_rx_enabled(XilinxAXIEnet *s)
{
return s->rcw[1] & RCW1_RX;
}
-static inline int axienet_extmcf_enabled(struct XilinxAXIEnet *s)
+static inline int axienet_extmcf_enabled(XilinxAXIEnet *s)
{
return !!(s->regs[R_RAF] & RAF_EMCF_EN);
}
-static inline int axienet_newfunc_enabled(struct XilinxAXIEnet *s)
+static inline int axienet_newfunc_enabled(XilinxAXIEnet *s)
{
return !!(s->regs[R_RAF] & RAF_NEWFUNC_EN);
}
-static void axienet_reset(struct XilinxAXIEnet *s)
+static void axienet_reset(XilinxAXIEnet *s)
{
axienet_rx_reset(s);
axienet_tx_reset(s);
@@ -406,7 +408,7 @@ static void axienet_reset(struct XilinxAXIEnet *s)
s->emmc = EMMC_LINKSPEED_100MB;
}
-static void enet_update_irq(struct XilinxAXIEnet *s)
+static void enet_update_irq(XilinxAXIEnet *s)
{
s->regs[R_IP] = s->regs[R_IS] & s->regs[R_IE];
qemu_set_irq(s->irq, !!s->regs[R_IP]);
@@ -414,7 +416,7 @@ static void enet_update_irq(struct XilinxAXIEnet *s)
static uint64_t enet_read(void *opaque, hwaddr addr, unsigned size)
{
- struct XilinxAXIEnet *s = opaque;
+ XilinxAXIEnet *s = opaque;
uint32_t r = 0;
addr >>= 2;
@@ -506,7 +508,7 @@ static uint64_t enet_read(void *opaque, hwaddr addr, unsigned size)
static void enet_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
- struct XilinxAXIEnet *s = opaque;
+ XilinxAXIEnet *s = opaque;
struct TEMAC *t = &s->TEMAC;
addr >>= 2;
@@ -618,7 +620,7 @@ static const MemoryRegionOps enet_ops = {
static int eth_can_rx(NetClientState *nc)
{
- struct XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
+ XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
/* RX enabled? */
return !axienet_rx_resetting(s) && axienet_rx_enabled(s);
@@ -641,7 +643,7 @@ static int enet_match_addr(const uint8_t *buf, uint32_t f0, uint32_t f1)
static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
{
- struct XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
+ XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
static const unsigned char sa_ipmcast[3] = {0x01, 0x00, 0x52};
@@ -786,7 +788,7 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
static void eth_cleanup(NetClientState *nc)
{
/* FIXME. */
- struct XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
+ XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
g_free(s->rxmem);
g_free(s);
}
@@ -794,7 +796,7 @@ static void eth_cleanup(NetClientState *nc)
static void
axienet_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, uint32_t *hdr)
{
- struct XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
+ XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
/* TX enable ? */
if (!(s->tc & TC_TX)) {
@@ -844,7 +846,7 @@ static NetClientInfo net_xilinx_enet_info = {
static int xilinx_enet_init(SysBusDevice *dev)
{
- struct XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), dev);
+ XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), dev);
sysbus_init_irq(dev, &s->irq);
@@ -869,7 +871,7 @@ static int xilinx_enet_init(SysBusDevice *dev)
static void xilinx_enet_initfn(Object *obj)
{
- struct XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
+ XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
@@ -878,10 +880,10 @@ static void xilinx_enet_initfn(Object *obj)
}
static Property xilinx_enet_properties[] = {
- DEFINE_PROP_UINT32("phyaddr", struct XilinxAXIEnet, c_phyaddr, 7),
- DEFINE_PROP_UINT32("rxmem", struct XilinxAXIEnet, c_rxmem, 0x1000),
- DEFINE_PROP_UINT32("txmem", struct XilinxAXIEnet, c_txmem, 0x1000),
- DEFINE_NIC_PROPERTIES(struct XilinxAXIEnet, conf),
+ DEFINE_PROP_UINT32("phyaddr", XilinxAXIEnet, c_phyaddr, 7),
+ DEFINE_PROP_UINT32("rxmem", XilinxAXIEnet, c_rxmem, 0x1000),
+ DEFINE_PROP_UINT32("txmem", XilinxAXIEnet, c_txmem, 0x1000),
+ DEFINE_NIC_PROPERTIES(XilinxAXIEnet, conf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -899,7 +901,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
static const TypeInfo xilinx_enet_info = {
.name = "xlnx.axi-ethernet",
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct XilinxAXIEnet),
+ .instance_size = sizeof(XilinxAXIEnet),
.class_init = xilinx_enet_class_init,
.instance_init = xilinx_enet_initfn,
.interfaces = (InterfaceInfo[]) {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 02/16] xilinx_axienet: Defined and use type cast macro
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 01/16] xilinx_axienet: typedef XilinxAXIEnet struct Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 03/16] xilinx_axienet: Register reset properly Peter Crosthwaite
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Standard QOM cast macro. Replaces usages of FROM_SYSBUS
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axienet.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index c3c0663..4c7d390 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -32,6 +32,11 @@
#define DPHY(x)
+#define TYPE_XILINX_AXI_ENET "xlnx.axi-ethernet"
+
+#define XILINX_AXI_ENET(obj) \
+ OBJECT_CHECK(XilinxAXIEnet, (obj), TYPE_XILINX_AXI_ENET)
+
/* Advertisement control register. */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
@@ -846,7 +851,7 @@ static NetClientInfo net_xilinx_enet_info = {
static int xilinx_enet_init(SysBusDevice *dev)
{
- XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), dev);
+ XilinxAXIEnet *s = XILINX_AXI_ENET(dev);
sysbus_init_irq(dev, &s->irq);
@@ -871,7 +876,7 @@ static int xilinx_enet_init(SysBusDevice *dev)
static void xilinx_enet_initfn(Object *obj)
{
- XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
+ XilinxAXIEnet *s = XILINX_AXI_ENET(obj);
Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
@@ -899,7 +904,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo xilinx_enet_info = {
- .name = "xlnx.axi-ethernet",
+ .name = TYPE_XILINX_AXI_ENET,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxAXIEnet),
.class_init = xilinx_enet_class_init,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 03/16] xilinx_axienet: Register reset properly
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 01/16] xilinx_axienet: typedef XilinxAXIEnet struct Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 02/16] xilinx_axienet: Defined and use type cast macro Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 04/16] xilinx_axienet: converted init->realize Peter Crosthwaite
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Register the reset function and the Device::reset function rather than
explicitly call it from the sysbus::init.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axienet.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 4c7d390..35b4e4f 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -402,8 +402,10 @@ static inline int axienet_newfunc_enabled(XilinxAXIEnet *s)
return !!(s->regs[R_RAF] & RAF_NEWFUNC_EN);
}
-static void axienet_reset(XilinxAXIEnet *s)
+static void xilinx_axienet_reset(DeviceState *d)
{
+ XilinxAXIEnet *s = XILINX_AXI_ENET(d);
+
axienet_rx_reset(s);
axienet_tx_reset(s);
@@ -869,7 +871,6 @@ static int xilinx_enet_init(SysBusDevice *dev)
s->TEMAC.parent = s;
s->rxmem = g_malloc(s->c_rxmem);
- axienet_reset(s);
return 0;
}
@@ -900,6 +901,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
k->init = xilinx_enet_init;
dc->props = xilinx_enet_properties;
+ dc->reset = xilinx_axienet_reset;
ssc->push = axienet_stream_push;
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 04/16] xilinx_axienet: converted init->realize
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (2 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 03/16] xilinx_axienet: Register reset properly Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 05/16] xilinx_axidma: typedef XilinxAXIDMA struct Peter Crosthwaite
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
The prescribed transition from SysBusDevice::init to Device::realize. Im going
with Andreas suggestion to move the sysbus foo to Object::init for early IRQ
visibility.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
Changed from v3: Added missing include of qerror
hw/xilinx_axidma.c | 1 +
hw/xilinx_axienet.c | 24 +++++++++++-------------
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 8db1a74..5d2b33a 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -27,6 +27,7 @@
#include "hw/ptimer.h"
#include "qemu/log.h"
#include "hw/qdev-addr.h"
+#include "qapi/qmp/qerror.h"
#include "hw/stream.h"
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 35b4e4f..ec1e893 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -851,18 +851,13 @@ static NetClientInfo net_xilinx_enet_info = {
.cleanup = eth_cleanup,
};
-static int xilinx_enet_init(SysBusDevice *dev)
+static void xilinx_enet_realize(DeviceState *dev, Error **errp)
{
XilinxAXIEnet *s = XILINX_AXI_ENET(dev);
- sysbus_init_irq(dev, &s->irq);
-
- memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
- sysbus_init_mmio(dev, &s->iomem);
-
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
tdk_init(&s->TEMAC.phy);
@@ -871,18 +866,22 @@ static int xilinx_enet_init(SysBusDevice *dev)
s->TEMAC.parent = s;
s->rxmem = g_malloc(s->c_rxmem);
-
- return 0;
}
-static void xilinx_enet_initfn(Object *obj)
+static void xilinx_enet_init(Object *obj)
{
XilinxAXIEnet *s = XILINX_AXI_ENET(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_dev, &errp);
assert_no_error(errp);
+
+ sysbus_init_irq(sbd, &s->irq);
+
+ memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
+ sysbus_init_mmio(sbd, &s->iomem);
}
static Property xilinx_enet_properties[] = {
@@ -896,10 +895,9 @@ static Property xilinx_enet_properties[] = {
static void xilinx_enet_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
- k->init = xilinx_enet_init;
+ dc->realize = xilinx_enet_realize;
dc->props = xilinx_enet_properties;
dc->reset = xilinx_axienet_reset;
ssc->push = axienet_stream_push;
@@ -910,7 +908,7 @@ static const TypeInfo xilinx_enet_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxAXIEnet),
.class_init = xilinx_enet_class_init,
- .instance_init = xilinx_enet_initfn,
+ .instance_init = xilinx_enet_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 05/16] xilinx_axidma: typedef XilinxAXIDMA struct
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (3 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 04/16] xilinx_axienet: converted init->realize Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 06/16] xilinx_axidma: Defined and use type cast macro Peter Crosthwaite
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Typedef xilinx_axidma's object state struct to shorten the repeated usages of
struct XilinxAXIDMA.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axidma.c | 16 +++++++++-------
1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 5d2b33a..d57538e 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -39,6 +39,8 @@
#define R_TAILDESC (0x10 / 4)
#define R_MAX (0x30 / 4)
+typedef struct XilinxAXIDMA XilinxAXIDMA;
+
enum {
DMACR_RUNSTOP = 1,
DMACR_TAILPTR_MODE = 2,
@@ -354,7 +356,7 @@ static void stream_process_s2mem(struct Stream *s,
static void
axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app)
{
- struct XilinxAXIDMA *d = FROM_SYSBUS(typeof(*d), SYS_BUS_DEVICE(obj));
+ XilinxAXIDMA *d = FROM_SYSBUS(typeof(*d), SYS_BUS_DEVICE(obj));
struct Stream *s = &d->streams[1];
if (!app) {
@@ -367,7 +369,7 @@ axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app)
static uint64_t axidma_read(void *opaque, hwaddr addr,
unsigned size)
{
- struct XilinxAXIDMA *d = opaque;
+ XilinxAXIDMA *d = opaque;
struct Stream *s;
uint32_t r = 0;
int sid;
@@ -402,7 +404,7 @@ static uint64_t axidma_read(void *opaque, hwaddr addr,
static void axidma_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
- struct XilinxAXIDMA *d = opaque;
+ XilinxAXIDMA *d = opaque;
struct Stream *s;
int sid;
@@ -460,7 +462,7 @@ static const MemoryRegionOps axidma_ops = {
static int xilinx_axidma_init(SysBusDevice *dev)
{
- struct XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
+ XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
int i;
sysbus_init_irq(dev, &s->streams[0].irq);
@@ -482,14 +484,14 @@ static int xilinx_axidma_init(SysBusDevice *dev)
static void xilinx_axidma_initfn(Object *obj)
{
- struct XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
+ XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_dev, NULL);
}
static Property axidma_properties[] = {
- DEFINE_PROP_UINT32("freqhz", struct XilinxAXIDMA, freqhz, 50000000),
+ DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000),
DEFINE_PROP_END_OF_LIST(),
};
@@ -507,7 +509,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
static const TypeInfo axidma_info = {
.name = "xlnx.axi-dma",
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct XilinxAXIDMA),
+ .instance_size = sizeof(XilinxAXIDMA),
.class_init = axidma_class_init,
.instance_init = xilinx_axidma_initfn,
.interfaces = (InterfaceInfo[]) {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 06/16] xilinx_axidma: Defined and use type cast macro
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (4 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 05/16] xilinx_axidma: typedef XilinxAXIDMA struct Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 07/16] xilinx_axidma: Register reset properly Peter Crosthwaite
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Standard QOM cast macro. Replaces usages of FROM_SYSBUS
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axidma.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index d57538e..7cb40bd 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -33,6 +33,11 @@
#define D(x)
+#define TYPE_XILINX_AXI_DMA "xlnx.axi-dma"
+
+#define XILINX_AXI_DMA(obj) \
+ OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA)
+
#define R_DMACR (0x00 / 4)
#define R_DMASR (0x04 / 4)
#define R_CURDESC (0x08 / 4)
@@ -356,7 +361,7 @@ static void stream_process_s2mem(struct Stream *s,
static void
axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app)
{
- XilinxAXIDMA *d = FROM_SYSBUS(typeof(*d), SYS_BUS_DEVICE(obj));
+ XilinxAXIDMA *d = XILINX_AXI_DMA(obj);
struct Stream *s = &d->streams[1];
if (!app) {
@@ -462,7 +467,7 @@ static const MemoryRegionOps axidma_ops = {
static int xilinx_axidma_init(SysBusDevice *dev)
{
- XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), dev);
+ XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
int i;
sysbus_init_irq(dev, &s->streams[0].irq);
@@ -484,7 +489,7 @@ static int xilinx_axidma_init(SysBusDevice *dev)
static void xilinx_axidma_initfn(Object *obj)
{
- XilinxAXIDMA *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
+ XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_dev, NULL);
@@ -507,7 +512,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo axidma_info = {
- .name = "xlnx.axi-dma",
+ .name = TYPE_XILINX_AXI_DMA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxAXIDMA),
.class_init = axidma_class_init,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 07/16] xilinx_axidma: Register reset properly
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (5 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 06/16] xilinx_axidma: Defined and use type cast macro Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 08/16] xilinx_axidma: converted init->realize Peter Crosthwaite
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Register the reset function as the Device::reset function rather than
explicitly call it from the sysbus::init.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axidma.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 7cb40bd..ac62245 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -358,6 +358,16 @@ static void stream_process_s2mem(struct Stream *s,
}
}
+static void xilinx_axidma_reset(DeviceState *dev)
+{
+ int i;
+ XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
+
+ for (i = 0; i < 2; i++) {
+ stream_reset(&s->streams[i]);
+ }
+}
+
static void
axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app)
{
@@ -478,7 +488,6 @@ static int xilinx_axidma_init(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->iomem);
for (i = 0; i < 2; i++) {
- stream_reset(&s->streams[i]);
s->streams[i].nr = i;
s->streams[i].bh = qemu_bh_new(timer_hit, &s->streams[i]);
s->streams[i].ptimer = ptimer_init(s->streams[i].bh);
@@ -507,6 +516,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
k->init = xilinx_axidma_init;
+ dc->reset = xilinx_axidma_reset;
dc->props = axidma_properties;
ssc->push = axidma_push;
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 08/16] xilinx_axidma: converted init->realize
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (6 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 07/16] xilinx_axidma: Register reset properly Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 09/16] petalogix_ml605_mmu: Fix machine node attachment Peter Crosthwaite
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
The prescribed transition from SysBusDevice::init to Device::realize. I'm going
with Andreas suggestion to move the sysbus foo to Object::init for early IRQ
visibility.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/xilinx_axidma.c | 25 ++++++++++++-------------
1 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index ac62245..2c95765 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -475,33 +475,33 @@ static const MemoryRegionOps axidma_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int xilinx_axidma_init(SysBusDevice *dev)
+static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
{
XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
int i;
- sysbus_init_irq(dev, &s->streams[0].irq);
- sysbus_init_irq(dev, &s->streams[1].irq);
-
- memory_region_init_io(&s->iomem, &axidma_ops, s,
- "xlnx.axi-dma", R_MAX * 4 * 2);
- sysbus_init_mmio(dev, &s->iomem);
-
for (i = 0; i < 2; i++) {
s->streams[i].nr = i;
s->streams[i].bh = qemu_bh_new(timer_hit, &s->streams[i]);
s->streams[i].ptimer = ptimer_init(s->streams[i].bh);
ptimer_set_freq(s->streams[i].ptimer, s->freqhz);
}
- return 0;
}
-static void xilinx_axidma_initfn(Object *obj)
+static void xilinx_axidma_init(Object *obj)
{
XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_dev, NULL);
+
+ sysbus_init_irq(sbd, &s->streams[0].irq);
+ sysbus_init_irq(sbd, &s->streams[1].irq);
+
+ memory_region_init_io(&s->iomem, &axidma_ops, s,
+ "xlnx.axi-dma", R_MAX * 4 * 2);
+ sysbus_init_mmio(sbd, &s->iomem);
}
static Property axidma_properties[] = {
@@ -512,10 +512,9 @@ static Property axidma_properties[] = {
static void axidma_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
- k->init = xilinx_axidma_init;
+ dc->realize = xilinx_axidma_realize,
dc->reset = xilinx_axidma_reset;
dc->props = axidma_properties;
ssc->push = axidma_push;
@@ -526,7 +525,7 @@ static const TypeInfo axidma_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxAXIDMA),
.class_init = axidma_class_init,
- .instance_init = xilinx_axidma_initfn,
+ .instance_init = xilinx_axidma_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 09/16] petalogix_ml605_mmu: Fix machine node attachment
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (7 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 08/16] xilinx_axidma: converted init->realize Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 10/16] petalogix_ml605_mmu: Attach ethernet to machine Peter Crosthwaite
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Just attach devices straight to the root machine node, rather than the
"unattached node"
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
Suggested (indirectly) by Andreas if he wants to put his Suggested-by to it.
hw/microblaze/petalogix_ml605_mmu.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index cfc0220..ca918b9 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -134,8 +134,8 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
dma = qdev_create(NULL, "xlnx.axi-dma");
/* FIXME: attach to the sysbus instead */
- object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
- "xilinx-dma", OBJECT(dma), NULL);
+ object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma),
+ NULL);
xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
0x82780000, irq[3], 0x1000, 0x1000);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 10/16] petalogix_ml605_mmu: Attach ethernet to machine
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (8 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 09/16] petalogix_ml605_mmu: Fix machine node attachment Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 11/16] xilinx_axienet: Create Proxy object for stream Peter Crosthwaite
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Explicitly make the ethernet a child of the machine. This is needed to set
and use links pre-realize. Also makes the ethernet initialization consistent
with its peer DMA.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/microblaze/petalogix_ml605_mmu.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index ca918b9..482c21f 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -134,6 +134,8 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
dma = qdev_create(NULL, "xlnx.axi-dma");
/* FIXME: attach to the sysbus instead */
+ object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0),
+ NULL);
object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma),
NULL);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 11/16] xilinx_axienet: Create Proxy object for stream
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (9 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 10/16] petalogix_ml605_mmu: Attach ethernet to machine Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 12/16] xilinx_axidma: " Peter Crosthwaite
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Create a separate child object to proxy the stream slave connection. This is
setup for future work where a second stream slave connection is needed. The
new child object is created at qdev init time and is linked back to the parent
(the ethernet device itself) automatically.
Stream slave masters differentiate which slave connection they are connected to
by linking to the proxy object rather than the parent.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
changed from v3:
Fixed function name s/axienet_data_stream_push/xilinx_axienet_data_stream_push
changed from v2:
got rid or overly defensive assert
change from v1:
renamed data-stream proxy link to "axistream-connected-target"
rebased ontop of realize conversion
reworked error return mechanism (Andreas review)
inlined child device state struct into parents (Andreas review)
replaced object_new() -> object_initialize() (Andreas review)
hw/microblaze/petalogix_ml605_mmu.c | 5 ++-
hw/xilinx_axienet.c | 60 ++++++++++++++++++++++++++++++++--
2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 482c21f..9240660 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -79,6 +79,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
const char *cpu_model = args->cpu_model;
MemoryRegion *address_space_mem = get_system_memory();
DeviceState *dev, *dma, *eth0;
+ Object *peer;
MicroBlazeCPU *cpu;
SysBusDevice *busdev;
CPUMBState *env;
@@ -142,7 +143,9 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
0x82780000, irq[3], 0x1000, 0x1000);
- xilinx_axidma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0],
+ peer = object_property_get_link(OBJECT(eth0),
+ "axistream-connected-target", NULL);
+ xilinx_axidma_init(dma, STREAM_SLAVE(peer), 0x84600000, irq[1], irq[0],
100 * 1000000);
{
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index ec1e893..141d2ac 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -33,10 +33,15 @@
#define DPHY(x)
#define TYPE_XILINX_AXI_ENET "xlnx.axi-ethernet"
+#define TYPE_XILINX_AXI_ENET_DATA_STREAM "xilinx-axienet-data-stream"
#define XILINX_AXI_ENET(obj) \
OBJECT_CHECK(XilinxAXIEnet, (obj), TYPE_XILINX_AXI_ENET)
+#define XILINX_AXI_ENET_DATA_STREAM(obj) \
+ OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
+ TYPE_XILINX_AXI_ENET_DATA_STREAM)
+
/* Advertisement control register. */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
@@ -311,13 +316,21 @@ struct TEMAC {
void *parent;
};
+typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave;
typedef struct XilinxAXIEnet XilinxAXIEnet;
+struct XilinxAXIEnetStreamSlave {
+ Object parent;
+
+ struct XilinxAXIEnet *enet;
+} ;
+
struct XilinxAXIEnet {
SysBusDevice busdev;
MemoryRegion iomem;
qemu_irq irq;
StreamSlave *tx_dev;
+ XilinxAXIEnetStreamSlave rx_data_dev;
NICState *nic;
NICConf conf;
@@ -801,9 +814,11 @@ static void eth_cleanup(NetClientState *nc)
}
static void
-axienet_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, uint32_t *hdr)
+xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
+ uint32_t *hdr)
{
- XilinxAXIEnet *s = FROM_SYSBUS(typeof(*s), SYS_BUS_DEVICE(obj));
+ XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj);
+ XilinxAXIEnet *s = ds->enet;
/* TX enable ? */
if (!(s->tc & TC_TX)) {
@@ -854,6 +869,18 @@ static NetClientInfo net_xilinx_enet_info = {
static void xilinx_enet_realize(DeviceState *dev, Error **errp)
{
XilinxAXIEnet *s = XILINX_AXI_ENET(dev);
+ XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev);
+ Error *local_errp = NULL;
+
+ object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
+ (Object **) &ds->enet, &local_errp);
+ if (local_errp) {
+ goto xilinx_enet_realize_fail;
+ }
+ object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_errp);
+ if (local_errp) {
+ goto xilinx_enet_realize_fail;
+ }
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
@@ -866,6 +893,12 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
s->TEMAC.parent = s;
s->rxmem = g_malloc(s->c_rxmem);
+ return;
+
+xilinx_enet_realize_fail:
+ if (!*errp) {
+ *errp = local_errp;
+ }
}
static void xilinx_enet_init(Object *obj)
@@ -878,6 +911,11 @@ static void xilinx_enet_init(Object *obj)
(Object **) &s->tx_dev, &errp);
assert_no_error(errp);
+ object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_ENET_DATA_STREAM);
+ object_property_add_child(OBJECT(s), "axistream-connected-target",
+ (Object *)&s->rx_data_dev, &errp);
+ assert_no_error(errp);
+
sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
@@ -895,12 +933,17 @@ static Property xilinx_enet_properties[] = {
static void xilinx_enet_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
dc->realize = xilinx_enet_realize;
dc->props = xilinx_enet_properties;
dc->reset = xilinx_axienet_reset;
- ssc->push = axienet_stream_push;
+}
+
+static void xilinx_enet_stream_class_init(ObjectClass *klass, void *data)
+{
+ StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
+
+ ssc->push = data;
}
static const TypeInfo xilinx_enet_info = {
@@ -909,6 +952,14 @@ static const TypeInfo xilinx_enet_info = {
.instance_size = sizeof(XilinxAXIEnet),
.class_init = xilinx_enet_class_init,
.instance_init = xilinx_enet_init,
+};
+
+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,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
@@ -918,6 +969,7 @@ static const TypeInfo xilinx_enet_info = {
static void xilinx_enet_register_types(void)
{
type_register_static(&xilinx_enet_info);
+ type_register_static(&xilinx_enet_data_stream_info);
}
type_init(xilinx_enet_register_types)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 12/16] xilinx_axidma: Create Proxy object for stream
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (10 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 11/16] xilinx_axienet: Create Proxy object for stream Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 13/16] xilinx_axidma: Fix rx/tx halted bit Peter Crosthwaite
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Create a separate child object to proxy the stream slave connection. This is
setup for future work where a second stream slave connection is needed. The
new child object is created at qdev init time and is linked back to the parent
(the ethernet device itself) automatically.
Stream slave masters differentiate which slave connection they are connected to
by linking to the proxy object rather than the parent.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
changed since v3:
Rebased to occur before flow control patches
hw/microblaze/petalogix_ml605_mmu.c | 6 ++-
hw/xilinx_axidma.c | 63 ++++++++++++++++++++++++++++++++---
2 files changed, 62 insertions(+), 7 deletions(-)
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 9240660..7581275 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -140,8 +140,10 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma),
NULL);
- xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
- 0x82780000, irq[3], 0x1000, 0x1000);
+ peer = object_property_get_link(OBJECT(dma),
+ "axistream-connected-target", NULL);
+ xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(peer),
+ 0x82780000, irq[3], 0x1000, 0x1000);
peer = object_property_get_link(OBJECT(eth0),
"axistream-connected-target", NULL);
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 2c95765..02700ea 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -34,10 +34,15 @@
#define D(x)
#define TYPE_XILINX_AXI_DMA "xlnx.axi-dma"
+#define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream"
#define XILINX_AXI_DMA(obj) \
OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA)
+#define XILINX_AXI_DMA_DATA_STREAM(obj) \
+ OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
+ TYPE_XILINX_AXI_DMA_DATA_STREAM)
+
#define R_DMACR (0x00 / 4)
#define R_DMASR (0x04 / 4)
#define R_CURDESC (0x08 / 4)
@@ -45,6 +50,7 @@
#define R_MAX (0x30 / 4)
typedef struct XilinxAXIDMA XilinxAXIDMA;
+typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave;
enum {
DMACR_RUNSTOP = 1,
@@ -97,11 +103,18 @@ struct Stream {
uint32_t regs[R_MAX];
};
+struct XilinxAXIDMAStreamSlave {
+ Object parent;
+
+ struct XilinxAXIDMA *dma;
+};
+
struct XilinxAXIDMA {
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t freqhz;
StreamSlave *tx_dev;
+ XilinxAXIDMAStreamSlave rx_data_dev;
struct Stream streams[2];
};
@@ -369,10 +382,11 @@ static void xilinx_axidma_reset(DeviceState *dev)
}
static void
-axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app)
+xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
+ uint32_t *app)
{
- XilinxAXIDMA *d = XILINX_AXI_DMA(obj);
- struct Stream *s = &d->streams[1];
+ XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
+ struct Stream *s = &ds->dma->streams[1];
if (!app) {
hw_error("No stream app data!\n");
@@ -478,6 +492,19 @@ static const MemoryRegionOps axidma_ops = {
static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
{
XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
+ XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
+ Error *local_errp = NULL;
+
+ object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
+ (Object **)&ds->dma, &local_errp);
+ if (local_errp) {
+ goto xilinx_axidma_realize_fail;
+ }
+ object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_errp);
+ if (local_errp) {
+ goto xilinx_axidma_realize_fail;
+ }
+
int i;
for (i = 0; i < 2; i++) {
@@ -486,16 +513,28 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
s->streams[i].ptimer = ptimer_init(s->streams[i].bh);
ptimer_set_freq(s->streams[i].ptimer, s->freqhz);
}
+ return;
+
+xilinx_axidma_realize_fail:
+ if (!*errp) {
+ *errp = local_errp;
+ }
}
static void xilinx_axidma_init(Object *obj)
{
XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_dev, NULL);
+ object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM);
+ object_property_add_child(OBJECT(s), "axistream-connected-target",
+ (Object *)&s->rx_data_dev, &errp);
+ assert_no_error(errp);
+
sysbus_init_irq(sbd, &s->streams[0].irq);
sysbus_init_irq(sbd, &s->streams[1].irq);
@@ -512,12 +551,17 @@ static Property axidma_properties[] = {
static void axidma_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
dc->realize = xilinx_axidma_realize,
dc->reset = xilinx_axidma_reset;
dc->props = axidma_properties;
- ssc->push = axidma_push;
+}
+
+static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
+{
+ StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
+
+ ssc->push = data;
}
static const TypeInfo axidma_info = {
@@ -526,6 +570,14 @@ static const TypeInfo axidma_info = {
.instance_size = sizeof(XilinxAXIDMA),
.class_init = axidma_class_init,
.instance_init = xilinx_axidma_init,
+};
+
+static const TypeInfo xilinx_axidma_data_stream_info = {
+ .name = TYPE_XILINX_AXI_DMA_DATA_STREAM,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
+ .class_init = xilinx_axidma_stream_class_init,
+ .class_data = xilinx_axidma_data_stream_push,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
@@ -535,6 +587,7 @@ static const TypeInfo axidma_info = {
static void xilinx_axidma_register_types(void)
{
type_register_static(&axidma_info);
+ type_register_static(&xilinx_axidma_data_stream_info);
}
type_init(xilinx_axidma_register_types)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 13/16] xilinx_axidma: Fix rx/tx halted bit.
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (11 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 12/16] xilinx_axidma: " Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 14/16] stream: Add flow control API Peter Crosthwaite
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
If there is no DMA buffer descriptor, the DMA halts, not idles.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
changed from v3:
Fixed for TX path as well as RX
hw/xilinx_axidma.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 02700ea..2bbfea1 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -276,7 +276,7 @@ static void stream_process_mem2s(struct Stream *s,
stream_desc_load(s, s->regs[R_CURDESC]);
if (s->desc.status & SDESC_STATUS_COMPLETE) {
- s->regs[R_DMASR] |= DMASR_IDLE;
+ s->regs[R_DMASR] |= DMASR_HALTED;
break;
}
@@ -331,7 +331,7 @@ static void stream_process_s2mem(struct Stream *s,
stream_desc_load(s, s->regs[R_CURDESC]);
if (s->desc.status & SDESC_STATUS_COMPLETE) {
- s->regs[R_DMASR] |= DMASR_IDLE;
+ s->regs[R_DMASR] |= DMASR_HALTED;
break;
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 14/16] stream: Add flow control API
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (12 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 13/16] xilinx_axidma: Fix rx/tx halted bit Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 15/16] xilinx_axienet/dma: Implement rx path flow control Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 16/16] stream: Remove app argument hack Peter Crosthwaite
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Add basic flow control to stream. A stream slave may return short, indicating
that it is not capable of accepting any more data at the present time. Polling
or a callback can be used via the can_push() function to determine when the
slave can receive again.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/stream.c | 13 +++++++++++--
hw/stream.h | 33 ++++++++++++++++++++++++++++++---
hw/xilinx_axidma.c | 3 ++-
hw/xilinx_axienet.c | 8 +++++---
4 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/hw/stream.c b/hw/stream.c
index a07d6a5..5397a8d 100644
--- a/hw/stream.c
+++ b/hw/stream.c
@@ -1,11 +1,20 @@
#include "hw/stream.h"
-void
+size_t
stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app)
{
StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink);
- k->push(sink, buf, len, app);
+ return k->push(sink, buf, len, app);
+}
+
+bool
+stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify,
+ void *notify_opaque)
+{
+ StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink);
+
+ return k->can_push ? k->can_push(sink, notify, notify_opaque) : true;
}
static const TypeInfo stream_slave_info = {
diff --git a/hw/stream.h b/hw/stream.h
index f6137d6..ff2cb14 100644
--- a/hw/stream.h
+++ b/hw/stream.h
@@ -18,14 +18,41 @@ typedef struct StreamSlave {
Object Parent;
} StreamSlave;
+typedef void (*StreamCanPushNotifyFn)(void *opaque);
+
typedef struct StreamSlaveClass {
InterfaceClass parent;
-
- void (*push)(StreamSlave *obj, unsigned char *buf, size_t len,
+ /**
+ * can push - determine if a stream slave is capable of accepting at least
+ * one byte of data. Returns false if cannot accept. If not implemented, the
+ * slave is assumed to always be capable of recieveing.
+ * @notify: Optional callback that the slave will call when the slave is
+ * capable of recieving again. Only called if false is returned.
+ * @notify_opaque: opaque data to pass to notify call.
+ */
+ bool (*can_push)(StreamSlave *obj, StreamCanPushNotifyFn notify,
+ void *notify_opaque);
+ /**
+ * push - push data to a Stream slave. The number of bytes pushed is
+ * returned. If the slave short returns, the master must wait before trying
+ * again, the slave may continue to just return 0 waiting for the vm time to
+ * advance. The can_push() function can be used to trap the point in time
+ * where the slave is ready to recieve agai, otherwise polling on a QEMU
+ * timer will work.
+ * @obj: Stream slave to push to
+ * @buf: Data to write
+ * @len: Maximum number of bytes to write
+ */
+ size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len,
uint32_t *app);
} StreamSlaveClass;
-void
+size_t
stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app);
+bool
+stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify,
+ void *notify_opaque);
+
+
#endif /* STREAM_H */
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 2bbfea1..80ce57f 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -381,7 +381,7 @@ static void xilinx_axidma_reset(DeviceState *dev)
}
}
-static void
+static size_t
xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
uint32_t *app)
{
@@ -393,6 +393,7 @@ xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
}
stream_process_s2mem(s, buf, len, app);
stream_update_irq(s);
+ return len;
}
static uint64_t axidma_read(void *opaque, hwaddr addr,
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 141d2ac..5c0ea59 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -813,7 +813,7 @@ static void eth_cleanup(NetClientState *nc)
g_free(s);
}
-static void
+static size_t
xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
uint32_t *hdr)
{
@@ -822,13 +822,13 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
/* TX enable ? */
if (!(s->tc & TC_TX)) {
- return;
+ return size;
}
/* Jumbo or vlan sizes ? */
if (!(s->tc & TC_JUM)) {
if (size > 1518 && size <= 1522 && !(s->tc & TC_VLAN)) {
- return;
+ return size;
}
}
@@ -856,6 +856,8 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
s->stats.tx_bytes += size;
s->regs[R_IS] |= IS_TX_COMPLETE;
enet_update_irq(s);
+
+ return size;
}
static NetClientInfo net_xilinx_enet_info = {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 15/16] xilinx_axienet/dma: Implement rx path flow control
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (13 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 14/16] stream: Add flow control API Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 16/16] stream: Remove app argument hack Peter Crosthwaite
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
Implement flow control for the RX data path from xilinx_axienet->xilinx_axidma.
On short return from axidma, then ethernet sets up the notify callback to resume
transfer from where it left off.
This also allows the ethernet to track whether there is an in progress transaction
and return false from ethernet can_receive() as appropriate.
If the DMA backs up or is disabled it waits for enablement. When the rx stream IO
region is touched, the can_push() notify function is called if set.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/xilinx_axidma.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
hw/xilinx_axienet.c | 28 +++++++++++++++++++++++++---
2 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 80ce57f..a5bf102 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -117,6 +117,9 @@ struct XilinxAXIDMA {
XilinxAXIDMAStreamSlave rx_data_dev;
struct Stream streams[2];
+
+ StreamCanPushNotifyFn notify;
+ void *notify_opaque;
};
/*
@@ -315,16 +318,16 @@ static void stream_process_mem2s(struct Stream *s,
}
}
-static void stream_process_s2mem(struct Stream *s,
- unsigned char *buf, size_t len, uint32_t *app)
+static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
+ size_t len, uint32_t *app)
{
uint32_t prev_d;
unsigned int rxlen;
- int pos = 0;
+ size_t pos = 0;
int sof = 1;
if (!stream_running(s) || stream_idle(s)) {
- return;
+ return 0;
}
while (len) {
@@ -369,6 +372,8 @@ static void stream_process_s2mem(struct Stream *s,
break;
}
}
+
+ return pos;
}
static void xilinx_axidma_reset(DeviceState *dev)
@@ -381,19 +386,37 @@ static void xilinx_axidma_reset(DeviceState *dev)
}
}
+static bool
+xilinx_axidma_data_stream_can_push(StreamSlave *obj,
+ StreamCanPushNotifyFn notify,
+ void *notify_opaque)
+{
+ XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
+ struct Stream *s = &ds->dma->streams[1];
+
+ if (!stream_running(s) || stream_idle(s)) {
+ ds->dma->notify = notify;
+ ds->dma->notify_opaque = notify_opaque;
+ return false;
+ }
+
+ return true;
+}
+
static size_t
xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
uint32_t *app)
{
XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
struct Stream *s = &ds->dma->streams[1];
+ size_t ret;
if (!app) {
hw_error("No stream app data!\n");
}
- stream_process_s2mem(s, buf, len, app);
+ ret = stream_process_s2mem(s, buf, len, app);
stream_update_irq(s);
- return len;
+ return ret;
}
static uint64_t axidma_read(void *opaque, hwaddr addr,
@@ -481,6 +504,10 @@ static void axidma_write(void *opaque, hwaddr addr,
s->regs[addr] = value;
break;
}
+ if (sid == 1 && d->notify) {
+ d->notify(d->notify_opaque);
+ d->notify = NULL;
+ }
stream_update_irq(s);
}
@@ -558,11 +585,17 @@ static void axidma_class_init(ObjectClass *klass, void *data)
dc->props = axidma_properties;
}
+static StreamSlaveClass xilinx_axidma_data_stream_class = {
+ .push = xilinx_axidma_data_stream_push,
+ .can_push = xilinx_axidma_data_stream_can_push,
+};
+
static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
{
StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
- ssc->push = data;
+ ssc->push = ((StreamSlaveClass *)data)->push;
+ ssc->can_push = ((StreamSlaveClass *)data)->can_push;
}
static const TypeInfo axidma_info = {
@@ -578,7 +611,7 @@ static const TypeInfo xilinx_axidma_data_stream_info = {
.parent = TYPE_OBJECT,
.instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
.class_init = xilinx_axidma_stream_class_init,
- .class_data = xilinx_axidma_data_stream_push,
+ .class_data = &xilinx_axidma_data_stream_class,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 5c0ea59..e67a68b 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -383,6 +383,9 @@ struct XilinxAXIEnet {
uint8_t *rxmem;
+ uint32_t *rxapp;
+ uint32_t rxsize;
+ uint32_t rxpos;
};
static void axienet_rx_reset(XilinxAXIEnet *s)
@@ -643,7 +646,7 @@ static int eth_can_rx(NetClientState *nc)
XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
/* RX enabled? */
- return !axienet_rx_resetting(s) && axienet_rx_enabled(s);
+ return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
}
static int enet_match_addr(const uint8_t *buf, uint32_t f0, uint32_t f1)
@@ -661,6 +664,23 @@ static int enet_match_addr(const uint8_t *buf, uint32_t f0, uint32_t f1)
return match;
}
+static void axienet_eth_rx_notify(void *opaque)
+{
+ XilinxAXIEnet *s = XILINX_AXI_ENET(opaque);
+
+ while (s->rxsize && stream_can_push(s->tx_dev, axienet_eth_rx_notify, s)) {
+ size_t ret = stream_push(s->tx_dev, (void *)s->rxmem + s->rxpos,
+ s->rxsize, s->rxapp);
+ s->rxsize -= ret;
+ s->rxpos += ret;
+ if (!s->rxsize) {
+ s->regs[R_IS] |= IS_RX_COMPLETE;
+ g_free(s->rxapp);
+ }
+ }
+ enet_update_irq(s);
+}
+
static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
{
XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
@@ -798,9 +818,11 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
/* Good frame. */
app[2] |= 1 << 6;
- stream_push(s->tx_dev, (void *)s->rxmem, size, app);
+ s->rxsize = size;
+ s->rxpos = 0;
+ s->rxapp = g_memdup(app, sizeof(app));
+ axienet_eth_rx_notify(s);
- s->regs[R_IS] |= IS_RX_COMPLETE;
enet_update_irq(s);
return size;
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v5 16/16] stream: Remove app argument hack
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
` (14 preceding siblings ...)
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 15/16] xilinx_axienet/dma: Implement rx path flow control Peter Crosthwaite
@ 2013-04-03 5:17 ` Peter Crosthwaite
15 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2013-04-03 5:17 UTC (permalink / raw)
To: qemu-devel, edgar.iglesias; +Cc: Peter Crosthwaite
The uint32_t *app argument doesn't exist in real hardware. It was a hack in
xilinx_axidma/enet to fake the (secondary) control stream connection. Removed
the argument and added the second stream to axienet/dma.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
changed since v3:
Rebased against now synchronous stream control API
Macrofied stream control packet lengths
hw/microblaze/petalogix_ml605_mmu.c | 25 +++++----
hw/stream.c | 4 +-
hw/stream.h | 5 +-
hw/xilinx.h | 21 +++++---
hw/xilinx_axidma.c | 99 ++++++++++++++++++++++++----------
hw/xilinx_axienet.c | 100 +++++++++++++++++++++++++++++-----
6 files changed, 187 insertions(+), 67 deletions(-)
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 7581275..341cd2e 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -79,7 +79,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
const char *cpu_model = args->cpu_model;
MemoryRegion *address_space_mem = get_system_memory();
DeviceState *dev, *dma, *eth0;
- Object *peer;
+ Object *ds, *cs;
MicroBlazeCPU *cpu;
SysBusDevice *busdev;
CPUMBState *env;
@@ -140,15 +140,20 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma),
NULL);
- peer = object_property_get_link(OBJECT(dma),
- "axistream-connected-target", NULL);
- xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(peer),
- 0x82780000, irq[3], 0x1000, 0x1000);
-
- peer = object_property_get_link(OBJECT(eth0),
- "axistream-connected-target", NULL);
- xilinx_axidma_init(dma, STREAM_SLAVE(peer), 0x84600000, irq[1], irq[0],
- 100 * 1000000);
+ ds = object_property_get_link(OBJECT(dma),
+ "axistream-connected-target", NULL);
+ cs = object_property_get_link(OBJECT(dma),
+ "axistream-control-connected-target", NULL);
+ xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(ds),
+ STREAM_SLAVE(cs), 0x82780000, irq[3], 0x1000,
+ 0x1000);
+
+ ds = object_property_get_link(OBJECT(eth0),
+ "axistream-connected-target", NULL);
+ cs = object_property_get_link(OBJECT(eth0),
+ "axistream-control-connected-target", NULL);
+ xilinx_axidma_init(dma, STREAM_SLAVE(ds), STREAM_SLAVE(cs), 0x84600000,
+ irq[1], irq[0], 100 * 1000000);
{
SSIBus *spi;
diff --git a/hw/stream.c b/hw/stream.c
index 5397a8d..e6a05a5 100644
--- a/hw/stream.c
+++ b/hw/stream.c
@@ -1,11 +1,11 @@
#include "hw/stream.h"
size_t
-stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app)
+stream_push(StreamSlave *sink, uint8_t *buf, size_t len)
{
StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink);
- return k->push(sink, buf, len, app);
+ return k->push(sink, buf, len);
}
bool
diff --git a/hw/stream.h b/hw/stream.h
index ff2cb14..36ae35d 100644
--- a/hw/stream.h
+++ b/hw/stream.h
@@ -43,12 +43,11 @@ typedef struct StreamSlaveClass {
* @buf: Data to write
* @len: Maximum number of bytes to write
*/
- size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len,
- uint32_t *app);
+ size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len);
} StreamSlaveClass;
size_t
-stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app);
+stream_push(StreamSlave *sink, uint8_t *buf, size_t len);
bool
stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify,
diff --git a/hw/xilinx.h b/hw/xilinx.h
index 6c1ee21..0c0251a 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -55,16 +55,19 @@ xilinx_ethlite_create(NICInfo *nd, hwaddr base, qemu_irq irq,
}
static inline void
-xilinx_axiethernet_init(DeviceState *dev, NICInfo *nd, StreamSlave *peer,
- hwaddr base, qemu_irq irq, int txmem, int rxmem)
+xilinx_axiethernet_init(DeviceState *dev, NICInfo *nd, StreamSlave *ds,
+ StreamSlave *cs, hwaddr base, qemu_irq irq, int txmem,
+ int rxmem)
{
Error *errp = NULL;
qdev_set_nic_properties(dev, nd);
qdev_prop_set_uint32(dev, "rxmem", rxmem);
qdev_prop_set_uint32(dev, "txmem", txmem);
- object_property_set_link(OBJECT(dev), OBJECT(peer), "axistream-connected",
- &errp);
+ object_property_set_link(OBJECT(dev), OBJECT(ds),
+ "axistream-connected", &errp);
+ object_property_set_link(OBJECT(dev), OBJECT(cs),
+ "axistream-control-connected", &errp);
assert_no_error(errp);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
@@ -72,14 +75,16 @@ xilinx_axiethernet_init(DeviceState *dev, NICInfo *nd, StreamSlave *peer,
}
static inline void
-xilinx_axidma_init(DeviceState *dev, StreamSlave *peer, hwaddr base,
- qemu_irq irq, qemu_irq irq2, int freqhz)
+xilinx_axidma_init(DeviceState *dev, StreamSlave *ds, StreamSlave *cs,
+ hwaddr base, qemu_irq irq, qemu_irq irq2, int freqhz)
{
Error *errp = NULL;
qdev_prop_set_uint32(dev, "freqhz", freqhz);
- object_property_set_link(OBJECT(dev), OBJECT(peer), "axistream-connected",
- &errp);
+ object_property_set_link(OBJECT(dev), OBJECT(ds),
+ "axistream-connected", &errp);
+ object_property_set_link(OBJECT(dev), OBJECT(cs),
+ "axistream-control-connected", &errp);
assert_no_error(errp);
qdev_init_nofail(dev);
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index a5bf102..1c23762 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -35,6 +35,7 @@
#define TYPE_XILINX_AXI_DMA "xlnx.axi-dma"
#define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream"
+#define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream"
#define XILINX_AXI_DMA(obj) \
OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA)
@@ -43,12 +44,19 @@
OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
TYPE_XILINX_AXI_DMA_DATA_STREAM)
+#define XILINX_AXI_DMA_CONTROL_STREAM(obj) \
+ OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
+ TYPE_XILINX_AXI_DMA_CONTROL_STREAM)
+
#define R_DMACR (0x00 / 4)
#define R_DMASR (0x04 / 4)
#define R_CURDESC (0x08 / 4)
#define R_TAILDESC (0x10 / 4)
#define R_MAX (0x30 / 4)
+#define CONTROL_PAYLOAD_WORDS 5
+#define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t)))
+
typedef struct XilinxAXIDMA XilinxAXIDMA;
typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave;
@@ -73,7 +81,7 @@ struct SDesc {
uint64_t reserved;
uint32_t control;
uint32_t status;
- uint32_t app[6];
+ uint8_t app[CONTROL_PAYLOAD_SIZE];
};
enum {
@@ -101,6 +109,7 @@ struct Stream {
int pos;
unsigned int complete_cnt;
uint32_t regs[R_MAX];
+ uint8_t app[20];
};
struct XilinxAXIDMAStreamSlave {
@@ -113,8 +122,10 @@ struct XilinxAXIDMA {
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t freqhz;
- StreamSlave *tx_dev;
+ StreamSlave *tx_data_dev;
+ StreamSlave *tx_control_dev;
XilinxAXIDMAStreamSlave rx_data_dev;
+ XilinxAXIDMAStreamSlave rx_control_dev;
struct Stream streams[2];
@@ -185,7 +196,6 @@ static void stream_desc_show(struct SDesc *d)
static void stream_desc_load(struct Stream *s, hwaddr addr)
{
struct SDesc *d = &s->desc;
- int i;
cpu_physical_memory_read(addr, (void *) d, sizeof *d);
@@ -194,24 +204,17 @@ static void stream_desc_load(struct Stream *s, hwaddr addr)
d->nxtdesc = le64_to_cpu(d->nxtdesc);
d->control = le32_to_cpu(d->control);
d->status = le32_to_cpu(d->status);
- for (i = 0; i < ARRAY_SIZE(d->app); i++) {
- d->app[i] = le32_to_cpu(d->app[i]);
- }
}
static void stream_desc_store(struct Stream *s, hwaddr addr)
{
struct SDesc *d = &s->desc;
- int i;
/* Convert from host endianness into LE. */
d->buffer_address = cpu_to_le64(d->buffer_address);
d->nxtdesc = cpu_to_le64(d->nxtdesc);
d->control = cpu_to_le32(d->control);
d->status = cpu_to_le32(d->status);
- for (i = 0; i < ARRAY_SIZE(d->app); i++) {
- d->app[i] = cpu_to_le32(d->app[i]);
- }
cpu_physical_memory_write(addr, (void *) d, sizeof *d);
}
@@ -263,13 +266,12 @@ static void stream_complete(struct Stream *s)
}
}
-static void stream_process_mem2s(struct Stream *s,
- StreamSlave *tx_dev)
+static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
+ StreamSlave *tx_control_dev)
{
uint32_t prev_d;
unsigned char txbuf[16 * 1024];
unsigned int txlen;
- uint32_t app[6];
if (!stream_running(s) || stream_idle(s)) {
return;
@@ -285,7 +287,7 @@ static void stream_process_mem2s(struct Stream *s,
if (stream_desc_sof(&s->desc)) {
s->pos = 0;
- memcpy(app, s->desc.app, sizeof app);
+ stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app));
}
txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
@@ -299,7 +301,7 @@ static void stream_process_mem2s(struct Stream *s,
s->pos += txlen;
if (stream_desc_eof(&s->desc)) {
- stream_push(tx_dev, txbuf, s->pos, app);
+ stream_push(tx_data_dev, txbuf, s->pos);
s->pos = 0;
stream_complete(s);
}
@@ -319,7 +321,7 @@ static void stream_process_mem2s(struct Stream *s,
}
static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
- size_t len, uint32_t *app)
+ size_t len)
{
uint32_t prev_d;
unsigned int rxlen;
@@ -350,12 +352,8 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
/* Update the descriptor. */
if (!len) {
- int i;
-
stream_complete(s);
- for (i = 0; i < 5; i++) {
- s->desc.app[i] = app[i];
- }
+ memcpy(s->desc.app, s->app, sizeof(s->desc.app));
s->desc.status |= SDESC_STATUS_EOF;
}
@@ -386,6 +384,22 @@ static void xilinx_axidma_reset(DeviceState *dev)
}
}
+static size_t
+xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
+ size_t len)
+{
+ XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
+ struct Stream *s = &cs->dma->streams[1];
+
+ if (len != CONTROL_PAYLOAD_SIZE) {
+ hw_error("AXI DMA requires %d byte control stream payload\n",
+ (int)CONTROL_PAYLOAD_SIZE);
+ }
+
+ memcpy(s->app, buf, len);
+ return len;
+}
+
static bool
xilinx_axidma_data_stream_can_push(StreamSlave *obj,
StreamCanPushNotifyFn notify,
@@ -404,17 +418,13 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj,
}
static size_t
-xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
- uint32_t *app)
+xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len)
{
XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
struct Stream *s = &ds->dma->streams[1];
size_t ret;
- if (!app) {
- hw_error("No stream app data!\n");
- }
- ret = stream_process_s2mem(s, buf, len, app);
+ ret = stream_process_s2mem(s, buf, len);
stream_update_irq(s);
return ret;
}
@@ -495,7 +505,7 @@ static void axidma_write(void *opaque, hwaddr addr,
s->regs[addr] = value;
s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle. */
if (!sid) {
- stream_process_mem2s(s, d->tx_dev);
+ stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev);
}
break;
default:
@@ -521,14 +531,19 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
{
XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
+ XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
+ &s->rx_control_dev);
Error *local_errp = NULL;
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&ds->dma, &local_errp);
+ object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
+ (Object **)&cs->dma, &local_errp);
if (local_errp) {
goto xilinx_axidma_realize_fail;
}
object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_errp);
+ object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_errp);
if (local_errp) {
goto xilinx_axidma_realize_fail;
}
@@ -556,12 +571,21 @@ static void xilinx_axidma_init(Object *obj)
Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
- (Object **) &s->tx_dev, NULL);
+ (Object **) &s->tx_data_dev, &errp);
+ assert_no_error(errp);
+ object_property_add_link(obj, "axistream-control-connected",
+ TYPE_STREAM_SLAVE,
+ (Object **) &s->tx_control_dev, &errp);
+ assert_no_error(errp);
object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM);
+ object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_DMA_CONTROL_STREAM);
object_property_add_child(OBJECT(s), "axistream-connected-target",
(Object *)&s->rx_data_dev, &errp);
assert_no_error(errp);
+ object_property_add_child(OBJECT(s), "axistream-control-connected-target",
+ (Object *)&s->rx_control_dev, &errp);
+ assert_no_error(errp);
sysbus_init_irq(sbd, &s->streams[0].irq);
sysbus_init_irq(sbd, &s->streams[1].irq);
@@ -590,6 +614,10 @@ static StreamSlaveClass xilinx_axidma_data_stream_class = {
.can_push = xilinx_axidma_data_stream_can_push,
};
+static StreamSlaveClass xilinx_axidma_control_stream_class = {
+ .push = xilinx_axidma_control_stream_push,
+};
+
static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
{
StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
@@ -618,10 +646,23 @@ static const TypeInfo xilinx_axidma_data_stream_info = {
}
};
+static const TypeInfo xilinx_axidma_control_stream_info = {
+ .name = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
+ .class_init = xilinx_axidma_stream_class_init,
+ .class_data = &xilinx_axidma_control_stream_class,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_STREAM_SLAVE },
+ { }
+ }
+};
+
static void xilinx_axidma_register_types(void)
{
type_register_static(&axidma_info);
type_register_static(&xilinx_axidma_data_stream_info);
+ type_register_static(&xilinx_axidma_control_stream_info);
}
type_init(xilinx_axidma_register_types)
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index e67a68b..019c114 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -34,6 +34,7 @@
#define TYPE_XILINX_AXI_ENET "xlnx.axi-ethernet"
#define TYPE_XILINX_AXI_ENET_DATA_STREAM "xilinx-axienet-data-stream"
+#define TYPE_XILINX_AXI_ENET_CONTROL_STREAM "xilinx-axienet-control-stream"
#define XILINX_AXI_ENET(obj) \
OBJECT_CHECK(XilinxAXIEnet, (obj), TYPE_XILINX_AXI_ENET)
@@ -42,12 +43,19 @@
OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
TYPE_XILINX_AXI_ENET_DATA_STREAM)
+#define XILINX_AXI_ENET_CONTROL_STREAM(obj) \
+ OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
+ TYPE_XILINX_AXI_ENET_CONTROL_STREAM)
+
/* Advertisement control register. */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define CONTROL_PAYLOAD_WORDS 5
+#define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t)))
+
struct PHY {
uint32_t regs[32];
@@ -329,8 +337,10 @@ struct XilinxAXIEnet {
SysBusDevice busdev;
MemoryRegion iomem;
qemu_irq irq;
- StreamSlave *tx_dev;
+ StreamSlave *tx_data_dev;
+ StreamSlave *tx_control_dev;
XilinxAXIEnetStreamSlave rx_data_dev;
+ XilinxAXIEnetStreamSlave rx_control_dev;
NICState *nic;
NICConf conf;
@@ -381,11 +391,14 @@ struct XilinxAXIEnet {
/* 32K x 1 lookup filter. */
uint32_t ext_mtable[1024];
+ uint32_t hdr[CONTROL_PAYLOAD_WORDS];
uint8_t *rxmem;
- uint32_t *rxapp;
uint32_t rxsize;
uint32_t rxpos;
+
+ uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
+ uint32_t rxappsize;
};
static void axienet_rx_reset(XilinxAXIEnet *s)
@@ -668,14 +681,22 @@ static void axienet_eth_rx_notify(void *opaque)
{
XilinxAXIEnet *s = XILINX_AXI_ENET(opaque);
- while (s->rxsize && stream_can_push(s->tx_dev, axienet_eth_rx_notify, s)) {
- size_t ret = stream_push(s->tx_dev, (void *)s->rxmem + s->rxpos,
- s->rxsize, s->rxapp);
+ while (s->rxappsize && stream_can_push(s->tx_control_dev,
+ 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 -= 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 -= ret;
s->rxpos += ret;
if (!s->rxsize) {
s->regs[R_IS] |= IS_RX_COMPLETE;
- g_free(s->rxapp);
}
}
enet_update_irq(s);
@@ -687,7 +708,7 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
static const unsigned char sa_ipmcast[3] = {0x01, 0x00, 0x52};
- uint32_t app[6] = {0};
+ uint32_t app[CONTROL_PAYLOAD_WORDS] = {0};
int promisc = s->fmi & (1 << 31);
int unicast, broadcast, multicast, ip_multicast = 0;
uint32_t csum32;
@@ -820,7 +841,11 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
s->rxsize = size;
s->rxpos = 0;
- s->rxapp = g_memdup(app, sizeof(app));
+ for (i = 0; i < ARRAY_SIZE(app); ++i) {
+ app[i] = cpu_to_le32(app[i]);
+ }
+ s->rxappsize = CONTROL_PAYLOAD_SIZE;
+ memcpy(s->rxapp, app, s->rxappsize);
axienet_eth_rx_notify(s);
enet_update_irq(s);
@@ -836,8 +861,27 @@ static void eth_cleanup(NetClientState *nc)
}
static size_t
-xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
- uint32_t *hdr)
+xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
+{
+ int i;
+ XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj);
+ XilinxAXIEnet *s = cs->enet;
+
+ if (len != CONTROL_PAYLOAD_SIZE) {
+ hw_error("AXI Enet requires %d byte control stream payload\n",
+ (int)CONTROL_PAYLOAD_SIZE);
+ }
+
+ memcpy(s->hdr, buf, len);
+
+ for (i = 0; i < ARRAY_SIZE(s->hdr); ++i) {
+ s->hdr[i] = le32_to_cpu(s->hdr[i]);
+ }
+ return len;
+}
+
+static size_t
+xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
{
XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj);
XilinxAXIEnet *s = ds->enet;
@@ -854,16 +898,16 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
}
}
- if (hdr[0] & 1) {
- unsigned int start_off = hdr[1] >> 16;
- unsigned int write_off = hdr[1] & 0xffff;
+ if (s->hdr[0] & 1) {
+ unsigned int start_off = s->hdr[1] >> 16;
+ unsigned int write_off = s->hdr[1] & 0xffff;
uint32_t tmp_csum;
uint16_t csum;
tmp_csum = net_checksum_add(size - start_off,
(uint8_t *)buf + start_off);
/* Accumulate the seed. */
- tmp_csum += hdr[2] & 0xffff;
+ tmp_csum += s->hdr[2] & 0xffff;
/* Fold the 32bit partial checksum. */
csum = net_checksum_finish(tmp_csum);
@@ -894,14 +938,19 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
{
XilinxAXIEnet *s = XILINX_AXI_ENET(dev);
XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev);
+ XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(
+ &s->rx_control_dev);
Error *local_errp = NULL;
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
(Object **) &ds->enet, &local_errp);
+ object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
+ (Object **) &cs->enet, &local_errp);
if (local_errp) {
goto xilinx_enet_realize_fail;
}
object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_errp);
+ object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_errp);
if (local_errp) {
goto xilinx_enet_realize_fail;
}
@@ -932,13 +981,21 @@ static void xilinx_enet_init(Object *obj)
Error *errp = NULL;
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
- (Object **) &s->tx_dev, &errp);
+ (Object **) &s->tx_data_dev, &errp);
+ assert_no_error(errp);
+ object_property_add_link(obj, "axistream-control-connected",
+ TYPE_STREAM_SLAVE,
+ (Object **) &s->tx_control_dev, &errp);
assert_no_error(errp);
object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_ENET_DATA_STREAM);
+ object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_ENET_CONTROL_STREAM);
object_property_add_child(OBJECT(s), "axistream-connected-target",
(Object *)&s->rx_data_dev, &errp);
assert_no_error(errp);
+ object_property_add_child(OBJECT(s), "axistream-control-connected-target",
+ (Object *)&s->rx_control_dev, &errp);
+ assert_no_error(errp);
sysbus_init_irq(sbd, &s->irq);
@@ -990,10 +1047,23 @@ static const TypeInfo xilinx_enet_data_stream_info = {
}
};
+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,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_STREAM_SLAVE },
+ { }
+ }
+};
+
static void xilinx_enet_register_types(void)
{
type_register_static(&xilinx_enet_info);
type_register_static(&xilinx_enet_data_stream_info);
+ type_register_static(&xilinx_enet_control_stream_info);
}
type_init(xilinx_enet_register_types)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2013-04-03 5:27 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-03 5:17 [Qemu-devel] [PATCH v5 00/16] Stream Patches Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 01/16] xilinx_axienet: typedef XilinxAXIEnet struct Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 02/16] xilinx_axienet: Defined and use type cast macro Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 03/16] xilinx_axienet: Register reset properly Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 04/16] xilinx_axienet: converted init->realize Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 05/16] xilinx_axidma: typedef XilinxAXIDMA struct Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 06/16] xilinx_axidma: Defined and use type cast macro Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 07/16] xilinx_axidma: Register reset properly Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 08/16] xilinx_axidma: converted init->realize Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 09/16] petalogix_ml605_mmu: Fix machine node attachment Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 10/16] petalogix_ml605_mmu: Attach ethernet to machine Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 11/16] xilinx_axienet: Create Proxy object for stream Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 12/16] xilinx_axidma: " Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 13/16] xilinx_axidma: Fix rx/tx halted bit Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 14/16] stream: Add flow control API Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 15/16] xilinx_axienet/dma: Implement rx path flow control Peter Crosthwaite
2013-04-03 5:17 ` [Qemu-devel] [PATCH v5 16/16] stream: Remove app argument hack Peter Crosthwaite
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).