Skip to content

Commit a2dccdb

Browse files
committed
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* '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
2 parents 7d5fcdc + 33fea79 commit a2dccdb

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

arch/s390/kernel/entry.S

+10-2
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,16 @@ pgm_no_vtime2:
535535
l %r3,__LC_PGM_ILC # load program interruption code
536536
la %r8,0x7f
537537
nr %r8,%r3 # clear per-event-bit and ilc
538-
be BASED(pgm_exit) # only per or per+check ?
539-
b BASED(pgm_do_call)
538+
be BASED(pgm_exit2) # only per or per+check ?
539+
l %r7,BASED(.Ljump_table)
540+
sll %r8,2
541+
l %r7,0(%r8,%r7) # load address of handler routine
542+
la %r2,SP_PTREGS(%r15) # address of register-save area
543+
basr %r14,%r7 # branch to interrupt-handler
544+
pgm_exit2:
545+
TRACE_IRQS_ON
546+
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
547+
b BASED(sysc_return)
540548

541549
#
542550
# it was a single stepped SVC that is causing all the trouble

arch/s390/kernel/entry64.S

+10-2
Original file line numberDiff line numberDiff line change
@@ -544,8 +544,16 @@ pgm_no_vtime2:
544544
lgf %r3,__LC_PGM_ILC # load program interruption code
545545
lghi %r8,0x7f
546546
ngr %r8,%r3 # clear per-event-bit and ilc
547-
je pgm_exit
548-
j pgm_do_call
547+
je pgm_exit2
548+
sll %r8,3
549+
larl %r1,pgm_check_table
550+
lg %r1,0(%r8,%r1) # load address of handler routine
551+
la %r2,SP_PTREGS(%r15) # address of register-save area
552+
basr %r14,%r1 # branch to interrupt-handler
553+
pgm_exit2:
554+
TRACE_IRQS_ON
555+
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
556+
j sysc_return
549557

550558
#
551559
# it was a single stepped SVC that is causing all the trouble

arch/s390/kernel/time.c

+12-6
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,11 @@ void etr_switch_to_local(void)
524524
if (!etr_eacr.sl)
525525
return;
526526
disable_sync_clock(NULL);
527-
set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
528-
queue_work(time_sync_wq, &etr_work);
527+
if (!test_and_set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events)) {
528+
etr_eacr.es = etr_eacr.sl = 0;
529+
etr_setr(&etr_eacr);
530+
queue_work(time_sync_wq, &etr_work);
531+
}
529532
}
530533

531534
/*
@@ -539,8 +542,11 @@ void etr_sync_check(void)
539542
if (!etr_eacr.es)
540543
return;
541544
disable_sync_clock(NULL);
542-
set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
543-
queue_work(time_sync_wq, &etr_work);
545+
if (!test_and_set_bit(ETR_EVENT_SYNC_CHECK, &etr_events)) {
546+
etr_eacr.es = 0;
547+
etr_setr(&etr_eacr);
548+
queue_work(time_sync_wq, &etr_work);
549+
}
544550
}
545551

546552
/*
@@ -902,7 +908,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
902908
* Do not try to get the alternate port aib if the clock
903909
* is not in sync yet.
904910
*/
905-
if (!check_sync_clock())
911+
if (!eacr.es || !check_sync_clock())
906912
return eacr;
907913

908914
/*
@@ -1064,7 +1070,7 @@ static void etr_work_fn(struct work_struct *work)
10641070
* If the clock is in sync just update the eacr and return.
10651071
* If there is no valid sync port wait for a port update.
10661072
*/
1067-
if (check_sync_clock() || sync_port < 0) {
1073+
if ((eacr.es && check_sync_clock()) || sync_port < 0) {
10681074
etr_update_eacr(eacr);
10691075
etr_set_tolec_timeout(now);
10701076
goto out_unlock;

0 commit comments

Comments
 (0)