These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / s390 / kernel / time.c
index 170ddd2..99f84ac 100644 (file)
@@ -58,6 +58,9 @@ EXPORT_SYMBOL_GPL(sched_clock_base_cc);
 
 static DEFINE_PER_CPU(struct clock_event_device, comparators);
 
+ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
+EXPORT_SYMBOL(s390_epoch_delta_notifier);
+
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
@@ -76,7 +79,7 @@ unsigned long long monotonic_clock(void)
 }
 EXPORT_SYMBOL(monotonic_clock);
 
-void tod_to_timeval(__u64 todval, struct timespec *xt)
+void tod_to_timeval(__u64 todval, struct timespec64 *xt)
 {
        unsigned long long sec;
 
@@ -117,11 +120,6 @@ static int s390_next_event(unsigned long delta,
        return 0;
 }
 
-static void s390_set_mode(enum clock_event_mode mode,
-                         struct clock_event_device *evt)
-{
-}
-
 /*
  * Set up lowcore and control register of the current cpu to
  * enable TOD clock and clock comparator interrupts.
@@ -145,7 +143,6 @@ void init_cpu_timer(void)
        cd->rating              = 400;
        cd->cpumask             = cpumask_of(cpu);
        cd->set_next_event      = s390_next_event;
-       cd->set_mode            = s390_set_mode;
 
        clockevents_register_device(cd);
 
@@ -181,12 +178,12 @@ static void timing_alert_interrupt(struct ext_code ext_code,
 static void etr_reset(void);
 static void stp_reset(void);
 
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
 {
        tod_to_timeval(get_tod_clock() - TOD_UNIX_EPOCH, ts);
 }
 
-void read_boot_clock(struct timespec *ts)
+void read_boot_clock64(struct timespec64 *ts)
 {
        tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, ts);
 }
@@ -381,7 +378,7 @@ static void disable_sync_clock(void *dummy)
         * increase the "sequence" counter to avoid the race of an
         * etr event and the complete recovery against get_sync_clock.
         */
-       atomic_clear_mask(0x80000000, sw_ptr);
+       atomic_andnot(0x80000000, sw_ptr);
        atomic_inc(sw_ptr);
 }
 
@@ -392,7 +389,7 @@ static void disable_sync_clock(void *dummy)
 static void enable_sync_clock(void)
 {
        atomic_t *sw_ptr = this_cpu_ptr(&clock_sync_word);
-       atomic_set_mask(0x80000000, sw_ptr);
+       atomic_or(0x80000000, sw_ptr);
 }
 
 /*
@@ -545,16 +542,17 @@ arch_initcall(etr_init);
  * Switch to local machine check. This is called when the last usable
  * ETR port goes inactive. After switch to local the clock is not in sync.
  */
-void etr_switch_to_local(void)
+int etr_switch_to_local(void)
 {
        if (!etr_eacr.sl)
-               return;
+               return 0;
        disable_sync_clock(NULL);
        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);
+               return 1;
        }
+       return 0;
 }
 
 /*
@@ -563,16 +561,22 @@ void etr_switch_to_local(void)
  * After a ETR sync check the clock is not in sync. The machine check
  * is broadcasted to all cpus at the same time.
  */
-void etr_sync_check(void)
+int etr_sync_check(void)
 {
        if (!etr_eacr.es)
-               return;
+               return 0;
        disable_sync_clock(NULL);
        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);
+               return 1;
        }
+       return 0;
+}
+
+void etr_queue_work(void)
+{
+       queue_work(time_sync_wq, &etr_work);
 }
 
 /*
@@ -752,7 +756,7 @@ static void clock_sync_cpu(struct clock_sync_data *sync)
 static int etr_sync_clock(void *data)
 {
        static int first;
-       unsigned long long clock, old_clock, delay, delta;
+       unsigned long long clock, old_clock, clock_delta, delay, delta;
        struct clock_sync_data *etr_sync;
        struct etr_aib *sync_port, *aib;
        int port;
@@ -789,6 +793,9 @@ static int etr_sync_clock(void *data)
                delay = (unsigned long long)
                        (aib->edf2.etv - sync_port->edf2.etv) << 32;
                delta = adjust_time(old_clock, clock, delay);
+               clock_delta = clock - old_clock;
+               atomic_notifier_call_chain(&s390_epoch_delta_notifier, 0,
+                                          &clock_delta);
                etr_sync->fixup_cc = delta;
                fixup_clock_comparator(delta);
                /* Verify that the clock is properly set. */
@@ -1504,10 +1511,10 @@ static void stp_timing_alert(struct stp_irq_parm *intparm)
  * After a STP sync check the clock is not in sync. The machine check
  * is broadcasted to all cpus at the same time.
  */
-void stp_sync_check(void)
+int stp_sync_check(void)
 {
        disable_sync_clock(NULL);
-       queue_work(time_sync_wq, &stp_work);
+       return 1;
 }
 
 /*
@@ -1516,17 +1523,21 @@ void stp_sync_check(void)
  * have matching CTN ids and have a valid stratum-1 configuration
  * but the configurations do not match.
  */
-void stp_island_check(void)
+int stp_island_check(void)
 {
        disable_sync_clock(NULL);
-       queue_work(time_sync_wq, &stp_work);
+       return 1;
 }
 
+void stp_queue_work(void)
+{
+       queue_work(time_sync_wq, &stp_work);
+}
 
 static int stp_sync_clock(void *data)
 {
        static int first;
-       unsigned long long old_clock, delta;
+       unsigned long long old_clock, delta, new_clock, clock_delta;
        struct clock_sync_data *stp_sync;
        int rc;
 
@@ -1551,7 +1562,11 @@ static int stp_sync_clock(void *data)
                old_clock = get_tod_clock();
                rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0);
                if (rc == 0) {
-                       delta = adjust_time(old_clock, get_tod_clock(), 0);
+                       new_clock = get_tod_clock();
+                       delta = adjust_time(old_clock, new_clock, 0);
+                       clock_delta = new_clock - old_clock;
+                       atomic_notifier_call_chain(&s390_epoch_delta_notifier,
+                                                  0, &clock_delta);
                        fixup_clock_comparator(delta);
                        rc = chsc_sstpi(stp_page, &stp_info,
                                        sizeof(struct stp_sstpi));