linux/drivers/char/mmtimer.c
<<
>>
Prefs
   1/*
   2 * Timer device implementation for SGI SN platforms.
   3 *
   4 * This file is subject to the terms and conditions of the GNU General Public
   5 * License.  See the file "COPYING" in the main directory of this archive
   6 * for more details.
   7 *
   8 * Copyright (c) 2001-2006 Silicon Graphics, Inc.  All rights reserved.
   9 *
  10 * This driver exports an API that should be supportable by any HPET or IA-PC
  11 * multimedia timer.  The code below is currently specific to the SGI Altix
  12 * SHub RTC, however.
  13 *
  14 * 11/01/01 - jbarnes - initial revision
  15 * 9/10/04 - Christoph Lameter - remove interrupt support for kernel inclusion
  16 * 10/1/04 - Christoph Lameter - provide posix clock CLOCK_SGI_CYCLE
  17 * 10/13/04 - Christoph Lameter, Dimitri Sivanich - provide timer interrupt
  18 *              support via the posix timer interface
  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/* name of the device, usually in /dev */
  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 /* 55 bits for this implementation */
  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 * Period in femtoseconds (10^-15 s)
  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 * We only have comparison registers RTC1-4 currently available per
  78 * node.  RTC0 is used by SAL.
  79 */
  80/* Check for an RTC interrupt pending */
  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/* Clear the RTC interrupt pending bit */
  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/* Setup timer on comparator RTC1 */
  98static void mmtimer_setup_int_0(int cpu, u64 expires)
  99{
 100        u64 val;
 101
 102        /* Disable interrupt */
 103        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 0UL);
 104
 105        /* Initialize comparator value */
 106        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), -1L);
 107
 108        /* Clear pending bit */
 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        /* Set configuration */
 116        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_CONFIG), val);
 117
 118        /* Enable RTC interrupts */
 119        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 1UL);
 120
 121        /* Initialize comparator value */
 122        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), expires);
 123
 124
 125}
 126
 127/* Setup timer on comparator RTC2 */
 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/* Setup timer on comparator RTC3 */
 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 * This function must be called with interrupts disabled and preemption off
 173 * in order to insure that the setup succeeds in a deterministic time frame.
 174 * It will check if the interrupt setup succeeded.
 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        /* We might've missed our expiration time */
 191        if (rtc_time() <= expires)
 192                return 1;
 193
 194        /*
 195         * If an interrupt is already pending then its okay
 196         * if not then we failed
 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               /* The comparator to use */
 223
 224#define TIMER_OFF       0xbadcabLL      /* Timer is not setup */
 225#define TIMER_SET       0               /* Comparator is set for this timer */
 226
 227/* There is one of these for each timer */
 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 * Add a new mmtimer struct to the node's mmtimer list.
 245 * This function assumes the struct mmtimer_node is locked.
 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         * Find the right place in the rbtree:
 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         * Insert the timer to the rbtree and check whether it
 270         * replaces the first pending timer
 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 * Set the comparator for the next timer.
 282 * This function assumes the struct mmtimer_node is locked.
 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                /* Not an interval timer */
 299                if (!mmtimer_setup(x->cpu, COMPARATOR,
 300                                        t->it.mmtimer.expires)) {
 301                        /* Late setup, fire now */
 302                        tasklet_schedule(&n->tasklet);
 303                }
 304                return;
 305        }
 306
 307        /* Interval timer */
 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 * mmtimer_ioctl - ioctl interface for /dev/mmtimer
 343 * @file: file structure for the device
 344 * @cmd: command to execute
 345 * @arg: optional argument to command
 346 *
 347 * Executes the command specified by @cmd.  Returns 0 for success, < 0 for
 348 * failure.
 349 *
 350 * Valid commands:
 351 *
 352 * %MMTIMER_GETOFFSET - Should return the offset (relative to the start
 353 * of the page where the registers are mapped) for the counter in question.
 354 *
 355 * %MMTIMER_GETRES - Returns the resolution of the clock in femto (10^-15)
 356 * seconds
 357 *
 358 * %MMTIMER_GETFREQ - Copies the frequency of the clock in Hz to the address
 359 * specified by @arg
 360 *
 361 * %MMTIMER_GETBITS - Returns the number of bits in the clock's counter
 362 *
 363 * %MMTIMER_MMAPAVAIL - Returns 1 if the registers can be mmap'd into userspace
 364 *
 365 * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
 366 * in the address specified by @arg.
 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: /* offset of the counter */
 377                /*
 378                 * SN RTC registers are on their own 64k page
 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: /* resolution of the clock in 10^-15 s */
 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: /* frequency in Hz */
 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: /* number of bits in the clock */
 400                ret = RTC_BITS;
 401                break;
 402
 403        case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */
 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 * mmtimer_mmap - maps the clock's registers into userspace
 422 * @file: file structure for the device
 423 * @vma: VMA to map the registers into
 424 *
 425 * Calls remap_pfn_range() to map the clock's registers into
 426 * the calling process' address space.
 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 * Posix Timer Interface
 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 * mmtimer_interrupt - timer interrupt handler
 504 * @irq: irq received
 505 * @dev_id: device the irq came from
 506 *
 507 * Called when one of the comarators matches the counter, This
 508 * routine will send signals to processes that have requested
 509 * them.
 510 *
 511 * This interrupt is run in an interrupt context
 512 * by the SHUB. It is therefore safe to locally access SHub
 513 * registers.
 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                /* expires test won't work with shared irqs */
 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        /* Send signal and deal with periodic signals */
 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                /* Ensure we don't false trigger in mmtimer_interrupt */
 577                t->it.mmtimer.clock = TIMER_OFF;
 578                t->it.mmtimer.expires = 0;
 579                kfree(x);
 580        }
 581        /* Set comparator for next timer, if there is one */
 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        /* Insure that a newly created timer is off */
 592        timer->it.mmtimer.clock = TIMER_OFF;
 593        return 0;
 594}
 595
 596/* This does not really delete a timer. It just insures
 597 * that the timer is not active
 598 *
 599 * Assumption: it_lock is already held with irq's disabled
 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/* Assumption: it_lock is already held with irq's disabled */
 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                /* Clear timer */
 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                        /* Fire the timer immediately */
 702                        when = 0;
 703        }
 704
 705        /*
 706         * Convert to sgi clock period. Need to keep rtc_time() as near as possible
 707         * to getnstimeofday() in order to be as faithful as possible to the time
 708         * specified.
 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         * We are allocating a local SHub comparator. If we would be moved to another
 715         * cpu then another SHub may be local to us. Prohibit that by switching off
 716         * preemption.
 717         */
 718        preempt_disable();
 719
 720        nodeid =  cpu_to_node(smp_processor_id());
 721
 722        /* Lock the node timer structure */
 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        /* Add the new struct mmtimer to node's timer list */
 736        mmtimer_add_list(base);
 737
 738        if (timers[nodeid].next == n) {
 739                /* No need to reprogram comparator for now */
 740                spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
 741                preempt_enable();
 742                return err;
 743        }
 744
 745        /* We need to reprogram the comparator */
 746        if (n)
 747                mmtimer_disable_int(cnodeid_to_nasid(nodeid), COMPARATOR);
 748
 749        mmtimer_set_next_timer(nodeid);
 750
 751        /* Unlock the node timer structure */
 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 * mmtimer_init - device initialization routine
 772 *
 773 * Does initial setup for the mmtimer device.
 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         * Sanity check the cycles/sec variable
 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        /* Get max numbered node, calculate slots needed */
 807        for_each_online_node(node) {
 808                maxn = node;
 809        }
 810        maxn++;
 811
 812        /* Allocate list of node ptrs to mmtimer_t's */
 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        /* Initialize struct mmtimer's for each online node */
 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