Patchwork [2/3] s390: Keep I/O interrupts enabled for all iscs.

login
register
mail settings
Submitter Alexander Graf
Date Feb. 12, 2013, 10:32 p.m.
Message ID <1360708343-30339-3-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/220003/
State New
Headers show

Comments

Alexander Graf - Feb. 12, 2013, 10:32 p.m.
From: Cornelia Huck <cornelia.huck@de.ibm.com>

do_io_interrupt() would stop scanning further iscs if it found
an I/O interrupt it could inject. This might cause the pending
interrupt indication for I/O interrupts to be reset although there
might be queued I/O interrupts for subsequent iscs.

Fix this by reordering the logic: Inject the I/O interrupt immediately
and continue searching all iscs for queued interrupts.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 target-s390x/helper.c |   40 +++++++++++++++++++++-------------------
 1 files changed, 21 insertions(+), 19 deletions(-)

Patch

diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 043feb2..9f9088b 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -617,7 +617,6 @@  static void do_ext_interrupt(CPUS390XState *env)
 
 static void do_io_interrupt(CPUS390XState *env)
 {
-    uint64_t mask = 0, addr = 0;
     LowCore *lowcore;
     IOIntQueue *q;
     uint8_t isc;
@@ -642,36 +641,39 @@  static void do_io_interrupt(CPUS390XState *env)
             disable = 0;
             continue;
         }
-        found = 1;
-        lowcore = cpu_map_lowcore(env);
+        if (!found) {
+            uint64_t mask, addr;
 
-        lowcore->subchannel_id = cpu_to_be16(q->id);
-        lowcore->subchannel_nr = cpu_to_be16(q->nr);
-        lowcore->io_int_parm = cpu_to_be32(q->parm);
-        lowcore->io_int_word = cpu_to_be32(q->word);
-        lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
-        lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
-        mask = be64_to_cpu(lowcore->io_new_psw.mask);
-        addr = be64_to_cpu(lowcore->io_new_psw.addr);
+            found = 1;
+            lowcore = cpu_map_lowcore(env);
 
-        cpu_unmap_lowcore(lowcore);
+            lowcore->subchannel_id = cpu_to_be16(q->id);
+            lowcore->subchannel_nr = cpu_to_be16(q->nr);
+            lowcore->io_int_parm = cpu_to_be32(q->parm);
+            lowcore->io_int_word = cpu_to_be32(q->word);
+            lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
+            lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
+            mask = be64_to_cpu(lowcore->io_new_psw.mask);
+            addr = be64_to_cpu(lowcore->io_new_psw.addr);
 
-        env->io_index[isc]--;
+            cpu_unmap_lowcore(lowcore);
+
+            env->io_index[isc]--;
+
+            DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
+                    env->psw.mask, env->psw.addr);
+            load_psw(env, mask, addr);
+        }
         if (env->io_index[isc] >= 0) {
             disable = 0;
         }
-        break;
+        continue;
     }
 
     if (disable) {
         env->pending_int &= ~INTERRUPT_IO;
     }
 
-    if (found) {
-        DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
-                env->psw.mask, env->psw.addr);
-        load_psw(env, mask, addr);
-    }
 }
 
 static void do_mchk_interrupt(CPUS390XState *env)