X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fsnsc.c;h=52753e723eaae5cf361a5b06cc097b2a7ce0da25;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=25917e08ea84d78bf7a94549b6d5def5e9a558ea;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 25917e08e..52753e723 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -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. */ /* @@ -21,7 +21,10 @@ #include #include #include +#include #include +#include +#include #include #include "snsc.h" @@ -31,7 +34,7 @@ #define SCDRV_TIMEOUT 1000 static irqreturn_t -scdrv_interrupt(int irq, void *subch_data, struct pt_regs *regs) +scdrv_interrupt(int irq, void *subch_data) { struct subch_data_s *sd = subch_data; unsigned long flags; @@ -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); @@ -103,7 +105,7 @@ scdrv_open(struct inode *inode, struct file *file) /* hook this subchannel up to the system controller interrupt */ rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt, - SA_SHIRQ | SA_INTERRUPT, + IRQF_SHARED | IRQF_DISABLED, SYSCTL_BASENAME, sd); if (rv) { ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch); @@ -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); @@ -345,7 +347,7 @@ scdrv_poll(struct file *file, struct poll_table_struct *wait) return mask; } -static struct file_operations scdrv_fops = { +static const struct file_operations scdrv_fops = { .owner = THIS_MODULE, .read = scdrv_read, .write = scdrv_write, @@ -354,6 +356,8 @@ static struct file_operations scdrv_fops = { .release = scdrv_release, }; +static struct class *snsc_class; + /* * scdrv_init * @@ -364,42 +368,38 @@ 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; + + if (!ia64_platform_is("sn2")) + return -ENODEV; - if (alloc_chrdev_region(&first_dev, 0, (MAX_SLABS*nummodules), + event_nasid = ia64_sn_get_console_nasid(); + + 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 +407,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 +430,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 +441,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; }