aboutsummaryrefslogtreecommitdiff
path: root/hw/net
diff options
context:
space:
mode:
authorAlistair Francis <alistair.francis@xilinx.com>2017-04-20 17:32:29 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-04-20 17:39:17 +0100
commit596b6f51b71eb1dd6f603b3f5aeb0a2f9300b21f (patch)
tree47863821f83234cf7145de9fb7428e6a6870925e /hw/net
parentdacc0566acda512ebaf18ad051b387a56a3f7253 (diff)
downloadqemu-596b6f51b71eb1dd6f603b3f5aeb0a2f9300b21f.zip
qemu-596b6f51b71eb1dd6f603b3f5aeb0a2f9300b21f.tar.gz
qemu-596b6f51b71eb1dd6f603b3f5aeb0a2f9300b21f.tar.bz2
cadence_gem: Correct the interupt logic
This patch fixes two mistakes in the interrupt logic. First we only trigger single-queue or multi-queue interrupts if the status register is set. This logic was already used for non multi-queue interrupts but it also applies to multi-queue interrupts. Secondly we need to lower the interrupts if the ISR isn't set. As part of this we can remove the other interrupt lowering logic and consolidate it inside gem_update_int_status(). Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> Message-id: 438bcc014f8f8a2f8f68f322cb6a53f4c04688c2.1491947224.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/net')
-rw-r--r--hw/net/cadence_gem.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index a66a9cc..e1962e1 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -509,7 +509,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);
@@ -1274,7 +1285,6 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
{
CadenceGEMState *s;
uint32_t retval;
- int i;
s = (CadenceGEMState *)opaque;
offset >>= 2;
@@ -1285,9 +1295,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) {