Merge branch 'release-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/ak...
[pandora-kernel.git] / drivers / char / mmtimer.c
index d83db5d..918711a 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/miscdevice.h>
 #include <linux/posix-timers.h>
 #include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/sn/addrs.h>
@@ -55,8 +58,8 @@ extern unsigned long sn_rtc_cycles_per_second;
 
 #define rtc_time()              (*RTC_COUNTER_ADDR)
 
-static int mmtimer_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, unsigned long arg);
+static long mmtimer_ioctl(struct file *file, unsigned int cmd,
+                                               unsigned long arg);
 static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
 
 /*
@@ -65,9 +68,9 @@ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
 static unsigned long mmtimer_femtoperiod = 0;
 
 static const struct file_operations mmtimer_fops = {
-       .owner =        THIS_MODULE,
-       .mmap =         mmtimer_mmap,
-       .ioctl =        mmtimer_ioctl,
+       .owner = THIS_MODULE,
+       .mmap = mmtimer_mmap,
+       .unlocked_ioctl = mmtimer_ioctl,
 };
 
 /*
@@ -337,7 +340,6 @@ restart:
 
 /**
  * mmtimer_ioctl - ioctl interface for /dev/mmtimer
- * @inode: inode of the device
  * @file: file structure for the device
  * @cmd: command to execute
  * @arg: optional argument to command
@@ -363,11 +365,13 @@ restart:
  * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
  * in the address specified by @arg.
  */
-static int mmtimer_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, unsigned long arg)
+static long mmtimer_ioctl(struct file *file, unsigned int cmd,
+                                               unsigned long arg)
 {
        int ret = 0;
 
+       lock_kernel();
+
        switch (cmd) {
        case MMTIMER_GETOFFSET: /* offset of the counter */
                /*
@@ -382,15 +386,14 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file,
        case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
                if(copy_to_user((unsigned long __user *)arg,
                                &mmtimer_femtoperiod, sizeof(unsigned long)))
-                       return -EFAULT;
+                       ret = -EFAULT;
                break;
 
        case MMTIMER_GETFREQ: /* frequency in Hz */
                if(copy_to_user((unsigned long __user *)arg,
                                &sn_rtc_cycles_per_second,
                                sizeof(unsigned long)))
-                       return -EFAULT;
-               ret = 0;
+                       ret = -EFAULT;
                break;
 
        case MMTIMER_GETBITS: /* number of bits in the clock */
@@ -404,13 +407,13 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file,
        case MMTIMER_GETCOUNTER:
                if(copy_to_user((unsigned long __user *)arg,
                                RTC_COUNTER_ADDR, sizeof(unsigned long)))
-                       return -EFAULT;
+                       ret = -EFAULT;
                break;
        default:
-               ret = -ENOSYS;
+               ret = -ENOTTY;
                break;
        }
-
+       unlock_kernel();
        return ret;
 }
 
@@ -472,8 +475,8 @@ static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
 
        nsec = rtc_time() * sgi_clock_period
                        + sgi_clock_offset.tv_nsec;
-       tp->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tp->tv_nsec)
-                       + sgi_clock_offset.tv_sec;
+       *tp = ns_to_timespec(nsec);
+       tp->tv_sec += sgi_clock_offset.tv_sec;
        return 0;
 };
 
@@ -481,11 +484,11 @@ static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
 {
 
        u64 nsec;
-       u64 rem;
+       u32 rem;
 
        nsec = rtc_time() * sgi_clock_period;
 
-       sgi_clock_offset.tv_sec = tp->tv_sec - div_long_long_rem(nsec, NSEC_PER_SEC, &rem);
+       sgi_clock_offset.tv_sec = tp->tv_sec - div_u64_rem(nsec, NSEC_PER_SEC, &rem);
 
        if (rem <= tp->tv_nsec)
                sgi_clock_offset.tv_nsec = tp->tv_sec - rem;
@@ -644,9 +647,6 @@ static int sgi_timer_del(struct k_itimer *timr)
        return 0;
 }
 
-#define timespec_to_ns(x) ((x).tv_nsec + (x).tv_sec * NSEC_PER_SEC)
-#define ns_to_timespec(ts, nsec) (ts).tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &(ts).tv_nsec)
-
 /* Assumption: it_lock is already held with irq's disabled */
 static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 {
@@ -659,9 +659,8 @@ static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
                return;
        }
 
-       ns_to_timespec(cur_setting->it_interval, timr->it.mmtimer.incr * sgi_clock_period);
-       ns_to_timespec(cur_setting->it_value, (timr->it.mmtimer.expires - rtc_time())* sgi_clock_period);
-       return;
+       cur_setting->it_interval = ns_to_timespec(timr->it.mmtimer.incr * sgi_clock_period);
+       cur_setting->it_value = ns_to_timespec((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
 }
 
 
@@ -679,8 +678,8 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
                sgi_timer_get(timr, old_setting);
 
        sgi_timer_del(timr);
-       when = timespec_to_ns(new_setting->it_value);
-       period = timespec_to_ns(new_setting->it_interval);
+       when = timespec_to_ns(&new_setting->it_value);
+       period = timespec_to_ns(&new_setting->it_interval);
 
        if (when == 0)
                /* Clear timer */
@@ -695,7 +694,7 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
                unsigned long now;
 
                getnstimeofday(&n);
-               now = timespec_to_ns(n);
+               now = timespec_to_ns(&n);
                if (when > now)
                        when -= now;
                else