1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/ioctl.h>
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/errno.h>
27#include <linux/mm.h>
28#include <linux/fs.h>
29#include <linux/mmtimer.h>
30#include <linux/miscdevice.h>
31#include <linux/posix-timers.h>
32#include <linux/interrupt.h>
33#include <linux/time.h>
34#include <linux/math64.h>
35#include <linux/smp_lock.h>
36
37#include <asm/uaccess.h>
38#include <asm/sn/addrs.h>
39#include <asm/sn/intr.h>
40#include <asm/sn/shub_mmr.h>
41#include <asm/sn/nodepda.h>
42#include <asm/sn/shubio.h>
43
44MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
45MODULE_DESCRIPTION("SGI Altix RTC Timer");
46MODULE_LICENSE("GPL");
47
48
49#define MMTIMER_NAME "mmtimer"
50#define MMTIMER_DESC "SGI Altix RTC Timer"
51#define MMTIMER_VERSION "2.1"
52
53#define RTC_BITS 55
54
55extern unsigned long sn_rtc_cycles_per_second;
56
57#define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC))
58
59#define rtc_time() (*RTC_COUNTER_ADDR)
60
61static long mmtimer_ioctl(struct file *file, unsigned int cmd,
62 unsigned long arg);
63static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
64
65
66
67
68static unsigned long mmtimer_femtoperiod = 0;
69
70static const struct file_operations mmtimer_fops = {
71 .owner = THIS_MODULE,
72 .mmap = mmtimer_mmap,
73 .unlocked_ioctl = mmtimer_ioctl,
74};
75
76
77
78
79
80
81static int mmtimer_int_pending(int comparator)
82{
83 if (HUB_L((unsigned long *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)) &
84 SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator)
85 return 1;
86 else
87 return 0;
88}
89
90
91static void mmtimer_clr_int_pending(int comparator)
92{
93 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
94 SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator);
95}
96
97
98static void mmtimer_setup_int_0(int cpu, u64 expires)
99{
100 u64 val;
101
102
103 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 0UL);
104
105
106 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), -1L);
107
108
109 mmtimer_clr_int_pending(0);
110
111 val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC1_INT_CONFIG_IDX_SHFT) |
112 ((u64)cpu_physical_id(cpu) <<
113 SH_RTC1_INT_CONFIG_PID_SHFT);
114
115
116 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_CONFIG), val);
117
118
119 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 1UL);
120
121
122 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), expires);
123
124
125}
126
127
128static void mmtimer_setup_int_1(int cpu, u64 expires)
129{
130 u64 val;
131
132 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 0UL);
133
134 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), -1L);
135
136 mmtimer_clr_int_pending(1);
137
138 val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC2_INT_CONFIG_IDX_SHFT) |
139 ((u64)cpu_physical_id(cpu) <<
140 SH_RTC2_INT_CONFIG_PID_SHFT);
141
142 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_CONFIG), val);
143
144 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 1UL);
145
146 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), expires);
147}
148
149
150static void mmtimer_setup_int_2(int cpu, u64 expires)
151{
152 u64 val;
153
154 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 0UL);
155
156 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), -1L);
157
158 mmtimer_clr_int_pending(2);
159
160 val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC3_INT_CONFIG_IDX_SHFT) |
161 ((u64)cpu_physical_id(cpu) <<
162 SH_RTC3_INT_CONFIG_PID_SHFT);
163
164 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_CONFIG), val);
165
166 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 1UL);
167
168 HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), expires);
169}
170
171
172
173
174
175
176static int mmtimer_setup(int cpu, int comparator, unsigned long expires)
177{
178
179 switch (comparator) {
180 case 0:
181 mmtimer_setup_int_0(cpu, expires);
182 break;
183 case 1:
184 mmtimer_setup_int_1(cpu, expires);
185 break;
186 case 2:
187 mmtimer_setup_int_2(cpu, expires);
188 break;
189 }
190
191 if (rtc_time() <= expires)
192 return 1;
193
194
195
196
197
198 return mmtimer_int_pending(comparator);
199}
200
201static int mmtimer_disable_int(long nasid, int comparator)
202{
203 switch (comparator) {
204 case 0:
205 nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE),
206 0UL) : REMOTE_HUB_S(nasid, SH_RTC1_INT_ENABLE, 0UL);
207 break;
208 case 1:
209 nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE),
210 0UL) : REMOTE_HUB_S(nasid, SH_RTC2_INT_ENABLE, 0UL);
211 break;
212 case 2:
213 nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE),
214 0UL) : REMOTE_HUB_S(nasid, SH_RTC3_INT_ENABLE, 0UL);
215 break;
216 default:
217 return -EFAULT;
218 }
219 return 0;
220}
221
222#define COMPARATOR 1
223
224#define TIMER_OFF 0xbadcabLL
225#define TIMER_SET 0
226
227
228struct mmtimer {
229 struct rb_node list;
230 struct k_itimer *timer;
231 int cpu;
232};
233
234struct mmtimer_node {
235 spinlock_t lock ____cacheline_aligned;
236 struct rb_root timer_head;
237 struct rb_node *next;
238 struct tasklet_struct tasklet;
239};
240static struct mmtimer_node *timers;
241
242
243
244
245
246
247static void mmtimer_add_list(struct mmtimer *n)
248{
249 int nodeid = n->timer->it.mmtimer.node;
250 unsigned long expires = n->timer->it.mmtimer.expires;
251 struct rb_node **link = &timers[nodeid].timer_head.rb_node;
252 struct rb_node *parent = NULL;
253 struct mmtimer *x;
254
255
256
257
258 while (*link) {
259 parent = *link;
260 x = rb_entry(parent, struct mmtimer, list);
261
262 if (expires < x->timer->it.mmtimer.expires)
263 link = &(*link)->rb_left;
264 else
265 link = &(*link)->rb_right;
266 }
267
268
269
270
271
272 rb_link_node(&n->list, parent, link);
273 rb_insert_color(&n->list, &timers[nodeid].timer_head);
274
275 if (!timers[nodeid].next || expires < rb_entry(timers[nodeid].next,
276 struct mmtimer, list)->timer->it.mmtimer.expires)
277 timers[nodeid].next = &n->list;
278}
279
280
281
282
283
284static void mmtimer_set_next_timer(int nodeid)
285{
286 struct mmtimer_node *n = &timers[nodeid];
287 struct mmtimer *x;
288 struct k_itimer *t;
289 int o;
290
291restart:
292 if (n->next == NULL)
293 return;
294
295 x = rb_entry(n->next, struct mmtimer, list);
296 t = x->timer;
297 if (!t->it.mmtimer.incr) {
298
299 if (!mmtimer_setup(x->cpu, COMPARATOR,
300 t->it.mmtimer.expires)) {
301
302 tasklet_schedule(&n->tasklet);
303 }
304 return;
305 }
306
307
308 o = 0;
309 while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) {
310 unsigned long e, e1;
311 struct rb_node *next;
312 t->it.mmtimer.expires += t->it.mmtimer.incr << o;
313 t->it_overrun += 1 << o;
314 o++;
315 if (o > 20) {
316 printk(KERN_ALERT "mmtimer: cannot reschedule timer\n");
317 t->it.mmtimer.clock = TIMER_OFF;
318 n->next = rb_next(&x->list);
319 rb_erase(&x->list, &n->timer_head);
320 kfree(x);
321 goto restart;
322 }
323
324 e = t->it.mmtimer.expires;
325 next = rb_next(&x->list);
326
327 if (next == NULL)
328 continue;
329
330 e1 = rb_entry(next, struct mmtimer, list)->
331 timer->it.mmtimer.expires;
332 if (e > e1) {
333 n->next = next;
334 rb_erase(&x->list, &n->timer_head);
335 mmtimer_add_list(x);
336 goto restart;
337 }
338 }
339}
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368static long mmtimer_ioctl(struct file *file, unsigned int cmd,
369 unsigned long arg)
370{
371 int ret = 0;
372
373 lock_kernel();
374
375 switch (cmd) {
376 case MMTIMER_GETOFFSET:
377
378
379
380 if(PAGE_SIZE <= (1 << 16))
381 ret = (((long)RTC_COUNTER_ADDR) & (PAGE_SIZE-1)) / 8;
382 else
383 ret = -ENOSYS;
384 break;
385
386 case MMTIMER_GETRES:
387 if(copy_to_user((unsigned long __user *)arg,
388 &mmtimer_femtoperiod, sizeof(unsigned long)))
389 ret = -EFAULT;
390 break;
391
392 case MMTIMER_GETFREQ:
393 if(copy_to_user((unsigned long __user *)arg,
394 &sn_rtc_cycles_per_second,
395 sizeof(unsigned long)))
396 ret = -EFAULT;
397 break;
398
399 case MMTIMER_GETBITS:
400 ret = RTC_BITS;
401 break;
402
403 case MMTIMER_MMAPAVAIL:
404 ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0;
405 break;
406
407 case MMTIMER_GETCOUNTER:
408 if(copy_to_user((unsigned long __user *)arg,
409 RTC_COUNTER_ADDR, sizeof(unsigned long)))
410 ret = -EFAULT;
411 break;
412 default:
413 ret = -ENOTTY;
414 break;
415 }
416 unlock_kernel();
417 return ret;
418}
419
420
421
422
423
424
425
426
427
428static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma)
429{
430 unsigned long mmtimer_addr;
431
432 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
433 return -EINVAL;
434
435 if (vma->vm_flags & VM_WRITE)
436 return -EPERM;
437
438 if (PAGE_SIZE > (1 << 16))
439 return -ENOSYS;
440
441 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
442
443 mmtimer_addr = __pa(RTC_COUNTER_ADDR);
444 mmtimer_addr &= ~(PAGE_SIZE - 1);
445 mmtimer_addr &= 0xfffffffffffffffUL;
446
447 if (remap_pfn_range(vma, vma->vm_start, mmtimer_addr >> PAGE_SHIFT,
448 PAGE_SIZE, vma->vm_page_prot)) {
449 printk(KERN_ERR "remap_pfn_range failed in mmtimer.c\n");
450 return -EAGAIN;
451 }
452
453 return 0;
454}
455
456static struct miscdevice mmtimer_miscdev = {
457 SGI_MMTIMER,
458 MMTIMER_NAME,
459 &mmtimer_fops
460};
461
462static struct timespec sgi_clock_offset;
463static int sgi_clock_period;
464
465
466
467
468
469static struct timespec sgi_clock_offset;
470static int sgi_clock_period;
471
472static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
473{
474 u64 nsec;
475
476 nsec = rtc_time() * sgi_clock_period
477 + sgi_clock_offset.tv_nsec;
478 *tp = ns_to_timespec(nsec);
479 tp->tv_sec += sgi_clock_offset.tv_sec;
480 return 0;
481};
482
483static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
484{
485
486 u64 nsec;
487 u32 rem;
488
489 nsec = rtc_time() * sgi_clock_period;
490
491 sgi_clock_offset.tv_sec = tp->tv_sec - div_u64_rem(nsec, NSEC_PER_SEC, &rem);
492
493 if (rem <= tp->tv_nsec)
494 sgi_clock_offset.tv_nsec = tp->tv_sec - rem;
495 else {
496 sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem;
497 sgi_clock_offset.tv_sec--;
498 }
499 return 0;
500}
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515static irqreturn_t
516mmtimer_interrupt(int irq, void *dev_id)
517{
518 unsigned long expires = 0;
519 int result = IRQ_NONE;
520 unsigned indx = cpu_to_node(smp_processor_id());
521 struct mmtimer *base;
522
523 spin_lock(&timers[indx].lock);
524 base = rb_entry(timers[indx].next, struct mmtimer, list);
525 if (base == NULL) {
526 spin_unlock(&timers[indx].lock);
527 return result;
528 }
529
530 if (base->cpu == smp_processor_id()) {
531 if (base->timer)
532 expires = base->timer->it.mmtimer.expires;
533
534 if ((mmtimer_int_pending(COMPARATOR) > 0) ||
535 (expires && (expires <= rtc_time()))) {
536 mmtimer_clr_int_pending(COMPARATOR);
537 tasklet_schedule(&timers[indx].tasklet);
538 result = IRQ_HANDLED;
539 }
540 }
541 spin_unlock(&timers[indx].lock);
542 return result;
543}
544
545static void mmtimer_tasklet(unsigned long data)
546{
547 int nodeid = data;
548 struct mmtimer_node *mn = &timers[nodeid];
549 struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list);
550 struct k_itimer *t;
551 unsigned long flags;
552
553
554 spin_lock_irqsave(&mn->lock, flags);
555 if (!mn->next)
556 goto out;
557
558 x = rb_entry(mn->next, struct mmtimer, list);
559 t = x->timer;
560
561 if (t->it.mmtimer.clock == TIMER_OFF)
562 goto out;
563
564 t->it_overrun = 0;
565
566 mn->next = rb_next(&x->list);
567 rb_erase(&x->list, &mn->timer_head);
568
569 if (posix_timer_event(t, 0) != 0)
570 t->it_overrun++;
571
572 if(t->it.mmtimer.incr) {
573 t->it.mmtimer.expires += t->it.mmtimer.incr;
574 mmtimer_add_list(x);
575 } else {
576
577 t->it.mmtimer.clock = TIMER_OFF;
578 t->it.mmtimer.expires = 0;
579 kfree(x);
580 }
581
582 mmtimer_set_next_timer(nodeid);
583
584 t->it_overrun_last = t->it_overrun;
585out:
586 spin_unlock_irqrestore(&mn->lock, flags);
587}
588
589static int sgi_timer_create(struct k_itimer *timer)
590{
591
592 timer->it.mmtimer.clock = TIMER_OFF;
593 return 0;
594}
595
596
597
598
599
600
601static int sgi_timer_del(struct k_itimer *timr)
602{
603 cnodeid_t nodeid = timr->it.mmtimer.node;
604 unsigned long irqflags;
605
606 spin_lock_irqsave(&timers[nodeid].lock, irqflags);
607 if (timr->it.mmtimer.clock != TIMER_OFF) {
608 unsigned long expires = timr->it.mmtimer.expires;
609 struct rb_node *n = timers[nodeid].timer_head.rb_node;
610 struct mmtimer *uninitialized_var(t);
611 int r = 0;
612
613 timr->it.mmtimer.clock = TIMER_OFF;
614 timr->it.mmtimer.expires = 0;
615
616 while (n) {
617 t = rb_entry(n, struct mmtimer, list);
618 if (t->timer == timr)
619 break;
620
621 if (expires < t->timer->it.mmtimer.expires)
622 n = n->rb_left;
623 else
624 n = n->rb_right;
625 }
626
627 if (!n) {
628 spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
629 return 0;
630 }
631
632 if (timers[nodeid].next == n) {
633 timers[nodeid].next = rb_next(n);
634 r = 1;
635 }
636
637 rb_erase(n, &timers[nodeid].timer_head);
638 kfree(t);
639
640 if (r) {
641 mmtimer_disable_int(cnodeid_to_nasid(nodeid),
642 COMPARATOR);
643 mmtimer_set_next_timer(nodeid);
644 }
645 }
646 spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
647 return 0;
648}
649
650
651static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
652{
653
654 if (timr->it.mmtimer.clock == TIMER_OFF) {
655 cur_setting->it_interval.tv_nsec = 0;
656 cur_setting->it_interval.tv_sec = 0;
657 cur_setting->it_value.tv_nsec = 0;
658 cur_setting->it_value.tv_sec =0;
659 return;
660 }
661
662 cur_setting->it_interval = ns_to_timespec(timr->it.mmtimer.incr * sgi_clock_period);
663 cur_setting->it_value = ns_to_timespec((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
664}
665
666
667static int sgi_timer_set(struct k_itimer *timr, int flags,
668 struct itimerspec * new_setting,
669 struct itimerspec * old_setting)
670{
671 unsigned long when, period, irqflags;
672 int err = 0;
673 cnodeid_t nodeid;
674 struct mmtimer *base;
675 struct rb_node *n;
676
677 if (old_setting)
678 sgi_timer_get(timr, old_setting);
679
680 sgi_timer_del(timr);
681 when = timespec_to_ns(&new_setting->it_value);
682 period = timespec_to_ns(&new_setting->it_interval);
683
684 if (when == 0)
685
686 return 0;
687
688 base = kmalloc(sizeof(struct mmtimer), GFP_KERNEL);
689 if (base == NULL)
690 return -ENOMEM;
691
692 if (flags & TIMER_ABSTIME) {
693 struct timespec n;
694 unsigned long now;
695
696 getnstimeofday(&n);
697 now = timespec_to_ns(&n);
698 if (when > now)
699 when -= now;
700 else
701
702 when = 0;
703 }
704
705
706
707
708
709
710 when = (when + sgi_clock_period - 1) / sgi_clock_period + rtc_time();
711 period = (period + sgi_clock_period - 1) / sgi_clock_period;
712
713
714
715
716
717
718 preempt_disable();
719
720 nodeid = cpu_to_node(smp_processor_id());
721
722
723 spin_lock_irqsave(&timers[nodeid].lock, irqflags);
724
725 base->timer = timr;
726 base->cpu = smp_processor_id();
727
728 timr->it.mmtimer.clock = TIMER_SET;
729 timr->it.mmtimer.node = nodeid;
730 timr->it.mmtimer.incr = period;
731 timr->it.mmtimer.expires = when;
732
733 n = timers[nodeid].next;
734
735
736 mmtimer_add_list(base);
737
738 if (timers[nodeid].next == n) {
739
740 spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
741 preempt_enable();
742 return err;
743 }
744
745
746 if (n)
747 mmtimer_disable_int(cnodeid_to_nasid(nodeid), COMPARATOR);
748
749 mmtimer_set_next_timer(nodeid);
750
751
752 spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
753
754 preempt_enable();
755
756 return err;
757}
758
759static struct k_clock sgi_clock = {
760 .res = 0,
761 .clock_set = sgi_clock_set,
762 .clock_get = sgi_clock_get,
763 .timer_create = sgi_timer_create,
764 .nsleep = do_posix_clock_nonanosleep,
765 .timer_set = sgi_timer_set,
766 .timer_del = sgi_timer_del,
767 .timer_get = sgi_timer_get
768};
769
770
771
772
773
774
775static int __init mmtimer_init(void)
776{
777 cnodeid_t node, maxn = -1;
778
779 if (!ia64_platform_is("sn2"))
780 return 0;
781
782
783
784
785 if (sn_rtc_cycles_per_second < 100000) {
786 printk(KERN_ERR "%s: unable to determine clock frequency\n",
787 MMTIMER_NAME);
788 goto out1;
789 }
790
791 mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
792 2) / sn_rtc_cycles_per_second;
793
794 if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) {
795 printk(KERN_WARNING "%s: unable to allocate interrupt.",
796 MMTIMER_NAME);
797 goto out1;
798 }
799
800 if (misc_register(&mmtimer_miscdev)) {
801 printk(KERN_ERR "%s: failed to register device\n",
802 MMTIMER_NAME);
803 goto out2;
804 }
805
806
807 for_each_online_node(node) {
808 maxn = node;
809 }
810 maxn++;
811
812
813 timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL);
814 if (timers == NULL) {
815 printk(KERN_ERR "%s: failed to allocate memory for device\n",
816 MMTIMER_NAME);
817 goto out3;
818 }
819
820
821 for_each_online_node(node) {
822 spin_lock_init(&timers[node].lock);
823 tasklet_init(&timers[node].tasklet, mmtimer_tasklet,
824 (unsigned long) node);
825 }
826
827 sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
828 register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
829
830 printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
831 sn_rtc_cycles_per_second/(unsigned long)1E6);
832
833 return 0;
834
835out3:
836 kfree(timers);
837 misc_deregister(&mmtimer_miscdev);
838out2:
839 free_irq(SGI_MMTIMER_VECTOR, NULL);
840out1:
841 return -1;
842}
843
844module_init(mmtimer_init);
845