X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fchar%2Frtc.c;h=66a7385bc34aebb96cbda088b2a0b74f23f31363;hb=43f82216f0bd114599f4a221ae6924f3658a0c9a;hp=aefac4ac0bf5841a6a6d928e578d73e351236066;hpb=b4b9034132c7e1e4474999e688dd7d03b7d97a99;p=linux-2.6-omap-h63xx.git diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index aefac4ac0bf..66a7385bc34 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -35,24 +35,23 @@ * 1.09a Pete Zaitcev: Sun SPARC * 1.09b Jeff Garzik: Modularize, init cleanup * 1.09c Jeff Garzik: SMP cleanup - * 1.10 Paul Barton-Davis: add support for async I/O + * 1.10 Paul Barton-Davis: add support for async I/O * 1.10a Andrea Arcangeli: Alpha updates * 1.10b Andrew Morton: SMP lock fix * 1.10c Cesar Barros: SMP locking fixes and cleanup * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit * 1.10e Maciej W. Rozycki: Handle DECstation's year weirdness. - * 1.11 Takashi Iwai: Kernel access functions + * 1.11 Takashi Iwai: Kernel access functions * rtc_register/rtc_unregister/rtc_control * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer * CONFIG_HPET_EMULATE_RTC + * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. * 1.12ac Alan Cox: Allow read access to the day of week register */ #define RTC_VERSION "1.12ac" -#define RTC_IO_EXTENT 0x8 - /* * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with * interrupts disabled. Due to the index-port/data-port (0x70/0x71) @@ -114,9 +113,9 @@ static int rtc_has_irq = 1; #define hpet_set_rtc_irq_bit(arg) 0 #define hpet_rtc_timer_init() do { } while (0) #define hpet_rtc_dropped_irq() 0 -static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {return 0;} +static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;} #else -extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); #endif /* @@ -210,11 +209,12 @@ static const unsigned char days_in_mo[] = */ static inline unsigned char rtc_is_updating(void) { + unsigned long flags; unsigned char uip; - spin_lock_irq(&rtc_lock); + spin_lock_irqsave(&rtc_lock, flags); uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); - spin_unlock_irq(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); return uip; } @@ -229,7 +229,7 @@ static inline unsigned char rtc_is_updating(void) * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) */ -irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t rtc_interrupt(int irq, void *dev_id) { /* * Can be an alarm interrupt, update complete interrupt, @@ -337,7 +337,15 @@ static ssize_t rtc_read(struct file *file, char __user *buf, if (rtc_has_irq == 0) return -EIO; - if (count < sizeof(unsigned)) + /* + * Historically this function used to assume that sizeof(unsigned long) + * is the same in userspace and kernelspace. This lead to problems + * for configurations with multiple ABIs such a the MIPS o32 and 64 + * ABIs supported on the same kernel. So now we support read of both + * 4 and 8 bytes and assume that's the sizeof(unsigned long) in the + * userspace ABI. + */ + if (count != sizeof(unsigned int) && count != sizeof(unsigned long)) return -EINVAL; add_wait_queue(&rtc_wait, &wait); @@ -368,10 +376,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf, schedule(); } while (1); - if (count < sizeof(unsigned long)) - retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); + if (count == sizeof(unsigned int)) + retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); else retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); + if (!retval) + retval = count; out: current->state = TASK_RUNNING; remove_wait_queue(&rtc_wait, &wait); @@ -877,7 +887,7 @@ int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) * The various file operations we support. */ -static struct file_operations rtc_fops = { +static const struct file_operations rtc_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = rtc_read, @@ -896,7 +906,7 @@ static struct miscdevice rtc_dev = { .fops = &rtc_fops, }; -static struct file_operations rtc_proc_fops = { +static const struct file_operations rtc_proc_fops = { .owner = THIS_MODULE, .open = rtc_proc_open, .read = seq_read, @@ -905,7 +915,7 @@ static struct file_operations rtc_proc_fops = { }; #if defined(RTC_IRQ) && !defined(__sparc__) -static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs); +static irq_handler_t rtc_int_handler_ptr; #endif static int __init rtc_init(void) @@ -923,6 +933,9 @@ static int __init rtc_init(void) struct sparc_isa_device *isa_dev; #endif #endif +#ifndef __sparc__ + void *r; +#endif #ifdef __sparc__ for_each_ebus(ebus) { @@ -964,8 +977,13 @@ found: } no_irq: #else - if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) { - printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0)); + if (RTC_IOMAPPED) + r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); + else + r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); + if (!r) { + printk(KERN_ERR "rtc: I/O resource %lx is not free.\n", + (long)(RTC_PORT(0))); return -EIO; } @@ -979,7 +997,10 @@ no_irq: if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); - release_region(RTC_PORT(0), RTC_IO_EXTENT); + if (RTC_IOMAPPED) + release_region(RTC_PORT(0), RTC_IO_EXTENT); + else + release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); return -EIO; } hpet_rtc_timer_init(); @@ -1079,7 +1100,10 @@ static void __exit rtc_exit (void) if (rtc_has_irq) free_irq (rtc_irq, &rtc_port); #else - release_region (RTC_PORT (0), RTC_IO_EXTENT); + if (RTC_IOMAPPED) + release_region(RTC_PORT(0), RTC_IO_EXTENT); + else + release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); #ifdef RTC_IRQ if (rtc_has_irq) free_irq (RTC_IRQ, NULL); @@ -1222,7 +1246,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) void rtc_get_rtc_time(struct rtc_time *rtc_tm) { - unsigned long uip_watchdog = jiffies; + unsigned long uip_watchdog = jiffies, flags; unsigned char ctrl; #ifdef CONFIG_MACH_DECSTATION unsigned int real_year; @@ -1238,10 +1262,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * Once the read clears, read the RTC time (again via ioctl). Easy. */ - while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) { - barrier(); + while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) cpu_relax(); - } /* * Only the values that we read from the RTC are set. We leave @@ -1249,7 +1271,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is * only updated by the RTC when initially set to a non-zero value. */ - spin_lock_irq(&rtc_lock); + spin_lock_irqsave(&rtc_lock, flags); rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); @@ -1263,7 +1285,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) real_year = CMOS_READ(RTC_DEC_YEAR); #endif ctrl = CMOS_READ(RTC_CONTROL); - spin_unlock_irq(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {