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 / char / snsc.c
index 25917e0..56c8243 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004, 2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 /*
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <asm/sn/io.h>
 #include <asm/sn/sn_sal.h>
+#include <asm/sn/module.h>
+#include <asm/sn/geo.h>
 #include <asm/sn/nodepda.h>
 #include "snsc.h"
 
@@ -74,7 +77,7 @@ scdrv_open(struct inode *inode, struct file *file)
        scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev);
 
        /* allocate memory for subchannel data */
-       sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+       sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
        if (sd == NULL) {
                printk("%s: couldn't allocate subchannel data\n",
                       __FUNCTION__);
@@ -82,7 +85,6 @@ scdrv_open(struct inode *inode, struct file *file)
        }
 
        /* initialize subch_data_s fields */
-       memset(sd, 0, sizeof (struct subch_data_s));
        sd->sd_nasid = scd->scd_nasid;
        sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid);
 
@@ -189,8 +191,8 @@ scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
                }
 
                len = CHUNKSIZE;
-               add_wait_queue(&sd->sd_rq, &wait);
                set_current_state(TASK_INTERRUPTIBLE);
+               add_wait_queue(&sd->sd_rq, &wait);
                spin_unlock_irqrestore(&sd->sd_rlock, flags);
 
                schedule_timeout(SCDRV_TIMEOUT);
@@ -285,8 +287,8 @@ scdrv_write(struct file *file, const char __user *buf,
                        return -EAGAIN;
                }
 
-               add_wait_queue(&sd->sd_wq, &wait);
                set_current_state(TASK_INTERRUPTIBLE);
+               add_wait_queue(&sd->sd_wq, &wait);
                spin_unlock_irqrestore(&sd->sd_wlock, flags);
 
                schedule_timeout(SCDRV_TIMEOUT);
@@ -354,6 +356,8 @@ static struct file_operations scdrv_fops = {
        .release =      scdrv_release,
 };
 
+static struct class *snsc_class;
+
 /*
  * scdrv_init
  *
@@ -364,42 +368,33 @@ int __init
 scdrv_init(void)
 {
        geoid_t geoid;
-       cmoduleid_t cmod;
-       int i;
+       cnodeid_t cnode;
        char devname[32];
        char *devnamep;
-       module_t *m;
        struct sysctl_data_s *scd;
        void *salbuf;
-       struct class_simple *snsc_class;
        dev_t first_dev, dev;
+       nasid_t event_nasid = ia64_sn_get_console_nasid();
 
-       if (alloc_chrdev_region(&first_dev, 0, (MAX_SLABS*nummodules),
+       if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
                                SYSCTL_BASENAME) < 0) {
                printk("%s: failed to register SN system controller device\n",
                       __FUNCTION__);
                return -ENODEV;
        }
-       snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
-
-       for (cmod = 0; cmod < nummodules; cmod++) {
-               m = sn_modules[cmod];
-               for (i = 0; i <= MAX_SLABS; i++) {
+       snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
 
-                       if (m->nodes[i] == -1) {
-                               /* node is not alive in module */
-                               continue;
-                       }
-
-                       geoid = m->geoid[i];
+       for (cnode = 0; cnode < num_cnodes; cnode++) {
+                       geoid = cnodeid_get_geoid(cnode);
                        devnamep = devname;
                        format_module_id(devnamep, geo_module(geoid),
                                         MODULE_FORMAT_BRIEF);
                        devnamep = devname + strlen(devname);
-                       sprintf(devnamep, "#%d", geo_slab(geoid));
+                       sprintf(devnamep, "^%d#%d", geo_slot(geoid),
+                               geo_slab(geoid));
 
                        /* allocate sysctl device data */
-                       scd = kmalloc(sizeof (struct sysctl_data_s),
+                       scd = kzalloc(sizeof (struct sysctl_data_s),
                                      GFP_KERNEL);
                        if (!scd) {
                                printk("%s: failed to allocate device info"
@@ -407,10 +402,9 @@ scdrv_init(void)
                                       SYSCTL_BASENAME, devname);
                                continue;
                        }
-                       memset(scd, 0, sizeof (struct sysctl_data_s));
 
                        /* initialize sysctl device data fields */
-                       scd->scd_nasid = cnodeid_to_nasid(m->nodes[i]);
+                       scd->scd_nasid = cnodeid_to_nasid(cnode);
                        if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
                                printk("%s: failed to allocate driver buffer"
                                       "(%s%s)\n", __FUNCTION__,
@@ -431,7 +425,7 @@ scdrv_init(void)
                                continue;
                        }
 
-                       dev = first_dev + m->nodes[i];
+                       dev = first_dev + cnode;
                        cdev_init(&scd->scd_cdev, &scdrv_fops);
                        if (cdev_add(&scd->scd_cdev, dev, 1)) {
                                printk("%s: failed to register system"
@@ -442,13 +436,19 @@ scdrv_init(void)
                                continue;
                        }
 
-                       class_simple_device_add(snsc_class, dev, NULL,
+                       class_device_create(snsc_class, NULL, dev, NULL,
                                                "%s", devname);
 
                        ia64_sn_irtr_intr_enable(scd->scd_nasid,
                                                 0 /*ignored */ ,
                                                 SAL_IROUTER_INTR_RECV);
-               }
+
+                        /* on the console nasid, prepare to receive
+                         * system controller environmental events
+                         */
+                        if(scd->scd_nasid == event_nasid) {
+                                scdrv_event_init(scd);
+                        }
        }
        return 0;
 }