s390/time: STP sync clock correction
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 31 May 2016 07:09:57 +0000 (09:09 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 13 Jun 2016 13:58:19 +0000 (15:58 +0200)
The sync clock operation of the channel subsystem call for STP delivers
the TOD clock difference as a result. Use this TOD clock difference
instead of the difference between the TOD timestamps before and after
the sync clock operation.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/cio.h
arch/s390/kernel/time.c
drivers/s390/cio/chsc.c

index d1e7b0a0feeb72649ae71ab8413c7693d022e24c..f7ed88cc066e25d5589025cb69aff45691368c43 100644 (file)
@@ -320,7 +320,7 @@ struct cio_iplinfo {
 extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo);
 
 /* Function from drivers/s390/cio/chsc.c */
-int chsc_sstpc(void *page, unsigned int op, u16 ctrl);
+int chsc_sstpc(void *page, unsigned int op, u16 ctrl, u64 *clock_delta);
 int chsc_sstpi(void *page, void *result, size_t size);
 
 #endif
index 9409d32f285e903580a50aa9e5b90ccd37f6b1cb..a725fd1c43152228115cb910f04eaad5795c269a 100644 (file)
@@ -1455,7 +1455,7 @@ static void __init stp_reset(void)
        int rc;
 
        stp_page = (void *) get_zeroed_page(GFP_ATOMIC);
-       rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
+       rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000, NULL);
        if (rc == 0)
                set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
        else if (stp_online) {
@@ -1554,11 +1554,10 @@ static int stp_sync_clock(void *data)
            stp_info.todoff[2] || stp_info.todoff[3] ||
            stp_info.tmd != 2) {
                old_clock = get_tod_clock();
-               rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0);
+               rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0, &clock_delta);
                if (rc == 0) {
-                       new_clock = get_tod_clock();
+                       new_clock = old_clock + clock_delta;
                        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);
@@ -1590,12 +1589,12 @@ static void stp_work_fn(struct work_struct *work)
        mutex_lock(&stp_work_mutex);
 
        if (!stp_online) {
-               chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
+               chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000, NULL);
                del_timer_sync(&stp_timer);
                goto out_unlock;
        }
 
-       rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
+       rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0, NULL);
        if (rc)
                goto out_unlock;
 
index c424c0c7367e360acd9ccd1ce899dc80bb575265..452193f7298cc5d5ecb3826f8c25550f7bd2bed9 100644 (file)
@@ -1176,7 +1176,7 @@ exit:
 EXPORT_SYMBOL_GPL(css_general_characteristics);
 EXPORT_SYMBOL_GPL(css_chsc_characteristics);
 
-int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
+int chsc_sstpc(void *page, unsigned int op, u16 ctrl, u64 *clock_delta)
 {
        struct {
                struct chsc_header request;
@@ -1186,7 +1186,9 @@ int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
                unsigned int ctrl : 16;
                unsigned int rsvd2[5];
                struct chsc_header response;
-               unsigned int rsvd3[7];
+               unsigned int rsvd3[3];
+               u64 clock_delta;
+               unsigned int rsvd4[2];
        } __attribute__ ((packed)) *rr;
        int rc;
 
@@ -1200,6 +1202,8 @@ int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
        if (rc)
                return -EIO;
        rc = (rr->response.code == 0x0001) ? 0 : -EIO;
+       if (clock_delta)
+               *clock_delta = rr->clock_delta;
        return rc;
 }