Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
Linus Torvalds [Thu, 29 Jul 2010 22:23:28 +0000 (15:23 -0700)]
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
  [S390] etr: fix clock synchronization race
  [S390] Fix IRQ tracing in case of PER

arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/time.c

index d5e3e60..bea9ee3 100644 (file)
@@ -535,8 +535,16 @@ pgm_no_vtime2:
        l       %r3,__LC_PGM_ILC        # load program interruption code
        la      %r8,0x7f
        nr      %r8,%r3                 # clear per-event-bit and ilc
-       be      BASED(pgm_exit)         # only per or per+check ?
-       b       BASED(pgm_do_call)
+       be      BASED(pgm_exit2)        # only per or per+check ?
+       l       %r7,BASED(.Ljump_table)
+       sll     %r8,2
+       l       %r7,0(%r8,%r7)          # load address of handler routine
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       basr    %r14,%r7                # branch to interrupt-handler
+pgm_exit2:
+       TRACE_IRQS_ON
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       b       BASED(sysc_return)
 
 #
 # it was a single stepped SVC that is causing all the trouble
index e7192e1..8bccec1 100644 (file)
@@ -544,8 +544,16 @@ pgm_no_vtime2:
        lgf     %r3,__LC_PGM_ILC        # load program interruption code
        lghi    %r8,0x7f
        ngr     %r8,%r3                 # clear per-event-bit and ilc
-       je      pgm_exit
-       j       pgm_do_call
+       je      pgm_exit2
+       sll     %r8,3
+       larl    %r1,pgm_check_table
+       lg      %r1,0(%r8,%r1)          # load address of handler routine
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       basr    %r14,%r1                # branch to interrupt-handler
+pgm_exit2:
+       TRACE_IRQS_ON
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       j       sysc_return
 
 #
 # it was a single stepped SVC that is causing all the trouble
index a2163c9..15a7536 100644 (file)
@@ -524,8 +524,11 @@ void etr_switch_to_local(void)
        if (!etr_eacr.sl)
                return;
        disable_sync_clock(NULL);
-       set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
-       queue_work(time_sync_wq, &etr_work);
+       if (!test_and_set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events)) {
+               etr_eacr.es = etr_eacr.sl = 0;
+               etr_setr(&etr_eacr);
+               queue_work(time_sync_wq, &etr_work);
+       }
 }
 
 /*
@@ -539,8 +542,11 @@ void etr_sync_check(void)
        if (!etr_eacr.es)
                return;
        disable_sync_clock(NULL);
-       set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
-       queue_work(time_sync_wq, &etr_work);
+       if (!test_and_set_bit(ETR_EVENT_SYNC_CHECK, &etr_events)) {
+               etr_eacr.es = 0;
+               etr_setr(&etr_eacr);
+               queue_work(time_sync_wq, &etr_work);
+       }
 }
 
 /*
@@ -902,7 +908,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
         * Do not try to get the alternate port aib if the clock
         * is not in sync yet.
         */
-       if (!check_sync_clock())
+       if (!eacr.es || !check_sync_clock())
                return eacr;
 
        /*
@@ -1064,7 +1070,7 @@ static void etr_work_fn(struct work_struct *work)
         * If the clock is in sync just update the eacr and return.
         * If there is no valid sync port wait for a port update.
         */
-       if (check_sync_clock() || sync_port < 0) {
+       if ((eacr.es && check_sync_clock()) || sync_port < 0) {
                etr_update_eacr(eacr);
                etr_set_tolec_timeout(now);
                goto out_unlock;