Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / sbus / char / envctrl.c
index cd6e2d3..19e8edd 100644 (file)
  *              Daniele Bellucci <bellucda@tiscali.it>
  */
 
+#define __KERNEL_SYSCALLS__
+static int errno;
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/kthread.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <asm/uaccess.h>
 #include <asm/envctrl.h>
 
-#define __KERNEL_SYSCALLS__
-static int errno;
-#include <asm/unistd.h>
-
 #define ENVCTRL_MINOR  162
 
 #define PCF8584_ADDRESS        0x55
@@ -130,10 +130,8 @@ static int errno;
  */
 #define ENVCTRL_CPCI_IGNORED_NODE              0x70
 
-struct pcf8584_reg {
-        unsigned char data;
-        unsigned char csr;
-};
+#define PCF8584_DATA   0x00
+#define PCF8584_CSR    0x01
 
 /* Each child device can be monitored by up to PCF8584_MAX_CHANNELS.
  * Property of a port or channel as defined by the firmware.
@@ -175,7 +173,7 @@ struct i2c_child_t {
        char mon_type[PCF8584_MAX_CHANNELS];
 };
 
-volatile static struct pcf8584_reg *i2c = NULL;
+static void __iomem *i2c;
 static struct i2c_child_t i2c_childlist[ENVCTRL_MAX_CPU*2];
 static unsigned char chnls_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
 static unsigned int warning_temperature = 0;
@@ -185,22 +183,6 @@ static char read_cpu;
 /* Forward declarations. */
 static struct i2c_child_t *envctrl_get_i2c_child(unsigned char);
 
-/* Function description: Read a byte from an i2c controller register.
- * Return: A byte from the passed in address.
- */
-static inline unsigned char envctrl_readb(volatile unsigned char *p)
-{
-       return readb(p);
-}
-
-/* Function description: Write a byte to an i2c controller register.
- * Return: Nothing.
- */
-static inline void envctrl_writeb(unsigned char val, volatile unsigned char *p)
-{
-       writeb(val, p);
-}
-
 /* Function Description: Test the PIN bit (Pending Interrupt Not) 
  *                      to test when serial transmission is completed .
  * Return : None.
@@ -210,7 +192,7 @@ static void envtrl_i2c_test_pin(void)
        int limit = 1000000;
 
        while (--limit > 0) {
-               if (!(envctrl_readb(&i2c->csr) & STATUS_PIN)) 
+               if (!(readb(i2c + PCF8584_CSR) & STATUS_PIN)) 
                        break;
                udelay(1);
        } 
@@ -228,7 +210,7 @@ static void envctrl_i2c_test_bb(void)
 
        while (--limit > 0) {
                /* Busy bit 0 means busy. */
-               if (envctrl_readb(&i2c->csr) & STATUS_BB)
+               if (readb(i2c + PCF8584_CSR) & STATUS_BB)
                        break;
                udelay(1);
        } 
@@ -245,20 +227,20 @@ static int envctrl_i2c_read_addr(unsigned char addr)
        envctrl_i2c_test_bb();
 
        /* Load address. */
-       envctrl_writeb(addr + 1, &i2c->data);
+       writeb(addr + 1, i2c + PCF8584_DATA);
 
        envctrl_i2c_test_bb();
 
-       envctrl_writeb(OBD_SEND_START, &i2c->csr);
+       writeb(OBD_SEND_START, i2c + PCF8584_CSR);
 
        /* Wait for PIN. */
        envtrl_i2c_test_pin();
 
        /* CSR 0 means acknowledged. */
-       if (!(envctrl_readb(&i2c->csr) & STATUS_LRB)) {
-               return envctrl_readb(&i2c->data);
+       if (!(readb(i2c + PCF8584_CSR) & STATUS_LRB)) {
+               return readb(i2c + PCF8584_DATA);
        } else {
-               envctrl_writeb(OBD_SEND_STOP, &i2c->csr);
+               writeb(OBD_SEND_STOP, i2c + PCF8584_CSR);
                return 0;
        }
 }
@@ -269,10 +251,10 @@ static int envctrl_i2c_read_addr(unsigned char addr)
 static void envctrl_i2c_write_addr(unsigned char addr)
 {
        envctrl_i2c_test_bb();
-       envctrl_writeb(addr, &i2c->data);
+       writeb(addr, i2c + PCF8584_DATA);
 
        /* Generate Start condition. */
-       envctrl_writeb(OBD_SEND_START, &i2c->csr);
+       writeb(OBD_SEND_START, i2c + PCF8584_CSR);
 }
 
 /* Function Description: Read 1 byte of data from addr 
@@ -282,8 +264,8 @@ static void envctrl_i2c_write_addr(unsigned char addr)
 static unsigned char envctrl_i2c_read_data(void)
 {
        envtrl_i2c_test_pin();
-       envctrl_writeb(CONTROL_ES0, &i2c->csr);  /* Send neg ack. */
-       return envctrl_readb(&i2c->data);
+       writeb(CONTROL_ES0, i2c + PCF8584_CSR);  /* Send neg ack. */
+       return readb(i2c + PCF8584_DATA);
 }
 
 /* Function Description: Instruct the device which port to read data from.  
@@ -292,7 +274,7 @@ static unsigned char envctrl_i2c_read_data(void)
 static void envctrl_i2c_write_data(unsigned char port)
 {
        envtrl_i2c_test_pin();
-       envctrl_writeb(port, &i2c->data);
+       writeb(port, i2c + PCF8584_DATA);
 }
 
 /* Function Description: Generate Stop condition after last byte is sent.
@@ -301,7 +283,7 @@ static void envctrl_i2c_write_data(unsigned char port)
 static void envctrl_i2c_stop(void)
 {
        envtrl_i2c_test_pin();
-       envctrl_writeb(OBD_SEND_STOP, &i2c->csr);
+       writeb(OBD_SEND_STOP, i2c + PCF8584_CSR);
 }
 
 /* Function Description: Read adc device.
@@ -323,7 +305,7 @@ static unsigned char envctrl_i2c_read_8591(unsigned char addr, unsigned char por
        envctrl_i2c_read_data();
        envctrl_i2c_stop();
 
-       return envctrl_readb(&i2c->data);
+       return readb(i2c + PCF8584_DATA);
 }
 
 /* Function Description: Read gpio device.
@@ -672,9 +654,8 @@ envctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 /* Function Description: Command what to read.  Mapped to user ioctl().
  * Return: Gives 0 for implemented commands, -EINVAL otherwise.
  */
-static int
-envctrl_ioctl(struct inode *inode, struct file *file,
-             unsigned int cmd, unsigned long arg)
+static long
+envctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        char __user *infobuf;
 
@@ -733,11 +714,14 @@ envctrl_release(struct inode *inode, struct file *file)
 }
 
 static struct file_operations envctrl_fops = {
-       .owner =        THIS_MODULE,
-       .read =         envctrl_read,
-       .ioctl =        envctrl_ioctl,
-       .open =         envctrl_open,
-       .release =      envctrl_release,
+       .owner =                THIS_MODULE,
+       .read =                 envctrl_read,
+       .unlocked_ioctl =       envctrl_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl =         envctrl_ioctl,
+#endif
+       .open =                 envctrl_open,
+       .release =              envctrl_release,
 };     
 
 static struct miscdevice envctrl_dev = {
@@ -1025,21 +1009,15 @@ static int kenvctrld(void *__unused)
                return -ENODEV;
        }
 
-       poll_interval = 5 * HZ; /* TODO env_mon_interval */
-
-       daemonize("kenvctrld");
-       allow_signal(SIGKILL);
-
-       kenvctrld_task = current;
+       poll_interval = 5000; /* TODO env_mon_interval */
 
        printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
        for (;;) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(poll_interval);
+               msleep_interruptible(poll_interval);
 
-               if(signal_pending(current))
+               if (kthread_should_stop())
                        break;
-
+               
                for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) {
                        if (0 < envctrl_read_cpu_info(whichcpu, cputemp,
                                                      ENVCTRL_CPUTEMP_MON,
@@ -1061,7 +1039,6 @@ static int kenvctrld(void *__unused)
 
 static int __init envctrl_init(void)
 {
-#ifdef CONFIG_PCI
        struct linux_ebus *ebus = NULL;
        struct linux_ebus_device *edev = NULL;
        struct linux_ebus_child *edev_child = NULL;
@@ -1084,8 +1061,7 @@ static int __init envctrl_init(void)
        for_each_ebus(ebus) {
                for_each_ebusdev(edev, ebus) {
                        if (!strcmp(edev->prom_name, "i2c")) {
-                               i2c = ioremap(  edev->resource[0].start, 
-                                                               sizeof(struct pcf8584_reg));
+                               i2c = ioremap(edev->resource[0].start, 0x2);
                                for_each_edevchild(edev, edev_child) {
                                        if (!strcmp("gpio", edev_child->prom_name)) {
                                                i2c_childlist[i].i2ctype = I2C_GPIO;
@@ -1108,15 +1084,15 @@ done:
        }
 
        /* Set device address. */
-       envctrl_writeb(CONTROL_PIN, &i2c->csr);
-       envctrl_writeb(PCF8584_ADDRESS, &i2c->data);
+       writeb(CONTROL_PIN, i2c + PCF8584_CSR);
+       writeb(PCF8584_ADDRESS, i2c + PCF8584_DATA);
 
        /* Set system clock and SCL frequencies. */ 
-       envctrl_writeb(CONTROL_PIN | CONTROL_ES1, &i2c->csr);
-       envctrl_writeb(CLK_4_43 | BUS_CLK_90, &i2c->data);
+       writeb(CONTROL_PIN | CONTROL_ES1, i2c + PCF8584_CSR);
+       writeb(CLK_4_43 | BUS_CLK_90, i2c + PCF8584_DATA);
 
        /* Enable serial interface. */
-       envctrl_writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, &i2c->csr);
+       writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c + PCF8584_CSR);
        udelay(200);
 
        /* Register the device as a minor miscellaneous device. */
@@ -1139,9 +1115,11 @@ done:
                        i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
        }
 
-       err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
-       if (err < 0)
+       kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+       if (IS_ERR(kenvctrld_task)) {
+               err = PTR_ERR(kenvctrld_task);
                goto out_deregister;
+       }
 
        return 0;
 
@@ -1149,50 +1127,23 @@ out_deregister:
        misc_deregister(&envctrl_dev);
 out_iounmap:
        iounmap(i2c);
-       for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
-               if (i2c_childlist[i].tables)
-                       kfree(i2c_childlist[i].tables);
-       }
+       for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++)
+               kfree(i2c_childlist[i].tables);
+
        return err;
-#else
-       return -ENODEV;
-#endif
 }
 
 static void __exit envctrl_cleanup(void)
 {
        int i;
 
-       if (NULL != kenvctrld_task) {
-               force_sig(SIGKILL, kenvctrld_task);
-               for (;;) {
-                       struct task_struct *p;
-                       int found = 0;
-
-                       read_lock(&tasklist_lock);
-                       for_each_process(p) {
-                               if (p == kenvctrld_task) {
-                                       found = 1;
-                                       break;
-                               }
-                       }
-                       read_unlock(&tasklist_lock);
-
-                       if (!found)
-                               break;
-
-                       msleep(1000);
-               }
-               kenvctrld_task = NULL;
-       }
+       kthread_stop(kenvctrld_task);
 
        iounmap(i2c);
        misc_deregister(&envctrl_dev);
 
-       for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
-               if (i2c_childlist[i].tables)
-                       kfree(i2c_childlist[i].tables);
-       }
+       for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++)
+               kfree(i2c_childlist[i].tables);
 }
 
 module_init(envctrl_init);