diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-08-30 18:30:38 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-08-30 18:30:38 -0400 |
commit | 0a7d5f8ce960e74fa22986bda4af488539796e49 (patch) | |
tree | e29ad17808a5c3410518e22dae8dfe94801b59f3 /drivers/char/rtc.c | |
parent | 0165508c80a2b5d5268d9c5dfa9b30c534a33693 (diff) | |
parent | dc709bd190c130b299ac19d596594256265c042a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/char/rtc.c')
-rw-r--r-- | drivers/char/rtc.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index cc7bd1a3095b..6e6a7c7a7eff 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -46,13 +46,12 @@ | |||
46 | * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init | 46 | * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init |
47 | * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer | 47 | * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer |
48 | * CONFIG_HPET_EMULATE_RTC | 48 | * CONFIG_HPET_EMULATE_RTC |
49 | * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. | ||
49 | * 1.12ac Alan Cox: Allow read access to the day of week register | 50 | * 1.12ac Alan Cox: Allow read access to the day of week register |
50 | */ | 51 | */ |
51 | 52 | ||
52 | #define RTC_VERSION "1.12ac" | 53 | #define RTC_VERSION "1.12ac" |
53 | 54 | ||
54 | #define RTC_IO_EXTENT 0x8 | ||
55 | |||
56 | /* | 55 | /* |
57 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with | 56 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with |
58 | * interrupts disabled. Due to the index-port/data-port (0x70/0x71) | 57 | * interrupts disabled. Due to the index-port/data-port (0x70/0x71) |
@@ -337,7 +336,15 @@ static ssize_t rtc_read(struct file *file, char __user *buf, | |||
337 | if (rtc_has_irq == 0) | 336 | if (rtc_has_irq == 0) |
338 | return -EIO; | 337 | return -EIO; |
339 | 338 | ||
340 | if (count < sizeof(unsigned)) | 339 | /* |
340 | * Historically this function used to assume that sizeof(unsigned long) | ||
341 | * is the same in userspace and kernelspace. This lead to problems | ||
342 | * for configurations with multiple ABIs such a the MIPS o32 and 64 | ||
343 | * ABIs supported on the same kernel. So now we support read of both | ||
344 | * 4 and 8 bytes and assume that's the sizeof(unsigned long) in the | ||
345 | * userspace ABI. | ||
346 | */ | ||
347 | if (count != sizeof(unsigned int) && count != sizeof(unsigned long)) | ||
341 | return -EINVAL; | 348 | return -EINVAL; |
342 | 349 | ||
343 | add_wait_queue(&rtc_wait, &wait); | 350 | add_wait_queue(&rtc_wait, &wait); |
@@ -368,10 +375,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf, | |||
368 | schedule(); | 375 | schedule(); |
369 | } while (1); | 376 | } while (1); |
370 | 377 | ||
371 | if (count < sizeof(unsigned long)) | 378 | if (count == sizeof(unsigned int)) |
372 | retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); | 379 | retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); |
373 | else | 380 | else |
374 | retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); | 381 | retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); |
382 | if (!retval) | ||
383 | retval = count; | ||
375 | out: | 384 | out: |
376 | current->state = TASK_RUNNING; | 385 | current->state = TASK_RUNNING; |
377 | remove_wait_queue(&rtc_wait, &wait); | 386 | remove_wait_queue(&rtc_wait, &wait); |
@@ -923,6 +932,9 @@ static int __init rtc_init(void) | |||
923 | struct sparc_isa_device *isa_dev; | 932 | struct sparc_isa_device *isa_dev; |
924 | #endif | 933 | #endif |
925 | #endif | 934 | #endif |
935 | #ifndef __sparc__ | ||
936 | void *r; | ||
937 | #endif | ||
926 | 938 | ||
927 | #ifdef __sparc__ | 939 | #ifdef __sparc__ |
928 | for_each_ebus(ebus) { | 940 | for_each_ebus(ebus) { |
@@ -964,8 +976,13 @@ found: | |||
964 | } | 976 | } |
965 | no_irq: | 977 | no_irq: |
966 | #else | 978 | #else |
967 | if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) { | 979 | if (RTC_IOMAPPED) |
968 | printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0)); | 980 | r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); |
981 | else | ||
982 | r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); | ||
983 | if (!r) { | ||
984 | printk(KERN_ERR "rtc: I/O resource %lx is not free.\n", | ||
985 | (long)(RTC_PORT(0))); | ||
969 | return -EIO; | 986 | return -EIO; |
970 | } | 987 | } |
971 | 988 | ||
@@ -979,7 +996,10 @@ no_irq: | |||
979 | if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { | 996 | if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { |
980 | /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ | 997 | /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ |
981 | printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); | 998 | printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); |
982 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | 999 | if (RTC_IOMAPPED) |
1000 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
1001 | else | ||
1002 | release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
983 | return -EIO; | 1003 | return -EIO; |
984 | } | 1004 | } |
985 | hpet_rtc_timer_init(); | 1005 | hpet_rtc_timer_init(); |
@@ -1079,7 +1099,10 @@ static void __exit rtc_exit (void) | |||
1079 | if (rtc_has_irq) | 1099 | if (rtc_has_irq) |
1080 | free_irq (rtc_irq, &rtc_port); | 1100 | free_irq (rtc_irq, &rtc_port); |
1081 | #else | 1101 | #else |
1082 | release_region (RTC_PORT (0), RTC_IO_EXTENT); | 1102 | if (RTC_IOMAPPED) |
1103 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
1104 | else | ||
1105 | release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
1083 | #ifdef RTC_IRQ | 1106 | #ifdef RTC_IRQ |
1084 | if (rtc_has_irq) | 1107 | if (rtc_has_irq) |
1085 | free_irq (RTC_IRQ, NULL); | 1108 | free_irq (RTC_IRQ, NULL); |
@@ -1222,7 +1245,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) | |||
1222 | 1245 | ||
1223 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) | 1246 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) |
1224 | { | 1247 | { |
1225 | unsigned long uip_watchdog = jiffies; | 1248 | unsigned long uip_watchdog = jiffies, flags; |
1226 | unsigned char ctrl; | 1249 | unsigned char ctrl; |
1227 | #ifdef CONFIG_MACH_DECSTATION | 1250 | #ifdef CONFIG_MACH_DECSTATION |
1228 | unsigned int real_year; | 1251 | unsigned int real_year; |
@@ -1249,7 +1272,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) | |||
1249 | * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is | 1272 | * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is |
1250 | * only updated by the RTC when initially set to a non-zero value. | 1273 | * only updated by the RTC when initially set to a non-zero value. |
1251 | */ | 1274 | */ |
1252 | spin_lock_irq(&rtc_lock); | 1275 | spin_lock_irqsave(&rtc_lock, flags); |
1253 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | 1276 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); |
1254 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | 1277 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); |
1255 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); | 1278 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); |
@@ -1263,7 +1286,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) | |||
1263 | real_year = CMOS_READ(RTC_DEC_YEAR); | 1286 | real_year = CMOS_READ(RTC_DEC_YEAR); |
1264 | #endif | 1287 | #endif |
1265 | ctrl = CMOS_READ(RTC_CONTROL); | 1288 | ctrl = CMOS_READ(RTC_CONTROL); |
1266 | spin_unlock_irq(&rtc_lock); | 1289 | spin_unlock_irqrestore(&rtc_lock, flags); |
1267 | 1290 | ||
1268 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 1291 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
1269 | { | 1292 | { |