summaryrefslogtreecommitdiffstats
path: root/drivers/i2o
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2o')
-rw-r--r--drivers/i2o/i2o_block.c21
-rw-r--r--drivers/i2o/i2o_config.c316
-rw-r--r--drivers/i2o/i2o_core.c630
-rw-r--r--drivers/i2o/i2o_lan.c142
-rw-r--r--drivers/i2o/i2o_lan.h2
-rw-r--r--drivers/i2o/i2o_proc.c367
6 files changed, 746 insertions, 732 deletions
diff --git a/drivers/i2o/i2o_block.c b/drivers/i2o/i2o_block.c
index 78d3a6c53..a0cab3015 100644
--- a/drivers/i2o/i2o_block.c
+++ b/drivers/i2o/i2o_block.c
@@ -685,7 +685,6 @@ static int i2ob_release(struct inode *inode, struct file *file)
minor = MINOR(inode->i_rdev);
if (minor >= (MAX_I2OB<<4))
return -ENODEV;
- sync_dev(inode->i_rdev);
dev = &i2ob_dev[(minor&0xF0)];
if (dev->refcnt <= 0)
printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt);
@@ -739,7 +738,9 @@ static int i2ob_open(struct inode *inode, struct file *file)
if (minor >= MAX_I2OB<<4)
return -ENODEV;
dev=&i2ob_dev[(minor&0xF0)];
-
+ if(dev->i2odev == NULL)
+ return -ENODEV;
+
if(dev->refcnt++==0)
{
u32 msg[6];
@@ -822,7 +823,6 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
i2ob_query_device(dev, 0x0000, 6, &status, 4);
i2ob_sizes[unit] = (int)(size>>10);
i2ob_hardsizes[unit] = blocksize;
- i2ob_gendisk.part[unit].nr_sects = i2ob_sizes[unit];
limit=4096; /* 8 deep scatter gather */
@@ -870,7 +870,7 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
printk(".\n");
printk("%s: Maximum sectors/read set to %d.\n",
d->dev_name, i2ob_max_sectors[unit]);
- resetup_one_dev(&i2ob_gendisk, unit>>4);
+ grok_partitions(&i2ob_gendisk, unit>>4, 1<<4, (long)(size>>9));
return 0;
}
@@ -1014,14 +1014,6 @@ static struct block_device_operations i2ob_fops =
check_media_change: i2ob_media_change,
revalidate: i2ob_revalidate,
};
-
-/*
- * Partitioning
- */
-
-static void i2ob_geninit(struct gendisk *gd)
-{
-}
static struct gendisk i2ob_gendisk =
{
@@ -1029,8 +1021,6 @@ static struct gendisk i2ob_gendisk =
"i2ohd",
4,
1<<4,
- MAX_I2OB,
- i2ob_geninit,
i2ob,
i2ob_sizes,
0,
@@ -1129,6 +1119,9 @@ int i2o_block_init(void)
* Finally see what is actually plugged in to our controllers
*/
+ for (i = 0; i < MAX_I2OB; i++)
+ register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4,
+ &i2ob_fops, 0);
i2ob_probe();
register_reboot_notifier(&i2ob_reboot_notifier);
diff --git a/drivers/i2o/i2o_config.c b/drivers/i2o/i2o_config.c
index 96d9c17e1..4133db0cb 100644
--- a/drivers/i2o/i2o_config.c
+++ b/drivers/i2o/i2o_config.c
@@ -1,26 +1,28 @@
/*
- * I2O Configuration Interface Driver
+ * I2O Configuration Interface Driver
*
- * (C) Copyright 1999 Red Hat Software
+ * (C) Copyright 1999 Red Hat Software
*
- * Written by Alan Cox, Building Number Three Ltd
+ * Written by Alan Cox, Building Number Three Ltd
*
- * Modified 04/20/1999 by Deepak Saxena
- * - Added basic ioctl() support
- * Modified 06/07/1999 by Deepak Saxena
- * - Added software download ioctl (still testing)
- * Modified 09/10/1999 by Auvo Häkkinen
- * - Changes to i2o_cfg_reply(), ioctl_parms()
- * - Added ioct_validate()
- * Modified 09/30/1999 by Taneli Vähäkangas
- * - Fixed ioctl_swdl()
- * Modified 10/04/1999 by Taneli Vähäkangas
- * - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
+ * Modified 04/20/1999 by Deepak Saxena
+ * - Added basic ioctl() support
+ * Modified 06/07/1999 by Deepak Saxena
+ * - Added software download ioctl (still testing)
+ * Modified 09/10/1999 by Auvo Häkkinen
+ * - Changes to i2o_cfg_reply(), ioctl_parms()
+ * - Added ioct_validate()
+ * Modified 09/30/1999 by Taneli Vähäkangas
+ * - Fixed ioctl_swdl()
+ * Modified 10/04/1999 by Taneli Vähäkangas
+ * - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
+ * Modified 11/18/199 by Deepak Saxena
+ * - Added event managmenet support
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
@@ -37,13 +39,29 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-static int i2o_cfg_token = 0;
static int i2o_cfg_context = -1;
static void *page_buf;
static void *i2o_buffer;
static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
struct wait_queue *i2o_wait_queue;
+#define MODINC(x,y) (x = x++ % y)
+
+struct i2o_cfg_info
+{
+ struct file* fp;
+ struct fasync_struct *fasync;
+ struct i2o_evt_info event_q[I2O_EVT_Q_LEN];
+ u16 q_in; // Queue head index
+ u16 q_out; // Queue tail index
+ u16 q_len; // Queue length
+ u16 q_lost; // Number of lost events
+ u32 q_id; // Event queue ID...used as tx_context
+ struct i2o_cfg_info *next;
+};
+static struct i2o_cfg_info *open_files = NULL;
+static int i2o_cfg_info_id = 0;
+
static int ioctl_getiops(unsigned long);
static int ioctl_gethrt(unsigned long);
static int ioctl_getlct(unsigned long);
@@ -53,6 +71,9 @@ static int ioctl_swdl(unsigned long);
static int ioctl_swul(unsigned long);
static int ioctl_swdel(unsigned long);
static int ioctl_validate(unsigned long);
+static int ioctl_evt_reg(unsigned long, struct file *);
+static int ioctl_evt_get(unsigned long, struct file *);
+static int cfg_fasync(int, struct file*, int);
/*
* This is the callback for any message we have posted. The message itself
@@ -62,13 +83,78 @@ static int ioctl_validate(unsigned long);
*/
static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m)
{
- u32 *msg = (u32 *)m;
+ u32 *msg = (u32 *)m;
+
+ if (msg[0] & (1<<13))
+ printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
- if (msg[4] >> 24) // RegStatus != SUCCESS
- i2o_cfg_token = -(msg[4] & 0xFFFF); // DetailedStatus
- else
- i2o_cfg_token = I2O_POST_WAIT_OK;
-
+ if (msg[4] >> 24) // RegStatus != SUCCESS
+ i2o_report_status(KERN_INFO,"i2o_config",msg);
+
+ if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
+ {
+ struct i2o_cfg_info *inf;
+
+ for(inf = open_files; inf; inf = inf->next)
+ if(inf->q_id == msg[3])
+ break;
+
+ //
+ // If this is the case, it means that we're getting
+ // events for a file descriptor that's been close()'d
+ // w/o the user unregistering for events first.
+ // The code currently assumes that the user will
+ // take care of unregistering for events before closing
+ // a file.
+ //
+ // TODO:
+ // Should we track event registartion and deregister
+ // for events when a file is close()'d so this doesn't
+ // happen? That would get rid of the search through
+ // the linked list since file->private_data could point
+ // directly to the i2o_config_info data structure...but
+ // it would mean having all sorts of tables to track
+ // what each file is registered for...I think the
+ // current method is simpler. - DS
+ //
+ if(!inf)
+ return;
+
+ inf->event_q[inf->q_in].id.iop = c->unit;
+ inf->event_q[inf->q_in].id.tid = m->target_tid;
+ inf->event_q[inf->q_in].id.evt_mask = msg[4];
+
+ //
+ // Data size = msg size - reply header
+ //
+ inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;
+ if(inf->event_q[inf->q_in].data_size)
+ memcpy(inf->event_q[inf->q_in].evt_data,
+ (unsigned char *)(msg + 5),
+ inf->event_q[inf->q_in].data_size);
+
+ spin_lock(&i2o_config_lock);
+ MODINC(inf->q_in, I2O_EVT_Q_LEN);
+ if(inf->q_len == I2O_EVT_Q_LEN)
+ {
+ MODINC(inf->q_out, I2O_EVT_Q_LEN);
+ inf->q_lost++;
+ }
+ else
+ {
+ // Keep I2OEVTGET on another CPU from touching this
+ inf->q_len++;
+ }
+ spin_unlock(&i2o_config_lock);
+
+
+// printk(KERN_INFO "File %p w/id %d has %d events\n",
+// inf->fp, inf->q_id, inf->q_len);
+
+ if(inf->fasync)
+ kill_fasync(inf->fasync, SIGIO, POLL_IN);
+ }
+
return;
}
@@ -107,14 +193,11 @@ static ssize_t cfg_read(struct file *file, char *buf, size_t count, loff_t *ptr)
/*
* IOCTL Handler
*/
-static int cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
unsigned long arg)
{
int ret;
- /* Only 1 token, so lock... */
- spin_lock(&i2o_config_lock);
-
switch(cmd)
{
case I2OGETIOPS:
@@ -157,11 +240,18 @@ static int cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = ioctl_html(arg);
break;
+ case I2OEVTREG:
+ ret = ioctl_evt_reg(arg, fp);
+ break;
+
+ case I2OEVTGET:
+ ret = ioctl_evt_get(arg, fp);
+ break;
+
default:
ret = -EINVAL;
}
- spin_unlock(&i2o_config_lock);
return ret;
}
@@ -320,7 +410,7 @@ static int ioctl_parms(unsigned long arg, unsigned int type)
}
len = i2o_issue_params(i2o_cmd, c, kcmd.tid,
- ops, kcmd.oplen, res, sizeof(res));
+ ops, kcmd.oplen, res, 65536);
i2o_unlock_controller(c);
kfree(ops);
@@ -392,7 +482,7 @@ int ioctl_html(unsigned long arg)
}
}
- res = kmalloc(4096, GFP_KERNEL);
+ res = kmalloc(65536, GFP_KERNEL);
if(!res)
{
i2o_unlock_controller(c);
@@ -403,21 +493,22 @@ int ioctl_html(unsigned long arg)
msg[2] = i2o_cfg_context;
msg[3] = 0;
msg[4] = kcmd.page;
- msg[5] = 0xD0000000|4096;
+ msg[5] = 0xD0000000|65536;
msg[6] = virt_to_bus(res);
if(!kcmd.qlen) /* Check for post data */
msg[0] = SEVEN_WORD_MSG_SIZE|SGL_OFFSET_5;
else
{
msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
- msg[5] = 0x50000000|4096;
+ msg[5] = 0x50000000|65536;
msg[7] = 0xD4000000|(kcmd.qlen);
msg[8] = virt_to_phys(query);
}
token = i2o_post_wait(c, msg, 9*4, 10);
- if(token != I2O_POST_WAIT_OK)
+ if(token)
{
+ printk(KERN_DEBUG "token = %#10x\n", token);
i2o_unlock_controller(c);
kfree(res);
if(kcmd.qlen) kfree(query);
@@ -426,7 +517,7 @@ int ioctl_html(unsigned long arg)
}
i2o_unlock_controller(c);
- len = strnlen(res, 8192);
+ len = strnlen(res, 65536);
put_user(len, kcmd.reslen);
if(len > reslen)
ret = -ENOMEM;
@@ -500,7 +591,7 @@ int ioctl_swdl(unsigned long arg)
{
// it fails if you try and send frags out of order
// and for some yet unknown reasons too
- printk("i2o_config: swdl failed, DetailedStatus = %d\n", status);
+ printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status);
return -ETIMEDOUT;
}
@@ -562,7 +653,7 @@ int ioctl_swul(unsigned long arg)
if (status != I2O_POST_WAIT_OK)
{
kfree(buffer);
- printk("i2o_config: swul failed, DetailedStatus = %d\n", status);
+ printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status);
return -ETIMEDOUT;
}
@@ -603,7 +694,7 @@ int ioctl_swdel(unsigned long arg)
if (token != I2O_POST_WAIT_OK)
{
- printk("i2o_config: swdel failed, DetailedStatus = %d\n", token);
+ printk(KERN_INFO "i2o_config: swdel failed, DetailedStatus = %d\n", token);
return -ETIMEDOUT;
}
@@ -631,7 +722,7 @@ int ioctl_validate(unsigned long arg)
if (token != I2O_POST_WAIT_OK)
{
- printk("Can't validate configuration, ErrorStatus = %d\n",
+ printk(KERN_INFO "Can't validate configuration, ErrorStatus = %d\n",
token);
return -ETIMEDOUT;
}
@@ -639,22 +730,154 @@ int ioctl_validate(unsigned long arg)
return 0;
}
+static int ioctl_evt_reg(unsigned long arg, struct file *fp)
+{
+ u32 msg[5];
+ struct i2o_evt_id *pdesc = (struct i2o_evt_id *)arg;
+ struct i2o_evt_id kdesc;
+ struct i2o_controller *iop;
+ struct i2o_device *d;
+
+ if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id)))
+ return -EFAULT;
+
+ /* IOP exists? */
+ iop = i2o_find_controller(kdesc.iop);
+ if(!iop)
+ return -ENXIO;
+ i2o_unlock_controller(iop);
+
+ /* Device exists? */
+ for(d = iop->devices; d; d = d->next)
+ if(d->lct_data->tid == kdesc.tid)
+ break;
+
+ if(!d)
+ return -ENODEV;
+
+ msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | kdesc.tid;
+ msg[2] = (u32)i2o_cfg_context;
+ msg[3] = (u32)fp->private_data;
+ msg[4] = kdesc.evt_mask;
+
+ i2o_post_this(iop, msg, 20);
+
+ return 0;
+}
+
+static int ioctl_evt_get(unsigned long arg, struct file *fp)
+{
+ u32 id = (u32)fp->private_data;
+ struct i2o_cfg_info *p = NULL;
+ struct i2o_evt_get *uget = (struct i2o_evt_get*)arg;
+ struct i2o_evt_get kget;
+ unsigned int flags;
+
+ // access_ok doesn't check for NULL?!?!
+ if(!arg)
+ return -EFAULT;
+
+ if(!access_ok(VERIFY_WRITE, uget, sizeof(struct i2o_evt_get)))
+ return -EFAULT;
+
+ for(p = open_files; p; p = p->next)
+ if(p->q_id == id)
+ break;
+
+ if(!p->q_len)
+ {
+ return -ENOENT;
+ return 0;
+ }
+
+ memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
+ MODINC(p->q_out, I2O_EVT_Q_LEN);
+ spin_lock_irqsave(&i2o_config_lock, flags);
+ p->q_len--;
+ kget.pending = p->q_len;
+ kget.lost = p->q_lost;
+ spin_unlock_irqrestore(&i2o_config_lock, flags);
+
+ __copy_to_user(uget, &kget, sizeof(struct i2o_evt_get));
+
+ return 0;
+}
static int cfg_open(struct inode *inode, struct file *file)
{
- /*
- * Should support multiple management users
- */
+ struct i2o_cfg_info *tmp =
+ (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL);
+ unsigned int flags;
+
+ if(!tmp)
+ return -ENOMEM;
+
+ file->private_data = (void*)(i2o_cfg_info_id++);
+ tmp->fp = file;
+ tmp->fasync = NULL;
+ tmp->q_id = (u32)file->private_data;
+ tmp->q_len = 0;
+ tmp->q_in = 0;
+ tmp->q_out = 0;
+ tmp->q_lost = 0;
+ tmp->next = open_files;
+
+ spin_lock_irqsave(&i2o_config_lock, flags);
+ open_files = tmp;
+ spin_unlock_irqrestore(&i2o_config_lock, flags);
+
MOD_INC_USE_COUNT;
return 0;
}
static int cfg_release(struct inode *inode, struct file *file)
{
+ u32 id = (u32)file->private_data;
+ struct i2o_cfg_info *p1, *p2;
+ unsigned int flags;
+
+ p1 = p2 = NULL;
+
+ spin_lock_irqsave(&i2o_config_lock, flags);
+ for(p1 = open_files; p1; )
+ {
+ if(p1->q_id == id)
+ {
+
+ if(p1->fasync)
+ cfg_fasync(-1, file, 0);
+ if(p2)
+ p2->next = p1->next;
+ else
+ open_files = p1->next;
+
+ kfree(p1);
+ break;
+ }
+ p2 = p1;
+ p1 = p1->next;
+ }
+ spin_unlock_irqrestore(&i2o_config_lock, flags);
+
MOD_DEC_USE_COUNT;
return 0;
}
+static int cfg_fasync(int fd, struct file *fp, int on)
+{
+ u32 id = (u32)fp->private_data;
+ struct i2o_cfg_info *p;
+
+ for(p = open_files; p; p = p->next)
+ if(p->q_id == id)
+ break;
+
+ if(!p)
+ return -EBADF;
+
+ return fasync_helper(fd, fp, on, &p->fasync);
+}
static struct file_operations config_fops =
{
@@ -667,7 +890,9 @@ static struct file_operations config_fops =
NULL, /* No mmap */
cfg_open,
NULL, /* No flush */
- cfg_release
+ cfg_release,
+ NULL,
+ cfg_fasync
};
static struct miscdevice i2o_miscdev = {
@@ -682,7 +907,8 @@ int init_module(void)
int __init i2o_config_init(void)
#endif
{
- printk(KERN_INFO "i2o configuration manager v 0.03\n");
+ printk(KERN_INFO "I2O configuration manager v 0.04.\n");
+ printk(KERN_INFO " (C) Copyright 1999 Red Hat Software");
if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL)
{
diff --git a/drivers/i2o/i2o_core.c b/drivers/i2o/i2o_core.c
index ff3e2405f..6428af9fc 100644
--- a/drivers/i2o/i2o_core.c
+++ b/drivers/i2o/i2o_core.c
@@ -18,7 +18,6 @@
* Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
* Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
- *
*/
#include <linux/config.h>
@@ -35,7 +34,6 @@
#include <linux/bitops.h>
#include <linux/wait.h>
-#include <linux/delay.h>
#include <linux/timer.h>
#include <asm/io.h>
@@ -53,19 +51,22 @@
static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];
static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];
+struct i2o_controller *i2o_controller_chain;
int i2o_num_controllers = 0;
static int core_context = 0;
-extern int i2o_online_controller(struct i2o_controller *c);
+static int i2o_activate_controller(struct i2o_controller *iop);
+static int i2o_online_controller(struct i2o_controller *c);
static int i2o_init_outbound_q(struct i2o_controller *c);
static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
struct i2o_message *);
static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *);
static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *);
-static void i2o_dump_message(u32 *msg);
+void i2o_dump_message(u32 *msg);
static int i2o_issue_claim(struct i2o_controller *, int, int, int, u32);
+static int i2o_reset_controller(struct i2o_controller *);
static int i2o_lct_get(struct i2o_controller *);
static int i2o_hrt_get(struct i2o_controller *);
@@ -176,9 +177,7 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
{
if (msg[4] >> 24)
{
- /* 0x40000000 is used as an error report supress bit */
- if(msg[2]&0x40000000)
- i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
+ i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
status = -(msg[4] & 0xFFFF);
}
else
@@ -233,7 +232,6 @@ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d)
d->next=c->devices;
c->devices=d;
*d->dev_name = 0;
- d->owner = NULL;
for(i = 0; i < I2O_MAX_MANAGERS; i++)
d->managers[i] = NULL;
@@ -307,12 +305,7 @@ int i2o_install_controller(struct i2o_controller *c)
c->next=i2o_controller_chain;
i2o_controller_chain=c;
c->unit = i;
- c->page_frame = NULL;
- c->hrt = NULL;
- c->lct = NULL;
- c->status_block = NULL;
-// printk(KERN_INFO "lct @ %p hrt @ %p status @ %p",
-// c->lct, c->hrt, c->status_block);
+
sprintf(c->name, "i2o/iop%d", i);
i2o_num_controllers++;
spin_unlock(&i2o_configuration_lock);
@@ -328,15 +321,13 @@ int i2o_delete_controller(struct i2o_controller *c)
{
struct i2o_controller **p;
int users;
-
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Deleting controller iop%d\n", c->unit);
-#endif
+ char name[16];
spin_lock(&i2o_configuration_lock);
if((users=atomic_read(&c->users)))
{
- printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit);
+ printk(KERN_INFO "%s busy: %d users for controller.\n", c->name, users);
+ c->bus_disable(c);
spin_unlock(&i2o_configuration_lock);
return -EBUSY;
}
@@ -345,6 +336,7 @@ int i2o_delete_controller(struct i2o_controller *c)
if(__i2o_delete_device(c->devices)<0)
{
/* Shouldnt happen */
+ c->bus_disable(c);
spin_unlock(&i2o_configuration_lock);
return -EBUSY;
}
@@ -356,8 +348,8 @@ int i2o_delete_controller(struct i2o_controller *c)
{
if(*p==c)
{
- /* Ask the IOP to switch to HOLD state */
- i2o_clear_controller(c);
+ /* Ask the IOP to switch into RESET state */
+ i2o_reset_controller(c);
/* Release IRQ */
c->destructor(c);
@@ -365,8 +357,6 @@ int i2o_delete_controller(struct i2o_controller *c)
*p=c->next;
spin_unlock(&i2o_configuration_lock);
-// printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n",
-// c->hrt, c->lct, c->page_frame, c->status_block);
if(c->page_frame)
kfree(c->page_frame);
if(c->hrt)
@@ -376,14 +366,13 @@ int i2o_delete_controller(struct i2o_controller *c)
if(c->status_block)
kfree(c->status_block);
- kfree(c);
-
i2o_controllers[c->unit]=NULL;
-
+ memcpy(name, c->name, strlen(c->name)+1);
+ kfree(c);
i2o_num_controllers--;
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "iop deleted\n");
-#endif
+
+ dprintk((KERN_INFO "%s: Deleted from controller chain.\n", name));
+
return 0;
}
p=&((*p)->next);
@@ -540,17 +529,20 @@ void i2o_run_queue(struct i2o_controller *c)
u32 mv;
#ifdef DEBUG_IRQ
- printk(KERN_INFO "iop%d interrupt\n", c->unit);
+ printk(KERN_INFO "%s: interrupt\n", c->name);
#endif
+ /* Sometimes we get here, but a message can't be read. Why? */
+ if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)
+ mv=I2O_REPLY_READ32(c);
- while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF)
+ while (mv!=0xFFFFFFFF)
{
struct i2o_handler *i;
m=(struct i2o_message *)bus_to_virt(mv);
/*
* Temporary Debugging
*/
- if(((m->function_addr>>24)&0xFF)==0x15)
+ if(m->function==0x15)
printk("UTFR!\n");
#ifdef DEBUG_IRQ
@@ -562,12 +554,13 @@ void i2o_run_queue(struct i2o_controller *c)
i->reply(i,c,m);
else
{
- printk("Spurious reply to handler %d\n",
+ printk("i2o: Spurious reply to handler %d\n",
m->initiator_context&(MAX_I2O_MODULES-1));
i2o_dump_message((u32*)m);
}
i2o_flush_reply(c,mv);
mb();
+ mv=I2O_REPLY_READ32(c);
}
}
@@ -699,7 +692,6 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit)
}
if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16)>=0)
{
-
buf[16]=0;
printk(" Device: %s", buf);
}
@@ -707,7 +699,7 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit)
if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)
{
buf[16]=0;
- printk(KERN_INFO "Description: %s\n", buf);
+ printk("Description: %s", buf);
}
#endif
if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8)>=0)
@@ -831,25 +823,17 @@ static int i2o_parse_lct(struct i2o_controller *c)
char str[22];
i2o_lct *lct = c->lct;
- max = lct->table_size;
+ if (lct == NULL) {
+ printk(KERN_ERR "%s: LCT is empty???\n",c->name);
+ return -1;
+ }
+ max = lct->table_size;
max -= 3;
max /= 9;
- if(max==0)
- {
- printk(KERN_ERR "%s: LCT is empty????\n",c->name);
- return -1;
- }
-
printk(KERN_INFO "%s: LCT has %d entries.\n", c->name,max);
- if(max > 128)
- {
- printk(KERN_INFO "%s: LCT was truncated.\n",c->name);
- max=128;
- }
-
if(lct->iop_flags&(1<<0))
printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name);
@@ -870,7 +854,7 @@ static int i2o_parse_lct(struct i2o_controller *c)
d->flags = 0;
tid = d->lct_data->tid;
- printk(KERN_INFO "Task ID %d.\n", tid);
+ printk(KERN_INFO "Target ID %d.\n", tid);
i2o_report_controller_unit(c, tid);
@@ -880,10 +864,10 @@ static int i2o_parse_lct(struct i2o_controller *c)
sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id));
printk("%s", str);
-
- printk(" Subclass: 0x%04X Flags: ",
+
+ printk(" Subclass: 0x%04X Flags: ",
d->lct_data->sub_class);
-
+
if(d->lct_data->device_flags&(1<<0))
printk("C"); // ConfigDialog requested
if(d->lct_data->device_flags&(1<<1))
@@ -899,37 +883,44 @@ static int i2o_parse_lct(struct i2o_controller *c)
}
-/* Quiesce IOP */
+/*
+ * Quiesce IOP. Causes IOP to make external operation quiescend.
+ * Internal operation of the IOP continues normally.
+ */
int i2o_quiesce_controller(struct i2o_controller *c)
{
u32 msg[4];
int ret;
- if ((c->status_block->iop_state != ADAPTER_STATE_READY) &
- (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL))
+ /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
+
+ if ((c->status_block->iop_state != ADAPTER_STATE_READY) &&
+ (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL))
{
- dprintk((KERN_INFO "%s: Not in READY or OPERATIONAL state\n",
- c->name));
- dprintk((KERN_INFO "%s: state = %d\n",
- c->name, c->status_block->iop_state));
- return -EINVAL;
+ return 0;
}
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
+ msg[3]=0;
/* Long timeout needed for quiesce if lots of devices */
if ((ret = i2o_post_wait(c, msg, sizeof(msg), 120)))
- printk(KERN_INFO "%s: Unable to quiesce.\n", c->name);
+ printk(KERN_INFO "%s: Unable to quiesce (status=%#10x).\n",
+ c->name, ret);
else
dprintk((KERN_INFO "%s: Quiesced.\n", c->name));
+ i2o_status_get(c); // Reread the Status Block
+
return ret;
}
-/* Enable IOP */
+/*
+ * Enable IOP. Allows the IOP to resume external operations.
+ */
int i2o_enable_controller(struct i2o_controller *c)
{
u32 msg[4];
@@ -937,44 +928,80 @@ int i2o_enable_controller(struct i2o_controller *c)
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
/* How long of a timeout do we need? */
if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
- printk(KERN_ERR "%s: Could not enable, %d\n", c->name, ret);
+ printk(KERN_ERR "%s: Could not enable (status=%#10x).\n",
+ c->name, ret);
+ else
+ dprintk((KERN_INFO "%s: Enabled.\n", c->name));
+
+ i2o_status_get(c);
return ret;
}
-/* Reset an IOP, but keep message queues alive */
+/*
+ * Clear an IOP to HOLD state, ie. terminate external operations, clear all
+ * input queues and prepare for a system restart. IOP's internal operation
+ * continues normally and the outbound queue is alive.
+ * IOP is not expected to rebuild its LCT.
+ */
int i2o_clear_controller(struct i2o_controller *c)
{
+ struct i2o_controller *iop;
u32 msg[4];
int ret;
+ /* Quiesce all IOPs first */
+
+ for (iop = i2o_controller_chain; iop; iop = iop->next)
+ i2o_quiesce_controller(iop);
+
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
+ msg[3]=0;
if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
- printk(KERN_INFO "%s: Unable to clear, %#10x\n",
+ printk(KERN_INFO "%s: Unable to clear (status=%#10x).\n",
c->name, ret);
+ else
+ dprintk((KERN_INFO "%s: Cleared.\n",c->name));
- i2o_status_get(c); // Reread the Status Block
+ i2o_status_get(c);
+
+ /* Enable other IOPs */
+
+ for (iop = i2o_controller_chain; iop; iop = iop->next)
+ if (iop != c)
+ i2o_enable_controller(iop);
return ret;
}
-/* Reset the IOP to sane state */
+/*
+ * Reset the IOP into INIT state and wait until IOP gets into RESET state.
+ * Terminate all external operations, clear IOP's inbound and outbound
+ * queues, terminate all DDMs, and reload the IOP's operating environment
+ * and all local DDMs. IOP rebuilds its LCT.
+ */
static int i2o_reset_controller(struct i2o_controller *c)
{
+ struct i2o_controller *iop;
u32 m;
u8 *status;
u32 *msg;
long time;
+ /* Quiesce all IOPs first */
+
+ for (iop = i2o_controller_chain; iop; iop = iop->next)
+ i2o_quiesce_controller(iop);
+
m=i2o_wait_message(c, "AdapterReset");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -1013,16 +1040,14 @@ static int i2o_reset_controller(struct i2o_controller *c)
barrier();
}
- if (status[0]==0x02)
- printk(KERN_WARNING "%s: Reset rejected.\n",c->name);
- else
+ if (status[0]==0x01)
{
/*
* Once the reset is sent, the IOP goes into the INIT state
- * which is inditerminate. We need to wait until the IOP
+ * which is indeterminate. We need to wait until the IOP
* has rebooted before we can let the system talk to
* it. We read the inbound Free_List until a message is
- * available. If we can't read one in the given ammount of
+ * available. If we can't read one in the given amount of
* time, we assume the IOP could not reboot properly.
*/
@@ -1043,9 +1068,26 @@ static int i2o_reset_controller(struct i2o_controller *c)
}
i2o_flush_reply(c,m);
- printk(KERN_INFO "%s: Reset completed.\n", c->name);
+
+ dprintk((KERN_INFO "%s: Reset completed.\n", c->name));
}
+ /* If IopReset was rejected or didn't perform reset, try IopClear */
+
+ i2o_status_get(c);
+ if (status[0] == 0x02 || c->status_block->iop_state != ADAPTER_STATE_RESET)
+ {
+ printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name);
+ i2o_clear_controller(c);
+
+ }
+
+ /* Enable other IOPs */
+
+ for (iop = i2o_controller_chain; iop; iop = iop->next)
+ if (iop != c)
+ i2o_enable_controller(iop);
+
kfree(status);
return 0;
}
@@ -1157,13 +1199,14 @@ int i2o_hrt_get(struct i2o_controller *c)
msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
+ msg[3]= 0;
msg[4]= (0xD0000000 | size); /* Simple transaction */
msg[5]= virt_to_phys(c->hrt); /* Dump it here */
if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
- printk(KERN_ERR "%s: Unable to get HRT,"
- " Status = %d.\n",c->name, ret);
+ printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n",
+ c->name, ret);
return ret;
}
@@ -1193,6 +1236,8 @@ static int i2o_systab_send(struct i2o_controller *iop)
iop->status->current_io_base;
iop->status->current_io_size;
#endif
+
+/* FIXME */
privmem[0]=iop->priv_mem; /* Private memory space base address */
privmem[1]=iop->priv_mem_size;
privio[0]=iop->priv_io; /* Private I/O address */
@@ -1200,7 +1245,8 @@ static int i2o_systab_send(struct i2o_controller *iop)
msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
- /* [2] and [3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
+ msg[3] = 0;
msg[4] = (0<<16) | ((iop->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
msg[5] = 0; /* Segment 0 */
@@ -1217,8 +1263,10 @@ static int i2o_systab_send(struct i2o_controller *iop)
msg[11] = virt_to_phys(privio);
if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
- printk(KERN_INFO "%s: Unable to set SysTab, %d\n",
- iop->name, ret);
+ printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n",
+ iop->name, ret);
+ else
+ dprintk((KERN_INFO "%s: SysTab set.\n", iop->name));
return ret;
@@ -1229,292 +1277,114 @@ static int i2o_systab_send(struct i2o_controller *iop)
*/
static void __init i2o_sys_init()
{
- struct i2o_controller *iop, *niop;
- int ret;
- u32 m;
+ struct i2o_controller *iop, *niop = NULL;
printk(KERN_INFO "Activating I2O controllers\n");
printk(KERN_INFO "This may take a few minutes if there are many devices\n");
- /* Get the status for each IOP */
- for(iop = i2o_controller_chain; iop; iop = niop)
- {
- niop = iop->next;
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
-#endif
- if(i2o_status_get(iop)<0)
- {
- printk("Unable to obtain status of IOP, attempting a reset.\n");
- i2o_reset_controller(iop);
- if(i2o_status_get(iop)<0)
- {
- printk("IOP not responding.\n");
- i2o_delete_controller(iop);
- continue;
- }
- }
-
- if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
- {
- printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
- iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
+ /* In INIT state, Activate IOPs */
- if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
- iop->status_block->iop_state == ADAPTER_STATE_READY ||
- iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
- iop->status_block->iop_state == ADAPTER_STATE_FAILED)
- {
- int msg[256];
-
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "iop%d already running...trying to reboot\n",
- iop->unit);
-#endif
- i2o_init_outbound_q(iop);
- I2O_REPLY_WRITE32(iop,virt_to_phys(msg));
- i2o_quiesce_controller(iop);
- i2o_reset_controller(iop);
- if(i2o_status_get(iop) ||
- iop->status_block->iop_state != ADAPTER_STATE_RESET)
- {
- printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
- }
- }
-
- /*
- * Now init the outbound queue for each one.
- */
- for(iop = i2o_controller_chain; iop; iop = niop)
- {
- int i;
-
+ for (iop = i2o_controller_chain; iop; iop = niop) {
niop = iop->next;
-
- if((ret=i2o_init_outbound_q(iop)))
- {
- printk(KERN_ERR
- "IOP%d initialization failed: Could not initialize outbound q\n",
- iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
- iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
-
- if(iop->page_frame==NULL)
- {
- printk(KERN_CRIT "iop%d init failed: no memory for message page.\n",
- iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
-
- m=virt_to_phys(iop->page_frame);
-
- for(i=0; i< NMBR_MSG_FRAMES; i++)
- {
- I2O_REPLY_WRITE32(iop,m);
- mb();
- m+=MSG_FRAME_SIZE;
- mb();
- }
+ i2o_activate_controller(iop);
}
- /*
- * OK..parse the HRT
- */
- for(iop = i2o_controller_chain; iop; iop = niop)
- {
- niop = iop->next;
- if(i2o_hrt_get(iop))
- {
- printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
- if(i2o_parse_hrt(iop))
- {
- printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
- }
+ /* Active IOPs in HOLD state */
+
+rebuild_sys_tab:
+ if (i2o_controller_chain == NULL)
+ return;
/*
- * Build and send the system table
- *
* If build_sys_table fails, we kill everything and bail
* as we can't init the IOPs w/o a system table
*/
- if(i2o_build_sys_table())
- {
- printk(KERN_CRIT "I2O: Error building system table. Aborting!\n");
+ if (i2o_build_sys_table() < 0) {
i2o_sys_shutdown();
return;
}
- for(iop = i2o_controller_chain; iop; iop = niop)
-#ifdef DRIVERDEBUG
- {
- niop = iop->next;
- printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
-#endif
- if(i2o_systab_send(iop))
- {
- printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
-#ifdef DRIVERDEBUG
- }
-#endif
-
- /*
- * Enable
- */
- for(iop = i2o_controller_chain; iop; iop = niop)
- {
- niop = iop->next;
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Enabling iop%d\n", iop->unit);
-#endif
- if(i2o_enable_controller(iop))
- {
- printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
- }
-
- /*
- * OK..one last thing and we're ready to go!
- */
- for(iop = i2o_controller_chain; iop; iop = niop)
- {
+ /* If IOP don't get online, we need to rebuild the System table */
+ for (iop = i2o_controller_chain; iop; iop = niop) {
niop = iop->next;
-#ifdef DRIVERDEBUG
- printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
-#endif
- if(i2o_lct_get(iop))
- {
- printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
- i2o_delete_controller(iop);
- continue;
- }
- else
- i2o_parse_lct(iop);
+ if (i2o_online_controller(iop) < 0)
+ goto rebuild_sys_tab;
}
+
+ /* Active IOPs now in OPERATIONAL state */
}
/*
* Shutdown I2O system
- *
- * 1. Quiesce all controllers
- * 2. Delete all controllers
*/
static void i2o_sys_shutdown(void)
{
struct i2o_controller *iop, *niop;
- for (iop = i2o_controller_chain; iop ; iop=iop->next) {
- i2o_quiesce_controller(iop);
- i2o_status_get(iop); // Update IOP status block
- }
+ /* Delete all IOPs from the controller chain */
+ /* that will reset all IOPs too */
for (iop = i2o_controller_chain; iop; iop = niop) {
niop = iop->next;
- if (i2o_delete_controller(iop))
- iop->bus_disable(iop);
+ i2o_delete_controller(iop);
}
}
/*
- * Bring an I2O controller into HOLD state. See the 1.5
- * spec. Basically we go
- *
- * Wait for the message queue to initialise.
- * If it didnt -> controller is dead
- *
- * Send a get status using the message queue
- * Poll for a reply block 88 bytes long
- *
- * Send an initialise outbound queue
- * Poll for a reply
- *
- * Post our blank messages to the queue FIFO
- *
- * Send GetHRT, Parse it
+ * Bring an I2O controller into HOLD state. See the spec.
*/
-int i2o_activate_controller(struct i2o_controller *c)
+int i2o_activate_controller(struct i2o_controller *iop)
{
- return 0;
-#ifdef I2O_HOTPLUG_SUPPORT
- u32 m;
- int i;
- int ret;
-
- printk(KERN_INFO "%s: Configuring I2O controller at 0x%08X.\n",
- c->name, (u32)c->mem_phys);
-
- if((ret=i2o_status_get(c)))
- return ret;
+ /* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */
+ /* In READY state, Get status */
+
+ if (i2o_status_get(iop) < 0) {
+ printk("Unable to obtain status of IOP, attempting a reset.\n");
+ i2o_reset_controller(iop);
+ if (i2o_status_get(iop) < 0) {
+ printk("IOP not responding.\n");
+ i2o_delete_controller(iop);
+ return -1;
+ }
+ }
- /* not likely to be seen */
- if(c->status_block->iop_state == ADAPTER_STATE_FAULTED)
- {
- printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
- c->unit);
+ if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) {
+ printk(KERN_CRIT "%s: hardware fault\n", iop->name);
+ i2o_delete_controller(iop);
return -1;
}
- /*
- * If the board is running, reset it - we have no idea
- * what kind of a mess the previous owner left it in.
- * We need to feed the IOP a single outbound message
- * so that it can reply back to the ExecSysQuiesce.
- */
- if(c->status_block->iop_state == ADAPTER_STATE_HOLD ||
- c->status_block->iop_state == ADAPTER_STATE_READY ||
- c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
- c->status_block->iop_state == ADAPTER_STATE_FAILED)
+// if (iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
+ if (iop->status_block->iop_state == ADAPTER_STATE_READY ||
+ iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+ iop->status_block->iop_state == ADAPTER_STATE_FAILED)
{
- int msg[256];
- printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit);
+ dprintk((KERN_INFO "%s: already running...trying to reset\n",
+ iop->name));
+ i2o_reset_controller(iop);
- if(i2o_init_outbound_q(c));
- I2O_REPLY_WRITE32(c,virt_to_phys(msg));
-
- if((ret=i2o_reset_controller(c)))
- return ret;
-
- if((ret=i2o_status_get(c)))
- return ret;
+ if (i2o_status_get(iop) < 0 ||
+ iop->status_block->iop_state != ADAPTER_STATE_RESET)
+ {
+ printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
+ i2o_delete_controller(iop);
+ return -1;
+ }
}
- if ((ret=i2o_init_outbound_q(c))){
- return ret;
+ if (i2o_init_outbound_q(iop) < 0) {
+ i2o_delete_controller(iop);
+ return -1;
}
- /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
-
- /*
- * The outbound queue is initialised and loaded,
- *
- * Now we need the Hardware Resource Table. We must ask for
- * this next we can't issue random messages yet.
- */
-
- if ((ret=i2o_hrt_get(c)))
- return ret;
+ /* In HOLD state */
+
+ if (i2o_hrt_get(iop) < 0) {
+ i2o_delete_controller(iop);
+ return -1;
+ }
- return i2o_online_controller(c);
-#endif
+ return 0;
}
/*
@@ -1533,7 +1403,6 @@ int i2o_init_outbound_q(struct i2o_controller *c)
return -ETIMEDOUT;
msg=(u32 *)(c->mem_offset+m);
-
status = kmalloc(4,GFP_KERNEL);
if (status==NULL) {
printk(KERN_ERR "%s: IOP reset failed - no free memory.\n",
@@ -1568,6 +1437,8 @@ int i2o_init_outbound_q(struct i2o_controller *c)
barrier();
}
+ /* Alloc space for IOP's outbound queue message frames */
+
c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
if(c->page_frame==NULL) {
printk(KERN_CRIT "%s: Outbound Q initialize failed; out of memory.\n",
@@ -1577,6 +1448,8 @@ int i2o_init_outbound_q(struct i2o_controller *c)
}
m=virt_to_phys(c->page_frame);
+ /* Post frames */
+
for(i=0; i< NMBR_MSG_FRAMES; i++) {
I2O_REPLY_WRITE32(c,m);
mb();
@@ -1608,15 +1481,16 @@ int i2o_lct_get(struct i2o_controller *c)
msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
+ msg[3] = 0;
msg[4] = 0xFFFFFFFF; /* All devices */
msg[5] = 0x00000000; /* Report now */
msg[6] = 0xD0000000|size;
msg[7] = virt_to_bus(c->lct);
if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
- printk(KERN_ERR "%s: Unable to get LCT,"
- " Status = %d.\n", c->name,ret);
+ printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n",
+ c->name, ret);
return ret;
}
@@ -1627,83 +1501,39 @@ int i2o_lct_get(struct i2o_controller *c)
}
} while (c->lct == NULL);
+ if ((ret=i2o_parse_lct(c)) < 0)
+ return ret;
+
return 0;
}
/*
- * Bring a controller online. Needs completing for multiple controllers
+ * Bring a controller online into OPERATIONAL state.
*/
-int i2o_online_controller(struct i2o_controller *c)
+int i2o_online_controller(struct i2o_controller *iop)
{
- return 0;
-#ifdef I2O_HOTPLUG_SUPPORT
- u32 msg[10];
- u32 privmem[2];
- u32 privio[2];
- int ret;
+ if (i2o_systab_send(iop) < 0) {
+ i2o_delete_controller(iop);
+ return -1;
+ }
- /*
- * Build and send the system table
- *
- * If build_sys_table fails, we kill everything and bail
- * as we can't init the IOPs w/o a system table
- */
-
- if (i2o_build_sys_table()) {
- i2o_sys_shutdown();
- return;
- }
-
- privmem[0]=c->priv_mem; /* Private memory space base address */
- privmem[1]=c->priv_mem_size;
- privio[0]=c->priv_io; /* Private I/O address */
- privio[1]=c->priv_io_size;
-
- __raw_writel(TEN_WORD_MSG_SIZE|SGL_OFFSET_6, &msg[0]);
- __raw_writel(I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID, &msg$
- __raw_writel(0, &msg[2]); /* Context not needed */
- __raw_writel(0, &msg[3]);
- __raw_writel((0<<16)|(2<<12), &msg[4]); /* Host 1 I2O 2 */
- __raw_writel(0, &msg[5]); /* Segment 1 */
-
- /*
- * Scatter Gather List
- */
-
- __raw_writel(0x54000000|sys_tbl_len, &msg[6]); /* One table for now */
- __raw_writel(virt_to_phys(sys_tbl), &msg[[7]);
- __raw_writel(0xD4000000|48, &msg[8]); /* One table for now */
- __raw_writel(virt_to_phys(privmem), &msg[9]);
-
- ret = (i2o_post_wait(c, msg, sizeof(msg), 120);
- if (ret)
- return ret;
-
- /*
- * Finally we go online
- */
- ret = i2o_enable_controller(c);
- if(ret)
- return ret;
+ /* In READY state */
- /*
- * Grab the LCT, see what is attached
- */
- ret=i2o_lct_get(c);
- if(ret)
- {
- /* Maybe we should do also do something else */
- return ret;
- }
+ if (i2o_enable_controller(iop) < 0) {
+ i2o_delete_controller(iop);
+ return -1;
+ }
- ret=i2o_parse_lct(c);
- if(ret)
- return ret;
+ /* In OPERATIONAL state */
- return 0;
-#endif
+ if (i2o_lct_get(iop) < 0){
+ i2o_delete_controller(iop);
+ return -1;
+ }
+
+ return 0;
}
static int i2o_build_sys_table(void)
@@ -1923,7 +1753,8 @@ int i2o_event_ack(struct i2o_controller *c, int tid, int context,
msg[0] = I2O_MESSAGE_SIZE(5 + evt_data_len / 4) | SGL_OFFSET_5;
msg[1] = I2O_CMD_UTIL_EVT_ACK << 24 | HOST_TID << 12 | tid;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ msg[2] = context;
+ msg[3] = 0;
msg[4] = evt_indicator;
memcpy(msg+5, evt_data, evt_data_len);
@@ -1947,9 +1778,10 @@ static int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int o
else
msg[1] = I2O_CMD_UTIL_RELEASE << 24 | HOST_TID << 12 | tid;
- /* msg[2] and msg[3] filled in i2o_post_wait */
+ /* msg[2] filled in i2o_post_wait */
+ msg[3] = 0;
msg[4] = type;
-
+
return i2o_post_wait(c, msg, sizeof(msg), 2);
}
@@ -1970,6 +1802,8 @@ int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid,
msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
msg[1] = cmd << 24 | HOST_TID << 12 | tid;
+ /* msg[2] filled in i2o_post_wait */
+ msg[3] = 0;
msg[4] = 0;
msg[5] = 0x54000000 | oplen; /* OperationBlock */
msg[6] = virt_to_bus(opblk);
@@ -2515,7 +2349,7 @@ void i2o_report_status(const char *severity, const char *module, u32 *msg)
}
/* Used to dump a message to syslog during debugging */
-static void i2o_dump_message(u32 *msg)
+void i2o_dump_message(u32 *msg)
{
#ifdef DRIVERDEBUG
int i;
@@ -2531,10 +2365,7 @@ static void i2o_dump_message(u32 *msg)
EXPORT_SYMBOL(i2o_install_handler);
EXPORT_SYMBOL(i2o_remove_handler);
-EXPORT_SYMBOL(i2o_install_device);
-EXPORT_SYMBOL(i2o_delete_device);
-EXPORT_SYMBOL(i2o_quiesce_controller);
-EXPORT_SYMBOL(i2o_clear_controller);
+
EXPORT_SYMBOL(i2o_install_controller);
EXPORT_SYMBOL(i2o_delete_controller);
EXPORT_SYMBOL(i2o_unlock_controller);
@@ -2547,9 +2378,7 @@ EXPORT_SYMBOL(i2o_event_ack);
EXPORT_SYMBOL(i2o_claim_device);
EXPORT_SYMBOL(i2o_release_device);
EXPORT_SYMBOL(i2o_run_queue);
-EXPORT_SYMBOL(i2o_report_controller_unit);
EXPORT_SYMBOL(i2o_activate_controller);
-EXPORT_SYMBOL(i2o_online_controller);
EXPORT_SYMBOL(i2o_get_class_name);
EXPORT_SYMBOL(i2o_status_get);
@@ -2558,7 +2387,6 @@ EXPORT_SYMBOL(i2o_set_scalar);
EXPORT_SYMBOL(i2o_query_table);
EXPORT_SYMBOL(i2o_clear_table);
EXPORT_SYMBOL(i2o_row_add_table);
-EXPORT_SYMBOL(i2o_row_delete_table);
EXPORT_SYMBOL(i2o_post_this);
EXPORT_SYMBOL(i2o_post_wait);
@@ -2632,7 +2460,7 @@ int __init i2o_init(void)
#endif
if(i2o_num_controllers)
- i2o_init();
+ i2o_sys_init();
i2o_config_init();
#ifdef CONFIG_I2O_BLOCK
diff --git a/drivers/i2o/i2o_lan.c b/drivers/i2o/i2o_lan.c
index 08fcc2c2c..d6aa43398 100644
--- a/drivers/i2o/i2o_lan.c
+++ b/drivers/i2o/i2o_lan.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/i2o/i2o_lan.c
*
- * I2O LAN CLASS OSM December 2nd 1999
+ * I2O LAN CLASS OSM January 7th 1999
*
* (C) Copyright 1999 University of Helsinki,
* Department of Computer Science
@@ -18,7 +18,8 @@
* Deepak Saxena <deepak@plexity.net>
*
* Tested: in FDDI environment (using SysKonnect's DDM)
- * in Ethernet environment (using Intel 82558 DDM proto)
+ * in Gigabit Eth environment (using SysKonnect's DDM)
+ * in Fast Ethernet environment (using Intel 82558 DDM)
*
* TODO: check error checking / timeouts
* code / test for other LAN classes
@@ -68,11 +69,12 @@ struct i2o_lan_local {
unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
u32 bucket_count; /* nbr of buckets sent to DDM */
u32 tx_count; /* packets in one TX message frame */
- u32 tx_max; /* DDM's Tx queue len */
+ u32 tx_max_out; /* DDM's Tx queue len */
u32 tx_out; /* outstanding TXes */
u32 sgl_max; /* max SGLs in one message frame */
u32 m; /* IOP address of msg frame */
+ struct tq_struct i2o_batch_send_task;
struct sk_buff **i2o_fbl; /* Free bucket list (to reuse skbs) */
int i2o_fbl_tail;
@@ -98,6 +100,9 @@ static struct tq_struct i2o_post_buckets_task = {
0, 0, (void (*)(void *))i2o_lan_receive_post, (void *) 0
};
+/*
+ * i2o_lan_reply(): The only callback function to handle incoming messages.
+ */
static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
struct i2o_message *m)
{
@@ -133,7 +138,7 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
}
// Something VERY wrong if this is happening
- printk( KERN_WARNING "i2olan: Device %s rejected bucket post.\n", dev->name);
+ printk( KERN_WARNING "%s: rejected bucket post.\n", dev->name);
}
// Shutting down, we are getting unused buckets back
@@ -165,7 +170,7 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
break;
}
- case LAN_RESET:
+ case LAN_RESET: /* default reply without payload */
case LAN_SUSPEND:
break;
@@ -175,12 +180,14 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
break;
default:
- printk(KERN_ERR "%s: Sorry, no handler for the reply.\n", dev->name);
+ printk(KERN_ERR "%s: No handler for the reply.\n", dev->name);
i2o_report_status(KERN_INFO, dev->name, msg);
}
}
-
+/*
+ * i2o_lan_event_reply(): Handle events.
+ */
static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -277,6 +284,9 @@ static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
/* Do we need to do something here too? */
}
+/*
+ * i2o_lan_release_buckets(): Handle unused buckets.
+ */
static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -292,6 +302,9 @@ static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
}
}
+/*
+ * i2o_lan_receive_post_reply(): Process incoming packets.
+ */
static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -332,15 +345,17 @@ static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
bucket++; // to next Packet Descriptor Block
}
- if ((msg[4] & 0x000000FF) == I2O_LAN_DSC_BUCKET_OVERRUN)
- printk(KERN_INFO "%s: DDM out of buckets (count = %d)!\n",
- dev->name, msg[5]);
+#ifdef DRIVERDEBUG
+ if (msg[5] == 0)
+ printk(KERN_INFO "%s: DDM out of buckets (priv->count = %d)!\n",
+ dev->name, priv->bucket_count);
+#endif
if (priv->bucket_count <= bucketpost - bucketthresh) {
-// i2o_lan_receive_post(dev);
i2o_post_buckets_task.data = (void *)dev;
queue_task(&i2o_post_buckets_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
+ /* Note: the task is queued only once */
}
return 0;
@@ -415,6 +430,7 @@ static int i2o_lan_reset(struct net_device *dev)
struct i2o_controller *iop = i2o_dev->controller;
u32 msg[5];
+ dprintk(KERN_INFO "%s: LAN RESET MESSAGE.\n", dev->name);
msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
@@ -453,7 +469,7 @@ static int i2o_lan_suspend(struct net_device *dev)
}
/*
- * Set DDM into batch mode.
+ * i2o_set_batch_mode(): Set DDM into batch mode.
*/
static void i2o_set_batch_mode(struct net_device *dev)
{
@@ -498,9 +514,10 @@ static int i2o_lan_open(struct net_device *dev)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_device *i2o_dev = priv->i2o_dev;
+#if 0
struct i2o_controller *iop = i2o_dev->controller;
- u32 evt_mask = 0xFFC00007; // All generic events, all lan evenst
-
+ u32 evt_mask = 0xFFC00007; // All generic events, all lan events
+#endif
if (i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) {
printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);
return -EAGAIN;
@@ -543,8 +560,8 @@ static int i2o_lan_close(struct net_device *dev)
if (i2o_event_register(iop, i2o_dev->lct_data->tid,
priv->unit << 16 | lan_context, 0) < 0)
printk(KERN_WARNING "%s: Unable to clear the event mask.\n",
- dev->name);
-#endif
+#endif dev->name);
+
dev->tbusy = 1;
dev->start = 0;
i2o_lan_suspend(dev);
@@ -586,10 +603,6 @@ static void i2o_lan_batch_send(struct net_device *dev)
}
}
-struct tq_struct i2o_post_send_task = {
- 0, 0, (void (*)(void *))i2o_lan_batch_send, (void *) 0
-};
-
/*
* i2o_lan_packet_send(): Send a packet as is, including the MAC header.
*
@@ -598,8 +611,8 @@ struct tq_struct i2o_post_send_task = {
*/
static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
{
- struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
- struct i2o_device *i2o_dev = priv->i2o_dev;
+ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+ struct i2o_device *i2o_dev = priv->i2o_dev;
struct i2o_controller *iop = i2o_dev->controller;
u32 m, *msg;
u32 *sgl_elem;
@@ -616,7 +629,7 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
priv->tx_count++;
priv->tx_out++;
- if (priv->tx_count == 1) {
+ if (priv->tx_count == 1) {
dprintk("%s: New message frame\n", dev->name);
m = I2O_POST_READ32(iop);
@@ -635,42 +648,40 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
__raw_writel((u32)skb, msg+5); // TransactionContext
__raw_writel(virt_to_bus(skb->data), msg+6);
- i2o_post_send_task.data = (void *)dev;
- queue_task(&i2o_post_send_task, &tq_scheduler);
-
- if (priv->tx_out < priv->tx_max)
- clear_bit(0, (void *)&dev->tbusy);
-
- return 0;
- }
-
- /* Else add new SGL element to the previous message frame */
-
- dprintk("%s: Adding packet %d to msg frame\n", dev->name, priv->tx_count);
+ queue_task(&priv->i2o_batch_send_task, &tq_scheduler);
- msg = (u32 *)(iop->mem_offset + priv->m);
- sgl_elem = &msg[priv->tx_count * 3 + 1];
+ } else { /* Add new SGL element to the previous message frame */
- __raw_writel(I2O_MESSAGE_SIZE((__raw_readl(msg)>>16) + 3) | 1<<12 | SGL_OFFSET_4, msg);
- __raw_writel(__raw_readl(sgl_elem-3) & 0x7FFFFFFF, sgl_elem-3); /* clear LE flag */
- __raw_writel(0xD5000000 | skb->len, sgl_elem);
- __raw_writel((u32)skb, sgl_elem+1);
- __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
-
- if (priv->tx_count == priv->sgl_max) { /* frame full, send now */
-// i2o_lan_batch_send(dev);
- i2o_post_message(iop, priv->m);
- dprintk("%s: %d packets sent.\n", dev->name, priv->tx_count);
- priv->tx_count = 0;
+ dprintk("%s: Adding packet %d to msg frame\n",
+ dev->name, priv->tx_count);
+
+ msg = (u32 *)(iop->mem_offset + priv->m);
+ sgl_elem = &msg[priv->tx_count * 3 + 1];
+
+ __raw_writel(I2O_MESSAGE_SIZE((__raw_readl(msg)>>16) + 3) | 1<<12 | SGL_OFFSET_4, msg);
+ __raw_writel(__raw_readl(sgl_elem-3) & 0x7FFFFFFF, sgl_elem-3); /* clear LE flag */
+ __raw_writel(0xD5000000 | skb->len, sgl_elem);
+ __raw_writel((u32)skb, sgl_elem+1);
+ __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
+
+ if (priv->tx_count == priv->sgl_max) { /* frame full, send now */
+ i2o_post_message(iop, priv->m);
+ dprintk("%s: %d packets sent.\n", dev->name, priv->tx_count);
+ priv->tx_count = 0;
+ }
}
+
+ /* If HDMs TxMaxPktOut reached, stay busy (don't clean tbusy) */
- if (priv->tx_out < priv->tx_max)
+ if (priv->tx_out < priv->tx_max_out)
clear_bit(0, (void *)&dev->tbusy);
-
+
return 0;
}
-
+/*
+ * i2o_lan_get_stats(): Fill in the statistics.
+ */
static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
{
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -882,12 +893,27 @@ static void i2o_lan_set_multicast_list(struct net_device *dev)
queue_task(task, &tq_scheduler);
}
+/*
+ * i2o_lan_change_mtu(): Change maximum transfer unit size.
+ */
+static int i2o_lan_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if ((new_mtu < 68) || (new_mtu > 9000))
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+/*
+ * i2o_lan_register_device(): Register LAN class device to kernel.
+ */
struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
{
struct net_device *dev = NULL;
struct i2o_lan_local *priv = NULL;
u8 hw_addr[8];
- u32 tx_max = 0;
+ u32 tx_max_out = 0;
unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
void (*unregister_dev)(struct net_device *dev);
@@ -981,7 +1007,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
memcpy(dev->dev_addr, hw_addr, 6);
if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
- 0x0007, 2, &tx_max, sizeof(tx_max)) < 0)
+ 0x0007, 2, &tx_max_out, sizeof(tx_max_out)) < 0)
{
printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
unit--;
@@ -989,17 +1015,23 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
kfree(dev);
return NULL;
}
- dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, tx_max);
- priv->tx_max = tx_max;
+ dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, tx_max_out);
+ priv->tx_max_out = tx_max_out;
priv->tx_out = 0;
priv->tx_count = 0;
priv->lock = SPIN_LOCK_UNLOCKED;
+ priv->i2o_batch_send_task.next = NULL;
+ priv->i2o_batch_send_task.sync = 0;
+ priv->i2o_batch_send_task.routine = (void *)i2o_lan_batch_send;
+ priv->i2o_batch_send_task.data = (void *)dev;
+
dev->open = i2o_lan_open;
dev->stop = i2o_lan_close;
dev->hard_start_xmit = i2o_lan_packet_send;
dev->get_stats = i2o_lan_get_stats;
dev->set_multicast_list = i2o_lan_set_multicast_list;
+ dev->change_mtu = i2o_lan_change_mtu;
return dev;
}
diff --git a/drivers/i2o/i2o_lan.h b/drivers/i2o/i2o_lan.h
index 7cd22e9ac..d4e5aa44b 100644
--- a/drivers/i2o/i2o_lan.h
+++ b/drivers/i2o/i2o_lan.h
@@ -18,7 +18,7 @@
/* Tunable parameters first */
#define I2O_BUCKET_COUNT 256
-#define I2O_BUCKET_THRESH 8
+#define I2O_BUCKET_THRESH 18 /* 9 buckets in one message */
/* LAN types */
#define I2O_LAN_ETHERNET 0x0030
diff --git a/drivers/i2o/i2o_proc.c b/drivers/i2o/i2o_proc.c
index 2d1c06ddc..ed89973eb 100644
--- a/drivers/i2o/i2o_proc.c
+++ b/drivers/i2o/i2o_proc.c
@@ -29,7 +29,7 @@
/*
* TODO List
*
- * - Add support for any version 2.0 spec changes once 2.0 IRTOS is
+ * - Add support for any version 2.0 spec changes once 2.0 IRTOS
* is available to test with
* - Clean up code to use official structure definitions
*/
@@ -64,8 +64,6 @@ typedef struct _i2o_proc_entry_t
write_proc_t *write_proc; /* write func */
} i2o_proc_entry;
-static int proc_context = 0;
-
static int i2o_proc_read_lct(char *, char **, off_t, int, int *, void *);
static int i2o_proc_read_hrt(char *, char **, off_t, int, int *, void *);
static int i2o_proc_read_status(char *, char **, off_t, int, int *, void *);
@@ -101,8 +99,6 @@ static void i2o_proc_remove_controller(struct i2o_controller *,
struct proc_dir_entry * );
static int create_i2o_procfs(void);
static int destroy_i2o_procfs(void);
-static void i2o_proc_reply(struct i2o_handler *, struct i2o_controller *,
- struct i2o_message *);
static int i2o_proc_read_lan_dev_info(char *, char **, off_t, int, int *,
void *);
@@ -134,17 +130,6 @@ static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *,
static struct proc_dir_entry *i2o_proc_dir_root;
/*
- * Message handler
- */
-static struct i2o_handler i2o_proc_handler =
-{
- (void *)i2o_proc_reply,
- "I2O procfs Layer",
- 0,
- 0xffffffff // All classes
-};
-
-/*
* IOP specific entries...write field just in case someone
* ever wants one.
*/
@@ -255,9 +240,6 @@ static i2o_proc_entry lan_fddi_entries[] =
{NULL, 0, NULL, NULL}
};
-
-static u32 i2o_proc_token = 0;
-
static char *chtostr(u8 *chars, int n)
{
char tmp[256];
@@ -295,12 +277,6 @@ static char* bus_strings[] =
static spinlock_t i2o_proc_lock = SPIN_LOCK_UNLOCKED;
-void i2o_proc_reply(struct i2o_handler *phdlr, struct i2o_controller *pctrl,
- struct i2o_message *pmsg)
-{
- i2o_proc_token = I2O_POST_WAIT_OK;
-}
-
int i2o_proc_read_hrt(char *buf, char **start, off_t offset, int len,
int *eof, void *data)
{
@@ -681,7 +657,7 @@ int i2o_proc_read_status(char *buf, char **start, off_t offset, int len,
c->status_block->expected_lct_size);
len += sprintf(buf+len,"IOP Capabilities\n");
- len += sprintf(buf+len," Context Field Size Support : ");
+ len += sprintf(buf+len," Context Field Size Support : ");
switch (c->status_block->iop_capabilities & 0x0000003) {
case 0:
len += sprintf(buf+len,"Supports only 32-bit context fields\n");
@@ -700,7 +676,7 @@ int i2o_proc_read_status(char *buf, char **start, off_t offset, int len,
default:
len += sprintf(buf+len,"0x%08x\n",c->status_block->iop_capabilities);
}
- len += sprintf(buf+len," Current Context Field Size : ");
+ len += sprintf(buf+len," Current Context Field Size : ");
switch (c->status_block->iop_capabilities & 0x0000000C) {
case 0:
len += sprintf(buf+len,"not configured\n");
@@ -718,11 +694,11 @@ int i2o_proc_read_status(char *buf, char **start, off_t offset, int len,
default:
len += sprintf(buf+len,"\n");
}
- len += sprintf(buf+len," Inbound Peer Support : %s\n",
+ len += sprintf(buf+len," Inbound Peer Support : %s\n",
(c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported");
- len += sprintf(buf+len," Outbound Peer Support : %s\n",
+ len += sprintf(buf+len," Outbound Peer Support : %s\n",
(c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported");
- len += sprintf(buf+len," Peer to Peer Support : %s\n",
+ len += sprintf(buf+len," Peer to Peer Support : %s\n",
(c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported");
len += sprintf(buf+len, "Desired private memory size : %d kB\n",
@@ -790,17 +766,17 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len,
len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10);
hwcap = work32[3];
- len += sprintf(buf+len, "Capabilities :\n");
- if(hwcap&0x00000001)
- len += sprintf(buf+len, " Self-booting\n");
- if(hwcap&0x00000002)
- len += sprintf(buf+len, " Upgradable IRTOS\n");
- if(hwcap&0x00000004)
- len += sprintf(buf+len, " Supports downloading DDMs\n");
- if(hwcap&0x00000008)
- len += sprintf(buf+len, " Supports installing DDMs\n");
- if(hwcap&0x00000010)
- len += sprintf(buf+len, " Battery-backed RAM\n");
+ len += sprintf(buf+len, "Capabilities : 0x%08x\n", hwcap);
+ len += sprintf(buf+len, " [%s] Self booting\n",
+ (hwcap&0x00000001) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Upgradable IRTOS\n",
+ (hwcap&0x00000002) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Supports downloading DDMs\n",
+ (hwcap&0x00000004) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Supports installing DDMs\n",
+ (hwcap&0x00000008) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Battery-backed RAM\n",
+ (hwcap&0x00000010) ? "+" : "-");
spin_unlock(&i2o_proc_lock);
@@ -1695,23 +1671,23 @@ int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len,
break;
}
- len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable);
- if (result.event_enable & 0x01)
- len += sprintf(buf+len, "\tOperational state change. \n");
- if (result.event_enable & 0x02)
- len += sprintf(buf+len, "\tLow catastrophic. \n");
- if (result.event_enable & 0x04)
- len += sprintf(buf+len, "\tLow reading. \n");
- if (result.event_enable & 0x08)
- len += sprintf(buf+len, "\tLow warning. \n");
- if (result.event_enable & 0x10)
- len += sprintf(buf+len, "\tChange back to normal from out of range state. \n");
- if (result.event_enable & 0x20)
- len += sprintf(buf+len, "\tHigh warning. \n");
- if (result.event_enable & 0x40)
- len += sprintf(buf+len, "\tHigh reading. \n");
- if (result.event_enable & 0x80)
- len += sprintf(buf+len, "\tHigh catastrophic. \n");
+ len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable);
+ len += sprintf(buf+len, " [%s] Operational state change. \n",
+ (result.event_enable & 0x01) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] Low catastrophic. \n",
+ (result.event_enable & 0x02) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] Low reading. \n",
+ (result.event_enable & 0x04) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] Low warning. \n",
+ (result.event_enable & 0x08) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] Change back to normal from out of range state. \n",
+ (result.event_enable & 0x10) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] High warning. \n",
+ (result.event_enable & 0x20) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] High reading. \n",
+ (result.event_enable & 0x40) ? "+" : "-" );
+ len += sprintf(buf+len, " [%s] High catastrophic. \n",
+ (result.event_enable & 0x80) ? "+" : "-" );
spin_unlock(&i2o_proc_lock);
return len;
@@ -2187,38 +2163,37 @@ int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len,
work8[16],work8[17],work8[18],work8[19],
work8[20],work8[21],work8[22],work8[23]);
- len += sprintf(buf+len, "HW/DDM capabilities : 0x%08x\n", work32[7]);
- len += sprintf(buf+len, " Unicast packets %ssupported\n",
- (work32[7]&0x00000001)?"":"not ");
- len += sprintf(buf+len, " Promiscuous mode %ssupported\n",
- (work32[7]&0x00000002)?"":"not");
- len += sprintf(buf+len, " Promiscuous multicast mode %ssupported\n",
- (work32[7]&0x00000004)?"":"not ");
- len += sprintf(buf+len," Broadcast reception disabling %ssupported\n",
- (work32[7]&0x00000100)?"":"not ");
- len += sprintf(buf+len," Multicast reception disabling %ssupported\n",
- (work32[7]&0x00000200)?"":"not ");
- len += sprintf(buf+len," Functional address disabling %ssupported\n",
- (work32[7]&0x00000400)?"":"not ");
- len += sprintf(buf+len, " MAC reporting %ssupported\n",
- (work32[7]&0x00000800)?"":"not ");
-
- len += sprintf(buf+len, "Filter mask : 0x%08x\n", work32[6]);
- len += sprintf(buf+len, " Unicast packets %s\n",
- (work32[6]&0x00000001)?"rejected":"enabled");
- len += sprintf(buf+len, " Promiscuous mode %s\n",
- (work32[6]&0x00000002)?"enabled":"disabled");
- len += sprintf(buf+len, " Promiscuous multicast mode %s\n",
- (work32[6]&0x00000004)?"enabled":"disabled");
- len += sprintf(buf+len, " Broadcast packets %s\n",
- (work32[6]&0x00000100)?"rejected":"enabled");
- len += sprintf(buf+len, " Multicast packets %s\n",
- (work32[6]&0x00000200)?"rejected":"enabled");
- len += sprintf(buf+len, " Functional address %s\n",
- (work32[6]&0x00000400)?"ignored":"enabled");
+ len += sprintf(buf+len,"HW/DDM capabilities : 0x%08x\n", work32[7]);
+ len += sprintf(buf+len," [%s] Unicast packets supported\n",
+ (work32[7]&0x00000001)?"+":"-");
+ len += sprintf(buf+len," [%s] Promiscuous mode supported\n",
+ (work32[7]&0x00000002)?"+":"-");
+ len += sprintf(buf+len," [%s] Promiscuous multicast mode supported\n",
+ (work32[7]&0x00000004)?"+":"-");
+ len += sprintf(buf+len," [%s] Broadcast reception disabling supported\n",
+ (work32[7]&0x00000100)?"+":"-");
+ len += sprintf(buf+len," [%s] Multicast reception disabling supported\n",
+ (work32[7]&0x00000200)?"+":"-");
+ len += sprintf(buf+len," [%s] Functional address disabling supported\n",
+ (work32[7]&0x00000400)?"+":"-");
+ len += sprintf(buf+len," [%s] MAC reporting supported\n",
+ (work32[7]&0x00000800)?"+":"-");
+
+ len += sprintf(buf+len,"Filter mask : 0x%08x\n", work32[6]);
+ len += sprintf(buf+len," [%s] Unicast packets disable\n",
+ (work32[6]&0x00000001)?"+":"-");
+ len += sprintf(buf+len," [%s] Promiscuous mode enable\n",
+ (work32[6]&0x00000002)?"+":"-");
+ len += sprintf(buf+len," [%s] Promiscuous multicast mode enable\n",
+ (work32[6]&0x00000004)?"+":"-");
+ len += sprintf(buf+len," [%s] Broadcast packets disable\n",
+ (work32[6]&0x00000100)?"+":"-");
+ len += sprintf(buf+len," [%s] Multicast packets disable\n",
+ (work32[6]&0x00000200)?"+":"-");
+ len += sprintf(buf+len," [%s] Functional address disable\n",
+ (work32[6]&0x00000400)?"+":"-");
- if (work32[7]&0x00000800)
- {
+ if (work32[7]&0x00000800) {
len += sprintf(buf+len, " MAC reporting mode : ");
if (work32[6]&0x00000800)
len += sprintf(buf+len, "Pass only priority MAC packets to user\n");
@@ -2321,28 +2296,10 @@ int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset,
len += sprintf(buf+len, ", toggle");
len += sprintf(buf+len, "\n");
- if(d->i2oversion == 0x00) { /* Reserved in 1.53 and 2.0 */
- len += sprintf(buf+len, "Rising load delay : %d ms\n",
- work32[1]/10);
- len += sprintf(buf+len, "Rising load threshold : %d ms\n",
- work32[2]/10);
- len += sprintf(buf+len, "Falling load delay : %d ms\n",
- work32[3]/10);
- len += sprintf(buf+len, "Falling load threshold : %d ms\n",
- work32[4]/10);
- }
-
- len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]);
- len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]);
-
- if(d->i2oversion == 0x00) {
- len += sprintf(buf+len,
- "Transmission completion reporting delay : %d ms\n",
- work32[7]);
- } else {
- len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]);
- len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]);
- }
+ len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]);
+ len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]);
+ len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]);
+ len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]);
spin_unlock(&i2o_proc_lock);
return len;
@@ -2374,37 +2331,35 @@ int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len,
(work32[1]&0x2)?"by host":"by DDM");
len += sprintf(buf+len, "Packet orphan limit : %d\n", work32[2]);
- len += sprintf(buf+len, "Tx modes :\n");
- if (work32[3]&0x00000004)
- len += sprintf(buf+len, " HW CRC supressed\n");
- else
- len += sprintf(buf+len, " HW CRC\n");
- if (work32[3]&0x00000100)
- len += sprintf(buf+len, " HW IPv4 checksumming\n");
- if (work32[3]&0x00000200)
- len += sprintf(buf+len, " HW TCP checksumming\n");
- if (work32[3]&0x00000400)
- len += sprintf(buf+len, " HW UDP checksumming\n");
- if (work32[3]&0x00000800)
- len += sprintf(buf+len, " HW RSVP checksumming\n");
- if (work32[3]&0x00001000)
- len += sprintf(buf+len, " HW ICMP checksumming\n");
- if (work32[3]&0x00002000)
- len += sprintf(buf+len, " Loopback packet not delivered\n");
-
- len += sprintf(buf+len, "Rx modes :\n");
- if (work32[4]&0x00000004)
- len += sprintf(buf+len, " FCS in payload\n");
- if (work32[4]&0x00000100)
- len += sprintf(buf+len, " HW IPv4 checksum validation\n");
- if (work32[4]&0x00000200)
- len += sprintf(buf+len, " HW TCP checksum validation\n");
- if (work32[4]&0x00000400)
- len += sprintf(buf+len, " HW UDP checksum validation\n");
- if (work32[4]&0x00000800)
- len += sprintf(buf+len, " HW RSVP checksum validation\n");
- if (work32[4]&0x00001000)
- len += sprintf(buf+len, " HW ICMP checksum validation\n");
+ len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[3]);
+ len += sprintf(buf+len, " [%s] HW CRC supression\n",
+ (work32[3]&0x00000004) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW IPv4 checksum\n",
+ (work32[3]&0x00000100) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW TCP checksum\n",
+ (work32[3]&0x00000200) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW UDP checksum\n",
+ (work32[3]&0x00000400) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW RSVP checksum\n",
+ (work32[3]&0x00000800) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW ICMP checksum\n",
+ (work32[3]&0x00001000) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Loopback supression enable\n",
+ (work32[3]&0x00002000) ? "+" : "-");
+
+ len += sprintf(buf+len, "Rx modes : 0x%08x\n", work32[4]);
+ len += sprintf(buf+len, " [%s] FCS in payload\n",
+ (work32[4]&0x00000004) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW IPv4 checksum validation\n",
+ (work32[4]&0x00000100) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW TCP checksum validation\n",
+ (work32[4]&0x00000200) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW UDP checksum validation\n",
+ (work32[4]&0x00000400) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW RSVP checksum validation\n",
+ (work32[4]&0x00000800) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] HW ICMP checksum validation\n",
+ (work32[4]&0x00001000) ? "+" : "-");
spin_unlock(&i2o_proc_lock);
return len;
@@ -2471,16 +2426,8 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
len += sprintf(buf+len, "Unspecified\n");
}
- if (d->i2oversion == 0x00) /* Reserved in 1.53 and 2.0 */
- {
- len += sprintf(buf+len, "Bad packets handled by : %s\n",
- (result.reserved == 0xFF)?"host":"DDM");
- }
- else
- {
- len += sprintf(buf+len, "Duplex mode target : ");
- switch (result.duplex_mode_target)
- {
+ len += sprintf(buf+len, "Duplex mode target : ");
+ switch (result.duplex_mode_target){
case 0:
len += sprintf(buf+len, "Half duplex\n");
break;
@@ -2489,14 +2436,13 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
break;
default:
len += sprintf(buf+len, "\n");
- }
-
- len += sprintf(buf+len, "Connector type target : %s\n",
- i2o_get_connector_type(result.connector_type_target));
- len += sprintf(buf+len, "Connection type target : %s\n",
- i2o_get_connection_type(result.connection_type_target));
}
+ len += sprintf(buf+len, "Connector type target : %s\n",
+ i2o_get_connector_type(result.connector_type_target));
+ len += sprintf(buf+len, "Connection type target : %s\n",
+ i2o_get_connection_type(result.connection_type_target));
+
spin_unlock(&i2o_proc_lock);
return len;
}
@@ -2568,46 +2514,34 @@ int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len,
return len;
}
- len += sprintf(buf, "Max SG Elements per packet : %d\n", work32[0]);
- len += sprintf(buf+len, "Max SG Elements per chain : %d\n", work32[1]);
- len += sprintf(buf+len, "Max outstanding packets : %d\n", work32[2]);
- len += sprintf(buf+len, "Max packets per request : %d\n", work32[3]);
-
- len += sprintf(buf+len, "Tx modes :\n");
- if(work32[4]&0x00000002)
- len += sprintf(buf+len, " No DA in SGL\n");
- if(work32[4]&0x00000004)
- len += sprintf(buf+len, " CRC suppression\n");
- if(work32[4]&0x00000008)
- len += sprintf(buf+len, " Loop suppression\n");
- if(work32[4]&0x00000010)
- len += sprintf(buf+len, " MAC insertion\n");
- if(work32[4]&0x00000020)
- len += sprintf(buf+len, " RIF insertion\n");
- if(work32[4]&0x00000100)
- len += sprintf(buf+len, " IPv4 checksum\n");
- if(work32[4]&0x00000200)
- len += sprintf(buf+len, " TCP checksum\n");
- if(work32[4]&0x00000400)
- len += sprintf(buf+len, " UDP checksum\n");
- if(work32[4]&0x00000800)
- len += sprintf(buf+len, " RSVP checksum\n");
- if(work32[4]&0x00001000)
- len += sprintf(buf+len, " ICMP checksum\n");
- if (d->i2oversion == 0x00)
- {
- if(work32[4]&0x00008000)
- len += sprintf(buf+len, " Loopback enabled\n");
- if(work32[4]&0x00010000)
- len += sprintf(buf+len, " Loopback suppression enabled\n");
- }
- else
- {
- if(work32[4]&0x00010000)
- len += sprintf(buf+len, " Loopback enabled\n");
- if(work32[4]&0x00020000)
- len += sprintf(buf+len, " Loopback suppression enabled\n");
- }
+ len += sprintf(buf, "Tx Max SG elements per packet : %d\n", work32[0]);
+ len += sprintf(buf+len, "Tx Max SG elements per chain : %d\n", work32[1]);
+ len += sprintf(buf+len, "Tx Max outstanding packets : %d\n", work32[2]);
+ len += sprintf(buf+len, "Tx Max packets per request : %d\n", work32[3]);
+
+ len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[4]);
+ len += sprintf(buf+len, " [%s] No DA in SGL\n",
+ (work32[4]&0x00000002) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] CRC suppression\n",
+ (work32[4]&0x00000004) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] MAC insertion\n",
+ (work32[4]&0x00000010) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] RIF insertion\n",
+ (work32[4]&0x00000020) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] IPv4 checksum generation\n",
+ (work32[4]&0x00000100) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] TCP checksum generation\n",
+ (work32[4]&0x00000200) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] UDP checksum generation\n",
+ (work32[4]&0x00000400) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] RSVP checksum generation\n",
+ (work32[4]&0x00000800) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] ICMP checksum generation\n",
+ (work32[4]&0x00001000) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Loopback enabled\n",
+ (work32[4]&0x00010000) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] Loopback suppression enabled\n",
+ (work32[4]&0x00020000) ? "+" : "-");
spin_unlock(&i2o_proc_lock);
return len;
@@ -2632,15 +2566,25 @@ int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len,
return len;
}
- len += sprintf(buf,"Max size of chain element : %d\n", work32[0]);
- len += sprintf(buf+len, "Max number of buckets : %d\n", work32[1]);
-
- if (d->i2oversion > 0x00) { /* not in 1.5 */
- len += sprintf(buf+len, "RxModes : %d\n", work32[2]);
- len += sprintf(buf+len, "RxMaxBucketsReply : %d\n", work32[3]);
- len += sprintf(buf+len, "RxMaxPacketsPerBuckets : %d\n", work32[4]);
- len += sprintf(buf+len, "RxMaxPostBuckets : %d\n", work32[5]);
- }
+ len += sprintf(buf ,"Rx Max size of chain element : %d\n", work32[0]);
+ len += sprintf(buf+len, "Rx Max Buckets : %d\n", work32[1]);
+ len += sprintf(buf+len, "Rx Max Buckets in Reply : %d\n", work32[3]);
+ len += sprintf(buf+len, "Rx Max Packets in Bucket : %d\n", work32[4]);
+ len += sprintf(buf+len, "Rx Max Buckets in Post : %d\n", work32[5]);
+
+ len += sprintf(buf+len, "Rx Modes : 0x%08x\n", work32[2]);
+ len += sprintf(buf+len, " [%s] FCS reception\n",
+ (work32[2]&0x00000004) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] IPv4 checksum validation \n",
+ (work32[2]&0x00000100) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] TCP checksum validation \n",
+ (work32[2]&0x00000200) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] UDP checksum validation \n",
+ (work32[2]&0x00000400) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] RSVP checksum validation \n",
+ (work32[2]&0x00000800) ? "+" : "-");
+ len += sprintf(buf+len, " [%s] ICMP checksum validation \n",
+ (work32[2]&0x00001000) ? "+" : "-");
spin_unlock(&i2o_proc_lock);
return len;
@@ -3344,14 +3288,6 @@ int __init i2o_proc_init(void)
if(create_i2o_procfs())
return -EBUSY;
- if (i2o_install_handler(&i2o_proc_handler) < 0)
- {
- printk(KERN_ERR "i2o_proc: Unable to install PROC handler.\n");
- return 0;
- }
-
- proc_context = i2o_proc_handler.context;
-
return 0;
}
@@ -3364,6 +3300,5 @@ MODULE_DESCRIPTION("I2O procfs Handler");
void cleanup_module(void)
{
destroy_i2o_procfs();
- i2o_remove_handler(&i2o_proc_handler);
}
#endif