~ubuntu-branches/ubuntu/lucid/linux-rt/lucid

« back to all changes in this revision

Viewing changes to arch/s390/kernel/time.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2009-08-05 23:00:52 UTC
  • Revision ID: james.westby@ubuntu.com-20090805230052-7xedvqcyk9dnnxb2
Tags: 2.6.31-1.1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#include <linux/notifier.h>
37
37
#include <linux/clocksource.h>
38
38
#include <linux/clockchips.h>
39
 
#include <linux/bootmem.h>
40
39
#include <asm/uaccess.h>
41
40
#include <asm/delay.h>
42
41
#include <asm/s390_ext.h>
52
51
#define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
53
52
#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
54
53
 
55
 
/* The value of the TOD clock for 1.1.1970. */
56
 
#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
57
 
 
58
54
/*
59
55
 * Create a small time difference between the timer interrupts
60
56
 * on the different cpus to avoid lock contention.
63
59
 
64
60
#define TICK_SIZE tick
65
61
 
66
 
static ext_int_info_t ext_int_info_cc;
67
 
static ext_int_info_t ext_int_etr_cc;
68
 
static u64 sched_clock_base_cc;
 
62
u64 sched_clock_base_cc = -1;   /* Force to data section. */
69
63
 
70
64
static DEFINE_PER_CPU(struct clock_event_device, comparators);
71
65
 
72
66
/*
73
67
 * Scheduler clock - returns current time in nanosec units.
74
68
 */
75
 
unsigned long long sched_clock(void)
 
69
unsigned long long notrace sched_clock(void)
76
70
{
77
71
        return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9;
78
72
}
97
91
        xtime->tv_nsec = ((todval * 1000) >> 12);
98
92
}
99
93
 
100
 
#ifdef CONFIG_PROFILING
101
 
#define s390_do_profile()       profile_tick(CPU_PROFILING)
102
 
#else
103
 
#define s390_do_profile()       do { ; } while(0)
104
 
#endif /* CONFIG_PROFILING */
105
 
 
106
94
void clock_comparator_work(void)
107
95
{
108
96
        struct clock_event_device *cd;
111
99
        set_clock_comparator(S390_lowcore.clock_comparator);
112
100
        cd = &__get_cpu_var(comparators);
113
101
        cd->event_handler(cd);
114
 
        s390_do_profile();
115
102
}
116
103
 
117
104
/*
195
182
static void etr_reset(void);
196
183
static void stp_reset(void);
197
184
 
198
 
/*
199
 
 * Get the TOD clock running.
200
 
 */
201
 
static u64 __init reset_tod_clock(void)
 
185
unsigned long read_persistent_clock(void)
202
186
{
203
 
        u64 time;
204
 
 
205
 
        etr_reset();
206
 
        stp_reset();
207
 
        if (store_clock(&time) == 0)
208
 
                return time;
209
 
        /* TOD clock not running. Set the clock to Unix Epoch. */
210
 
        if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0)
211
 
                panic("TOD clock not operational.");
212
 
 
213
 
        return TOD_UNIX_EPOCH;
 
187
        struct timespec ts;
 
188
 
 
189
        tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, &ts);
 
190
        return ts.tv_sec;
214
191
}
215
192
 
216
 
static cycle_t read_tod_clock(void)
 
193
static cycle_t read_tod_clock(struct clocksource *cs)
217
194
{
218
195
        return get_clock();
219
196
}
265
242
 */
266
243
void __init time_init(void)
267
244
{
268
 
        sched_clock_base_cc = reset_tod_clock();
 
245
        struct timespec ts;
 
246
        unsigned long flags;
 
247
        cycle_t now;
269
248
 
270
 
        /* set xtime */
271
 
        tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime);
272
 
        set_normalized_timespec(&wall_to_monotonic,
273
 
                                -xtime.tv_sec, -xtime.tv_nsec);
 
249
        /* Reset time synchronization interfaces. */
 
250
        etr_reset();
 
251
        stp_reset();
274
252
 
275
253
        /* request the clock comparator external interrupt */
276
 
        if (register_early_external_interrupt(0x1004,
277
 
                                              clock_comparator_interrupt,
278
 
                                              &ext_int_info_cc) != 0)
 
254
        if (register_external_interrupt(0x1004, clock_comparator_interrupt))
279
255
                panic("Couldn't request external interrupt 0x1004");
280
256
 
 
257
        /* request the timing alert external interrupt */
 
258
        if (register_external_interrupt(0x1406, timing_alert_interrupt))
 
259
                panic("Couldn't request external interrupt 0x1406");
 
260
 
281
261
        if (clocksource_register(&clocksource_tod) != 0)
282
262
                panic("Could not register TOD clock source");
283
263
 
284
 
        /* request the timing alert external interrupt */
285
 
        if (register_early_external_interrupt(0x1406,
286
 
                                              timing_alert_interrupt,
287
 
                                              &ext_int_etr_cc) != 0)
288
 
                panic("Couldn't request external interrupt 0x1406");
 
264
        /*
 
265
         * The TOD clock is an accurate clock. The xtime should be
 
266
         * initialized in a way that the difference between TOD and
 
267
         * xtime is reasonably small. Too bad that timekeeping_init
 
268
         * sets xtime.tv_nsec to zero. In addition the clock source
 
269
         * change from the jiffies clock source to the TOD clock
 
270
         * source add another error of up to 1/HZ second. The same
 
271
         * function sets wall_to_monotonic to a value that is too
 
272
         * small for /proc/uptime to be accurate.
 
273
         * Reset xtime and wall_to_monotonic to sane values.
 
274
         */
 
275
        write_seqlock_irqsave(&xtime_lock, flags);
 
276
        now = get_clock();
 
277
        tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime);
 
278
        clocksource_tod.cycle_last = now;
 
279
        clocksource_tod.raw_time = xtime;
 
280
        tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts);
 
281
        set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec);
 
282
        write_sequnlock_irqrestore(&xtime_lock, flags);
289
283
 
290
284
        /* Enable TOD clock interrupts on the boot cpu. */
291
285
        init_cpu_timer();
 
286
 
292
287
        /* Enable cpu timer interrupts on the boot cpu. */
293
288
        vtime_init();
294
289
}
331
326
}
332
327
 
333
328
static DEFINE_PER_CPU(atomic_t, clock_sync_word);
 
329
static DEFINE_MUTEX(clock_sync_mutex);
334
330
static unsigned long clock_sync_flags;
335
331
 
336
332
#define CLOCK_SYNC_HAS_ETR      0
394
390
        atomic_set_mask(0x80000000, sw_ptr);
395
391
}
396
392
 
 
393
/*
 
394
 * Function to check if the clock is in sync.
 
395
 */
 
396
static inline int check_sync_clock(void)
 
397
{
 
398
        atomic_t *sw_ptr;
 
399
        int rc;
 
400
 
 
401
        sw_ptr = &get_cpu_var(clock_sync_word);
 
402
        rc = (atomic_read(sw_ptr) & 0x80000000U) != 0;
 
403
        put_cpu_var(clock_sync_sync);
 
404
        return rc;
 
405
}
 
406
 
397
407
/* Single threaded workqueue used for etr and stp sync events */
398
408
static struct workqueue_struct *time_sync_wq;
399
409
 
485
495
        if (etr_setr(&etr_eacr) == 0) {
486
496
                etr_tolec = get_clock();
487
497
                set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags);
 
498
                if (etr_port0_online && etr_port1_online)
 
499
                        set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
488
500
        } else if (etr_port0_online || etr_port1_online) {
489
501
                pr_warning("The real or virtual hardware system does "
490
502
                           "not provide an ETR interface\n");
533
545
{
534
546
        if (!etr_eacr.sl)
535
547
                return;
536
 
        if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
537
 
                disable_sync_clock(NULL);
 
548
        disable_sync_clock(NULL);
538
549
        set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
539
550
        queue_work(time_sync_wq, &etr_work);
540
551
}
549
560
{
550
561
        if (!etr_eacr.es)
551
562
                return;
552
 
        if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
553
 
                disable_sync_clock(NULL);
 
563
        disable_sync_clock(NULL);
554
564
        set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
555
565
        queue_work(time_sync_wq, &etr_work);
556
566
}
914
924
         * Do not try to get the alternate port aib if the clock
915
925
         * is not in sync yet.
916
926
         */
917
 
        if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es)
 
927
        if (!check_sync_clock())
918
928
                return eacr;
919
929
 
920
930
        /*
997
1007
                on_each_cpu(disable_sync_clock, NULL, 1);
998
1008
                del_timer_sync(&etr_timer);
999
1009
                etr_update_eacr(eacr);
1000
 
                clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1001
1010
                goto out_unlock;
1002
1011
        }
1003
1012
 
1071
1080
                /* Both ports not usable. */
1072
1081
                eacr.es = eacr.sl = 0;
1073
1082
                sync_port = -1;
1074
 
                clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1075
1083
        }
1076
1084
 
1077
 
        if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
1078
 
                eacr.es = 0;
1079
 
 
1080
1085
        /*
1081
1086
         * If the clock is in sync just update the eacr and return.
1082
1087
         * If there is no valid sync port wait for a port update.
1083
1088
         */
1084
 
        if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) ||
1085
 
            eacr.es || sync_port < 0) {
 
1089
        if (check_sync_clock() || sync_port < 0) {
1086
1090
                etr_update_eacr(eacr);
1087
1091
                etr_set_tolec_timeout(now);
1088
1092
                goto out_unlock;
1103
1107
         * and set up a timer to try again after 0.5 seconds
1104
1108
         */
1105
1109
        etr_update_eacr(eacr);
1106
 
        set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1107
1110
        if (now < etr_tolec + (1600000 << 12) ||
1108
1111
            etr_sync_clock_stop(&aib, sync_port) != 0) {
1109
1112
                /* Sync failed. Try again in 1/2 second. */
1110
1113
                eacr.es = 0;
1111
1114
                etr_update_eacr(eacr);
1112
 
                clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1113
1115
                etr_set_sync_timeout();
1114
1116
        } else
1115
1117
                etr_set_tolec_timeout(now);
1191
1193
                return -EINVAL;
1192
1194
        if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
1193
1195
                return -EOPNOTSUPP;
 
1196
        mutex_lock(&clock_sync_mutex);
1194
1197
        if (dev == &etr_port0_dev) {
1195
1198
                if (etr_port0_online == value)
1196
 
                        return count;   /* Nothing to do. */
 
1199
                        goto out;       /* Nothing to do. */
1197
1200
                etr_port0_online = value;
 
1201
                if (etr_port0_online && etr_port1_online)
 
1202
                        set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
 
1203
                else
 
1204
                        clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1198
1205
                set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
1199
1206
                queue_work(time_sync_wq, &etr_work);
1200
1207
        } else {
1201
1208
                if (etr_port1_online == value)
1202
 
                        return count;   /* Nothing to do. */
 
1209
                        goto out;       /* Nothing to do. */
1203
1210
                etr_port1_online = value;
 
1211
                if (etr_port0_online && etr_port1_online)
 
1212
                        set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
 
1213
                else
 
1214
                        clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1204
1215
                set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
1205
1216
                queue_work(time_sync_wq, &etr_work);
1206
1217
        }
 
1218
out:
 
1219
        mutex_unlock(&clock_sync_mutex);
1207
1220
        return count;
1208
1221
}
1209
1222
 
1405
1418
static void stp_work_fn(struct work_struct *work);
1406
1419
static DEFINE_MUTEX(stp_work_mutex);
1407
1420
static DECLARE_WORK(stp_work, stp_work_fn);
 
1421
static struct timer_list stp_timer;
1408
1422
 
1409
1423
static int __init early_parse_stp(char *p)
1410
1424
{
1423
1437
{
1424
1438
        int rc;
1425
1439
 
1426
 
        stp_page = alloc_bootmem_pages(PAGE_SIZE);
 
1440
        stp_page = (void *) get_zeroed_page(GFP_ATOMIC);
1427
1441
        rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
1428
1442
        if (rc == 0)
1429
1443
                set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
1430
1444
        else if (stp_online) {
1431
1445
                pr_warning("The real or virtual hardware system does "
1432
1446
                           "not provide an STP interface\n");
1433
 
                free_bootmem((unsigned long) stp_page, PAGE_SIZE);
 
1447
                free_page((unsigned long) stp_page);
1434
1448
                stp_page = NULL;
1435
1449
                stp_online = 0;
1436
1450
        }
1437
1451
}
1438
1452
 
 
1453
static void stp_timeout(unsigned long dummy)
 
1454
{
 
1455
        queue_work(time_sync_wq, &stp_work);
 
1456
}
 
1457
 
1439
1458
static int __init stp_init(void)
1440
1459
{
1441
1460
        if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
1442
1461
                return 0;
 
1462
        setup_timer(&stp_timer, stp_timeout, 0UL);
1443
1463
        time_init_wq();
1444
1464
        if (!stp_online)
1445
1465
                return 0;
1471
1491
 */
1472
1492
void stp_sync_check(void)
1473
1493
{
1474
 
        if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
1475
 
                return;
1476
1494
        disable_sync_clock(NULL);
1477
1495
        queue_work(time_sync_wq, &stp_work);
1478
1496
}
1485
1503
 */
1486
1504
void stp_island_check(void)
1487
1505
{
1488
 
        if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
1489
 
                return;
1490
1506
        disable_sync_clock(NULL);
1491
1507
        queue_work(time_sync_wq, &stp_work);
1492
1508
}
1513
1529
 
1514
1530
        enable_sync_clock();
1515
1531
 
1516
 
        set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1517
 
        if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
1518
 
                queue_work(time_sync_wq, &etr_work);
1519
 
 
1520
1532
        rc = 0;
1521
1533
        if (stp_info.todoff[0] || stp_info.todoff[1] ||
1522
1534
            stp_info.todoff[2] || stp_info.todoff[3] ||
1535
1547
        if (rc) {
1536
1548
                disable_sync_clock(NULL);
1537
1549
                stp_sync->in_sync = -EAGAIN;
1538
 
                clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1539
 
                if (etr_port0_online || etr_port1_online)
1540
 
                        queue_work(time_sync_wq, &etr_work);
1541
1550
        } else
1542
1551
                stp_sync->in_sync = 1;
1543
1552
        xchg(&first, 0);
1558
1567
 
1559
1568
        if (!stp_online) {
1560
1569
                chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
 
1570
                del_timer_sync(&stp_timer);
1561
1571
                goto out_unlock;
1562
1572
        }
1563
1573
 
1569
1579
        if (rc || stp_info.c == 0)
1570
1580
                goto out_unlock;
1571
1581
 
 
1582
        /* Skip synchronization if the clock is already in sync. */
 
1583
        if (check_sync_clock())
 
1584
                goto out_unlock;
 
1585
 
1572
1586
        memset(&stp_sync, 0, sizeof(stp_sync));
1573
1587
        get_online_cpus();
1574
1588
        atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
1575
1589
        stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map);
1576
1590
        put_online_cpus();
1577
1591
 
 
1592
        if (!check_sync_clock())
 
1593
                /*
 
1594
                 * There is a usable clock but the synchonization failed.
 
1595
                 * Retry after a second.
 
1596
                 */
 
1597
                mod_timer(&stp_timer, jiffies + HZ);
 
1598
 
1578
1599
out_unlock:
1579
1600
        mutex_unlock(&stp_work_mutex);
1580
1601
}
1684
1705
                return -EINVAL;
1685
1706
        if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
1686
1707
                return -EOPNOTSUPP;
 
1708
        mutex_lock(&clock_sync_mutex);
1687
1709
        stp_online = value;
 
1710
        if (stp_online)
 
1711
                set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
 
1712
        else
 
1713
                clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1688
1714
        queue_work(time_sync_wq, &stp_work);
 
1715
        mutex_unlock(&clock_sync_mutex);
1689
1716
        return count;
1690
1717
}
1691
1718