Commit a2dccdb2055abeb8a7ce8e45e5f83de9c980a00c
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
Showing 3 changed files Side-by-side Diff
arch/s390/kernel/entry.S
... | ... | @@ -535,8 +535,16 @@ |
535 | 535 | l %r3,__LC_PGM_ILC # load program interruption code |
536 | 536 | la %r8,0x7f |
537 | 537 | 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) | |
540 | 548 | |
541 | 549 | # |
542 | 550 | # it was a single stepped SVC that is causing all the trouble |
arch/s390/kernel/entry64.S
... | ... | @@ -544,8 +544,16 @@ |
544 | 544 | lgf %r3,__LC_PGM_ILC # load program interruption code |
545 | 545 | lghi %r8,0x7f |
546 | 546 | 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 | |
549 | 557 | |
550 | 558 | # |
551 | 559 | # it was a single stepped SVC that is causing all the trouble |
arch/s390/kernel/time.c
... | ... | @@ -524,8 +524,11 @@ |
524 | 524 | if (!etr_eacr.sl) |
525 | 525 | return; |
526 | 526 | 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 | + } | |
529 | 532 | } |
530 | 533 | |
531 | 534 | /* |
... | ... | @@ -539,8 +542,11 @@ |
539 | 542 | if (!etr_eacr.es) |
540 | 543 | return; |
541 | 544 | 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 | + } | |
544 | 550 | } |
545 | 551 | |
546 | 552 | /* |
... | ... | @@ -902,7 +908,7 @@ |
902 | 908 | * Do not try to get the alternate port aib if the clock |
903 | 909 | * is not in sync yet. |
904 | 910 | */ |
905 | - if (!check_sync_clock()) | |
911 | + if (!eacr.es || !check_sync_clock()) | |
906 | 912 | return eacr; |
907 | 913 | |
908 | 914 | /* |
... | ... | @@ -1064,7 +1070,7 @@ |
1064 | 1070 | * If the clock is in sync just update the eacr and return. |
1065 | 1071 | * If there is no valid sync port wait for a port update. |
1066 | 1072 | */ |
1067 | - if (check_sync_clock() || sync_port < 0) { | |
1073 | + if ((eacr.es && check_sync_clock()) || sync_port < 0) { | |
1068 | 1074 | etr_update_eacr(eacr); |
1069 | 1075 | etr_set_tolec_timeout(now); |
1070 | 1076 | goto out_unlock; |