diff options
Diffstat (limited to 'drivers/i2o')
-rw-r--r-- | drivers/i2o/i2o_block.c | 21 | ||||
-rw-r--r-- | drivers/i2o/i2o_config.c | 316 | ||||
-rw-r--r-- | drivers/i2o/i2o_core.c | 630 | ||||
-rw-r--r-- | drivers/i2o/i2o_lan.c | 142 | ||||
-rw-r--r-- | drivers/i2o/i2o_lan.h | 2 | ||||
-rw-r--r-- | drivers/i2o/i2o_proc.c | 367 |
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 |