aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/mmtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/mmtimer.c')
-rw-r--r--drivers/char/mmtimer.c98
1 files changed, 56 insertions, 42 deletions
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index ea7c99fa978f..33dc2298af73 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,7 +32,7 @@
32#include <linux/interrupt.h> 32#include <linux/interrupt.h>
33#include <linux/time.h> 33#include <linux/time.h>
34#include <linux/math64.h> 34#include <linux/math64.h>
35#include <linux/smp_lock.h> 35#include <linux/mutex.h>
36#include <linux/slab.h> 36#include <linux/slab.h>
37 37
38#include <asm/uaccess.h> 38#include <asm/uaccess.h>
@@ -53,12 +53,15 @@ MODULE_LICENSE("GPL");
53 53
54#define RTC_BITS 55 /* 55 bits for this implementation */ 54#define RTC_BITS 55 /* 55 bits for this implementation */
55 55
56static struct k_clock sgi_clock;
57
56extern unsigned long sn_rtc_cycles_per_second; 58extern unsigned long sn_rtc_cycles_per_second;
57 59
58#define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC)) 60#define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC))
59 61
60#define rtc_time() (*RTC_COUNTER_ADDR) 62#define rtc_time() (*RTC_COUNTER_ADDR)
61 63
64static DEFINE_MUTEX(mmtimer_mutex);
62static long mmtimer_ioctl(struct file *file, unsigned int cmd, 65static long mmtimer_ioctl(struct file *file, unsigned int cmd,
63 unsigned long arg); 66 unsigned long arg);
64static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); 67static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
@@ -72,6 +75,7 @@ static const struct file_operations mmtimer_fops = {
72 .owner = THIS_MODULE, 75 .owner = THIS_MODULE,
73 .mmap = mmtimer_mmap, 76 .mmap = mmtimer_mmap,
74 .unlocked_ioctl = mmtimer_ioctl, 77 .unlocked_ioctl = mmtimer_ioctl,
78 .llseek = noop_llseek,
75}; 79};
76 80
77/* 81/*
@@ -174,9 +178,9 @@ static void mmtimer_setup_int_2(int cpu, u64 expires)
174 * in order to insure that the setup succeeds in a deterministic time frame. 178 * in order to insure that the setup succeeds in a deterministic time frame.
175 * It will check if the interrupt setup succeeded. 179 * It will check if the interrupt setup succeeded.
176 */ 180 */
177static int mmtimer_setup(int cpu, int comparator, unsigned long expires) 181static int mmtimer_setup(int cpu, int comparator, unsigned long expires,
182 u64 *set_completion_time)
178{ 183{
179
180 switch (comparator) { 184 switch (comparator) {
181 case 0: 185 case 0:
182 mmtimer_setup_int_0(cpu, expires); 186 mmtimer_setup_int_0(cpu, expires);
@@ -189,7 +193,8 @@ static int mmtimer_setup(int cpu, int comparator, unsigned long expires)
189 break; 193 break;
190 } 194 }
191 /* We might've missed our expiration time */ 195 /* We might've missed our expiration time */
192 if (rtc_time() <= expires) 196 *set_completion_time = rtc_time();
197 if (*set_completion_time <= expires)
193 return 1; 198 return 1;
194 199
195 /* 200 /*
@@ -225,6 +230,8 @@ static int mmtimer_disable_int(long nasid, int comparator)
225#define TIMER_OFF 0xbadcabLL /* Timer is not setup */ 230#define TIMER_OFF 0xbadcabLL /* Timer is not setup */
226#define TIMER_SET 0 /* Comparator is set for this timer */ 231#define TIMER_SET 0 /* Comparator is set for this timer */
227 232
233#define MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT 40
234
228/* There is one of these for each timer */ 235/* There is one of these for each timer */
229struct mmtimer { 236struct mmtimer {
230 struct rb_node list; 237 struct rb_node list;
@@ -240,6 +247,11 @@ struct mmtimer_node {
240}; 247};
241static struct mmtimer_node *timers; 248static struct mmtimer_node *timers;
242 249
250static unsigned mmtimer_interval_retry_increment =
251 MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT;
252module_param(mmtimer_interval_retry_increment, uint, 0644);
253MODULE_PARM_DESC(mmtimer_interval_retry_increment,
254 "RTC ticks to add to expiration on interval retry (default 40)");
243 255
244/* 256/*
245 * Add a new mmtimer struct to the node's mmtimer list. 257 * Add a new mmtimer struct to the node's mmtimer list.
@@ -287,7 +299,8 @@ static void mmtimer_set_next_timer(int nodeid)
287 struct mmtimer_node *n = &timers[nodeid]; 299 struct mmtimer_node *n = &timers[nodeid];
288 struct mmtimer *x; 300 struct mmtimer *x;
289 struct k_itimer *t; 301 struct k_itimer *t;
290 int o; 302 u64 expires, exp, set_completion_time;
303 int i;
291 304
292restart: 305restart:
293 if (n->next == NULL) 306 if (n->next == NULL)
@@ -298,7 +311,8 @@ restart:
298 if (!t->it.mmtimer.incr) { 311 if (!t->it.mmtimer.incr) {
299 /* Not an interval timer */ 312 /* Not an interval timer */
300 if (!mmtimer_setup(x->cpu, COMPARATOR, 313 if (!mmtimer_setup(x->cpu, COMPARATOR,
301 t->it.mmtimer.expires)) { 314 t->it.mmtimer.expires,
315 &set_completion_time)) {
302 /* Late setup, fire now */ 316 /* Late setup, fire now */
303 tasklet_schedule(&n->tasklet); 317 tasklet_schedule(&n->tasklet);
304 } 318 }
@@ -306,14 +320,23 @@ restart:
306 } 320 }
307 321
308 /* Interval timer */ 322 /* Interval timer */
309 o = 0; 323 i = 0;
310 while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) { 324 expires = exp = t->it.mmtimer.expires;
311 unsigned long e, e1; 325 while (!mmtimer_setup(x->cpu, COMPARATOR, expires,
312 struct rb_node *next; 326 &set_completion_time)) {
313 t->it.mmtimer.expires += t->it.mmtimer.incr << o; 327 int to;
314 t->it_overrun += 1 << o; 328
315 o++; 329 i++;
316 if (o > 20) { 330 expires = set_completion_time +
331 mmtimer_interval_retry_increment + (1 << i);
332 /* Calculate overruns as we go. */
333 to = ((u64)(expires - exp) / t->it.mmtimer.incr);
334 if (to) {
335 t->it_overrun += to;
336 t->it.mmtimer.expires += t->it.mmtimer.incr * to;
337 exp = t->it.mmtimer.expires;
338 }
339 if (i > 20) {
317 printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); 340 printk(KERN_ALERT "mmtimer: cannot reschedule timer\n");
318 t->it.mmtimer.clock = TIMER_OFF; 341 t->it.mmtimer.clock = TIMER_OFF;
319 n->next = rb_next(&x->list); 342 n->next = rb_next(&x->list);
@@ -321,21 +344,6 @@ restart:
321 kfree(x); 344 kfree(x);
322 goto restart; 345 goto restart;
323 } 346 }
324
325 e = t->it.mmtimer.expires;
326 next = rb_next(&x->list);
327
328 if (next == NULL)
329 continue;
330
331 e1 = rb_entry(next, struct mmtimer, list)->
332 timer->it.mmtimer.expires;
333 if (e > e1) {
334 n->next = next;
335 rb_erase(&x->list, &n->timer_head);
336 mmtimer_add_list(x);
337 goto restart;
338 }
339 } 347 }
340} 348}
341 349
@@ -371,7 +379,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
371{ 379{
372 int ret = 0; 380 int ret = 0;
373 381
374 lock_kernel(); 382 mutex_lock(&mmtimer_mutex);
375 383
376 switch (cmd) { 384 switch (cmd) {
377 case MMTIMER_GETOFFSET: /* offset of the counter */ 385 case MMTIMER_GETOFFSET: /* offset of the counter */
@@ -414,7 +422,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
414 ret = -ENOTTY; 422 ret = -ENOTTY;
415 break; 423 break;
416 } 424 }
417 unlock_kernel(); 425 mutex_unlock(&mmtimer_mutex);
418 return ret; 426 return ret;
419} 427}
420 428
@@ -481,7 +489,7 @@ static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
481 return 0; 489 return 0;
482}; 490};
483 491
484static int sgi_clock_set(clockid_t clockid, struct timespec *tp) 492static int sgi_clock_set(const clockid_t clockid, const struct timespec *tp)
485{ 493{
486 494
487 u64 nsec; 495 u64 nsec;
@@ -757,15 +765,21 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
757 return err; 765 return err;
758} 766}
759 767
768static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp)
769{
770 tp->tv_sec = 0;
771 tp->tv_nsec = sgi_clock_period;
772 return 0;
773}
774
760static struct k_clock sgi_clock = { 775static struct k_clock sgi_clock = {
761 .res = 0, 776 .clock_set = sgi_clock_set,
762 .clock_set = sgi_clock_set, 777 .clock_get = sgi_clock_get,
763 .clock_get = sgi_clock_get, 778 .clock_getres = sgi_clock_getres,
764 .timer_create = sgi_timer_create, 779 .timer_create = sgi_timer_create,
765 .nsleep = do_posix_clock_nonanosleep, 780 .timer_set = sgi_timer_set,
766 .timer_set = sgi_timer_set, 781 .timer_del = sgi_timer_del,
767 .timer_del = sgi_timer_del, 782 .timer_get = sgi_timer_get
768 .timer_get = sgi_timer_get
769}; 783};
770 784
771/** 785/**
@@ -825,8 +839,8 @@ static int __init mmtimer_init(void)
825 (unsigned long) node); 839 (unsigned long) node);
826 } 840 }
827 841
828 sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second; 842 sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second;
829 register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); 843 posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock);
830 844
831 printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, 845 printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
832 sn_rtc_cycles_per_second/(unsigned long)1E6); 846 sn_rtc_cycles_per_second/(unsigned long)1E6);