aboutsummaryrefslogtreecommitdiff
path: root/hw/net/cadence_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/net/cadence_gem.c')
-rw-r--r--hw/net/cadence_gem.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index d4de8ad9f1..3943187572 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -300,6 +300,8 @@
#define DESC_1_RX_SOF 0x00004000
#define DESC_1_RX_EOF 0x00008000
+#define GEM_MODID_VALUE 0x00020118
+
static inline unsigned tx_desc_get_buffer(unsigned *desc)
{
return desc[0];
@@ -481,14 +483,17 @@ static int gem_can_receive(NetClientState *nc)
}
for (i = 0; i < s->num_priority_queues; i++) {
- if (rx_desc_get_ownership(s->rx_desc[i]) == 1) {
- if (s->can_rx_state != 2) {
- s->can_rx_state = 2;
- DB_PRINT("can't receive - busy buffer descriptor (q%d) 0x%x\n",
- i, s->rx_desc_addr[i]);
- }
- return 0;
+ if (rx_desc_get_ownership(s->rx_desc[i]) != 1) {
+ break;
+ }
+ };
+
+ if (i == s->num_priority_queues) {
+ if (s->can_rx_state != 2) {
+ s->can_rx_state = 2;
+ DB_PRINT("can't receive - all the buffer descriptors are busy\n");
}
+ return 0;
}
if (s->can_rx_state != 0) {
@@ -506,7 +511,18 @@ static void gem_update_int_status(CadenceGEMState *s)
{
int i;
- if ((s->num_priority_queues == 1) && s->regs[GEM_ISR]) {
+ if (!s->regs[GEM_ISR]) {
+ /* ISR isn't set, clear all the interrupts */
+ for (i = 0; i < s->num_priority_queues; ++i) {
+ qemu_set_irq(s->irq[i], 0);
+ }
+ return;
+ }
+
+ /* If we get here we know s->regs[GEM_ISR] is set, so we don't need to
+ * check it again.
+ */
+ if (s->num_priority_queues == 1) {
/* No priority queues, just trigger the interrupt */
DB_PRINT("asserting int.\n");
qemu_set_irq(s->irq[0], 1);
@@ -790,8 +806,8 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q)
{
DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]);
/* read current descriptor */
- cpu_physical_memory_read(s->rx_desc_addr[0],
- (uint8_t *)s->rx_desc[0], sizeof(s->rx_desc[0]));
+ cpu_physical_memory_read(s->rx_desc_addr[q],
+ (uint8_t *)s->rx_desc[q], sizeof(s->rx_desc[q]));
/* Descriptor owned by software ? */
if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
@@ -1209,7 +1225,7 @@ static void gem_reset(DeviceState *d)
s->regs[GEM_TXPAUSE] = 0x0000ffff;
s->regs[GEM_TXPARTIALSF] = 0x000003ff;
s->regs[GEM_RXPARTIALSF] = 0x000003ff;
- s->regs[GEM_MODID] = 0x00020118;
+ s->regs[GEM_MODID] = s->revision;
s->regs[GEM_DESCONF] = 0x02500111;
s->regs[GEM_DESCONF2] = 0x2ab13fff;
s->regs[GEM_DESCONF5] = 0x002f2145;
@@ -1271,7 +1287,6 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
{
CadenceGEMState *s;
uint32_t retval;
- int i;
s = (CadenceGEMState *)opaque;
offset >>= 2;
@@ -1282,9 +1297,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
switch (offset) {
case GEM_ISR:
DB_PRINT("lowering irqs on ISR read\n");
- for (i = 0; i < s->num_priority_queues; ++i) {
- qemu_set_irq(s->irq[i], 0);
- }
+ /* The interrupts get updated at the end of the function. */
break;
case GEM_PHYMNTNC:
if (retval & GEM_PHYMNTNC_OP_R) {
@@ -1508,6 +1521,8 @@ static const VMStateDescription vmstate_cadence_gem = {
static Property gem_properties[] = {
DEFINE_NIC_PROPERTIES(CadenceGEMState, conf),
+ DEFINE_PROP_UINT32("revision", CadenceGEMState, revision,
+ GEM_MODID_VALUE),
DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState,
num_priority_queues, 1),
DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState,