[VLAN]: Clean up initialization code
[safe/jmp/linux-2.6] / drivers / char / rtc.c
index ab6429b..0c66b80 100644 (file)
  *     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
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#if defined(__i386__)
+#ifdef CONFIG_X86
 #include <asm/hpet.h>
 #endif
 
-#ifdef __sparc__
+#ifdef CONFIG_SPARC32
 #include <linux/pci.h>
 #include <asm/ebus.h>
-#ifdef __sparc_v9__
-#include <asm/isa.h>
-#endif
 
 static unsigned long rtc_port;
 static int rtc_irq = PCI_IRQ_NONE;
@@ -113,9 +110,14 @@ 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;}
+#ifdef RTC_IRQ
+static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+{
+       return 0;
+}
+#endif
 #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
 
 /*
@@ -130,7 +132,9 @@ static struct fasync_struct *rtc_async_queue;
 static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
 
 #ifdef RTC_IRQ
-static struct timer_list rtc_irq_timer;
+static void rtc_dropped_irq(unsigned long data);
+
+static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
 #endif
 
 static ssize_t rtc_read(struct file *file, char __user *buf,
@@ -145,8 +149,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait);
 
 static void get_rtc_alm_time (struct rtc_time *alm_tm);
 #ifdef RTC_IRQ
-static void rtc_dropped_irq(unsigned long data);
-
 static void set_rtc_irq_bit_locked(unsigned char bit);
 static void mask_rtc_irq_bit_locked(unsigned char bit);
 
@@ -165,7 +167,9 @@ static void mask_rtc_irq_bit(unsigned char bit)
 }
 #endif
 
+#ifdef CONFIG_PROC_FS
 static int rtc_proc_open(struct inode *inode, struct file *file);
+#endif
 
 /*
  *     Bits in rtc_status. (6 bits of room for future expansion)
@@ -229,7 +233,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,
@@ -275,7 +279,7 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  */
 static ctl_table rtc_table[] = {
        {
-               .ctl_name       = 1,
+               .ctl_name       = CTL_UNNUMBERED,
                .procname       = "max-user-freq",
                .data           = &rtc_max_user_freq,
                .maxlen         = sizeof(int),
@@ -287,9 +291,8 @@ static ctl_table rtc_table[] = {
 
 static ctl_table rtc_root[] = {
        {
-               .ctl_name       = 1,
+               .ctl_name       = CTL_UNNUMBERED,
                .procname       = "rtc",
-               .maxlen         = 0,
                .mode           = 0555,
                .child          = rtc_table,
        },
@@ -300,7 +303,6 @@ static ctl_table dev_root[] = {
        {
                .ctl_name       = CTL_DEV,
                .procname       = "dev",
-               .maxlen         = 0,
                .mode           = 0555,
                .child          = rtc_root,
        },
@@ -311,7 +313,7 @@ static struct ctl_table_header *sysctl_header;
 
 static int __init init_sysctl(void)
 {
-    sysctl_header = register_sysctl_table(dev_root, 0);
+    sysctl_header = register_sysctl_table(dev_root);
     return 0;
 }
 
@@ -383,7 +385,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
        if (!retval)
                retval = count;
  out:
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&rtc_wait, &wait);
 
        return retval;
@@ -447,8 +449,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
 
                spin_lock_irqsave (&rtc_lock, flags);
                if (!(rtc_status & RTC_TIMER_ON)) {
-                       rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
-                       add_timer(&rtc_irq_timer);
+                       mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq +
+                                       2*HZ/100);
                        rtc_status |= RTC_TIMER_ON;
                }
                set_rtc_irq_bit_locked(RTC_PIE);
@@ -906,6 +908,7 @@ static struct miscdevice rtc_dev = {
        .fops           = &rtc_fops,
 };
 
+#ifdef CONFIG_PROC_FS
 static const struct file_operations rtc_proc_fops = {
        .owner = THIS_MODULE,
        .open = rtc_proc_open,
@@ -913,31 +916,53 @@ static const struct file_operations rtc_proc_fops = {
        .llseek = seq_lseek,
        .release = single_release,
 };
-
-#if defined(RTC_IRQ) && !defined(__sparc__)
-static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 
+static resource_size_t rtc_size;
+
+static struct resource * __init rtc_request_region(resource_size_t size)
+{
+       struct resource *r;
+
+       if (RTC_IOMAPPED)
+               r = request_region(RTC_PORT(0), size, "rtc");
+       else
+               r = request_mem_region(RTC_PORT(0), size, "rtc");
+
+       if (r)
+               rtc_size = size;
+
+       return r;
+}
+
+static void rtc_release_region(void)
+{
+       if (RTC_IOMAPPED)
+               release_region(RTC_PORT(0), rtc_size);
+       else
+               release_mem_region(RTC_PORT(0), rtc_size);
+}
+
 static int __init rtc_init(void)
 {
+#ifdef CONFIG_PROC_FS
        struct proc_dir_entry *ent;
+#endif
 #if defined(__alpha__) || defined(__mips__)
        unsigned int year, ctrl;
        char *guess = NULL;
 #endif
-#ifdef __sparc__
+#ifdef CONFIG_SPARC32
        struct linux_ebus *ebus;
        struct linux_ebus_device *edev;
-#ifdef __sparc_v9__
-       struct sparc_isa_bridge *isa_br;
-       struct sparc_isa_device *isa_dev;
-#endif
-#endif
-#ifndef __sparc__
+#else
        void *r;
+#ifdef RTC_IRQ
+       irq_handler_t rtc_int_handler_ptr;
+#endif
 #endif
 
-#ifdef __sparc__
+#ifdef CONFIG_SPARC32
        for_each_ebus(ebus) {
                for_each_ebusdev(edev, ebus) {
                        if(strcmp(edev->prom_node->name, "rtc") == 0) {
@@ -947,17 +972,7 @@ static int __init rtc_init(void)
                        }
                }
        }
-#ifdef __sparc_v9__
-       for_each_isa(isa_br) {
-               for_each_isadev(isa_dev, isa_br) {
-                       if (strcmp(isa_dev->prom_node->name, "rtc") == 0) {
-                               rtc_port = isa_dev->resource.start;
-                               rtc_irq = isa_dev->irq;
-                               goto found;
-                       }
-               }
-       }
-#endif
+       rtc_has_irq = 0;
        printk(KERN_ERR "rtc_init: no PC rtc found\n");
        return -EIO;
 
@@ -972,16 +987,27 @@ found:
         * PCI Slot 2 INTA# (and some INTx# in Slot 1).
         */
        if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
+               rtc_has_irq = 0;
                printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
                return -EIO;
        }
 no_irq:
 #else
-       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");
+       r = rtc_request_region(RTC_IO_EXTENT);
+
+       /*
+        * If we've already requested a smaller range (for example, because
+        * PNPBIOS or ACPI told us how the device is configured), the request
+        * above might fail because it's too big.
+        *
+        * If so, request just the range we actually use.
+        */
+       if (!r)
+               r = rtc_request_region(RTC_IO_EXTENT_USED);
        if (!r) {
+#ifdef RTC_IRQ
+               rtc_has_irq = 0;
+#endif
                printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
                       (long)(RTC_PORT(0)));
                return -EIO;
@@ -996,37 +1022,33 @@ 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. */
+               rtc_has_irq = 0;
                printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
-               if (RTC_IOMAPPED)
-                       release_region(RTC_PORT(0), RTC_IO_EXTENT);
-               else
-                       release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+               rtc_release_region();
                return -EIO;
        }
        hpet_rtc_timer_init();
 
 #endif
 
-#endif /* __sparc__ vs. others */
+#endif /* CONFIG_SPARC32 vs. others */
 
        if (misc_register(&rtc_dev)) {
 #ifdef RTC_IRQ
                free_irq(RTC_IRQ, NULL);
+               rtc_has_irq = 0;
 #endif
-               release_region(RTC_PORT(0), RTC_IO_EXTENT);
+               rtc_release_region();
                return -ENODEV;
        }
 
+#ifdef CONFIG_PROC_FS
        ent = create_proc_entry("driver/rtc", 0, NULL);
-       if (!ent) {
-#ifdef RTC_IRQ
-               free_irq(RTC_IRQ, NULL);
+       if (ent)
+               ent->proc_fops = &rtc_proc_fops;
+       else
+               printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
 #endif
-               release_region(RTC_PORT(0), RTC_IO_EXTENT);
-               misc_deregister(&rtc_dev);
-               return -ENOMEM;
-       }
-       ent->proc_fops = &rtc_proc_fops;
 
 #if defined(__alpha__) || defined(__mips__)
        rtc_freq = HZ;
@@ -1071,8 +1093,6 @@ no_irq:
        if (rtc_has_irq == 0)
                goto no_irq2;
 
-       init_timer(&rtc_irq_timer);
-       rtc_irq_timer.function = rtc_dropped_irq;
        spin_lock_irq(&rtc_lock);
        rtc_freq = 1024;
        if (!hpet_set_periodic_freq(rtc_freq)) {
@@ -1096,19 +1116,16 @@ static void __exit rtc_exit (void)
        remove_proc_entry ("driver/rtc", NULL);
        misc_deregister(&rtc_dev);
 
-#ifdef __sparc__
+#ifdef CONFIG_SPARC32
        if (rtc_has_irq)
                free_irq (rtc_irq, &rtc_port);
 #else
-       if (RTC_IOMAPPED)
-               release_region(RTC_PORT(0), RTC_IO_EXTENT);
-       else
-               release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+       rtc_release_region();
 #ifdef RTC_IRQ
        if (rtc_has_irq)
                free_irq (RTC_IRQ, NULL);
 #endif
-#endif /* __sparc__ */
+#endif /* CONFIG_SPARC32 */
 }
 
 module_init(rtc_init);
@@ -1150,7 +1167,8 @@ static void rtc_dropped_irq(unsigned long data)
 
        spin_unlock_irq(&rtc_lock);
 
-       printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
+       if (printk_ratelimit())
+               printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
 
        /* Now we have new data */
        wake_up_interruptible(&rtc_wait);
@@ -1159,6 +1177,7 @@ static void rtc_dropped_irq(unsigned long data)
 }
 #endif
 
+#ifdef CONFIG_PROC_FS
 /*
  *     Info exported via "/proc/driver/rtc".
  */
@@ -1243,6 +1262,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
 {
        return single_open(file, rtc_proc_show, NULL);
 }
+#endif
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
@@ -1262,10 +1282,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