Commit a2dccdb2055abeb8a7ce8e45e5f83de9c980a00c

Authored by Linus Torvalds

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;