[PATCH 3/5] I2O subsystem fixing and cleanup for 2.6 - i2o_block-cleanup.patch

From: Markus Lidel
Date: Thu Apr 29 2004 - 15:35:34 EST


--- a/drivers/message/i2o/i2o_block.c 2004-04-03 17:37:37.000000000 -1000
+++ b/drivers/message/i2o/i2o_block.c 2004-04-23 02:13:24.132931000 -1000
@@ -83,7 +83,6 @@
#include <asm/semaphore.h>
#include <linux/completion.h>
#include <asm/io.h>
-#include <asm/atomic.h>
#include <linux/smp_lock.h>
#include <linux/wait.h>

@@ -111,16 +110,12 @@
I2O_EVT_IND_BSA_SCSI_SMART )


-#define I2O_LOCK(unit) (i2ob_dev[(unit)].req_queue->queue_lock)
-
/*
* Some of these can be made smaller later
*/

-static int i2ob_media_change_flag[MAX_I2OB];
-static u32 i2ob_max_sectors[MAX_I2OB<<4];
-
static int i2ob_context;
+static struct block_device_operations i2ob_fops;

/*
* I2O Block device descriptor
@@ -143,6 +138,9 @@
int wcache;
int power;
int index;
+ int media_change_flag;
+ u32 max_sectors;
+ struct gendisk *gd;
};

/*
@@ -162,16 +160,16 @@
};

/*
- * Per IOP requst queue information
+ * Per IOP request queue information
*
- * We have a separate requeust_queue_t per IOP so that a heavilly
+ * We have a separate request_queue_t per IOP so that a heavilly
* loaded I2O block device on an IOP does not starve block devices
* across all I2O controllers.
*
*/
struct i2ob_iop_queue
{
- atomic_t queue_depth;
+ unsigned int queue_depth;
struct i2ob_request request_queue[MAX_I2OB_DEPTH];
struct i2ob_request *i2ob_qhead;
request_queue_t *req_queue;
@@ -183,9 +181,8 @@
* Each I2O disk is one of these.
*/

-static struct i2ob_device i2ob_dev[MAX_I2OB<<4];
+static struct i2ob_device i2ob_dev[MAX_I2OB];
static int i2ob_dev_count = 0;
-static struct gendisk *i2ob_disk[MAX_I2OB];

/*
* Mutex and spin lock for event handling synchronization
@@ -312,7 +309,6 @@
/*
* Mask out partitions from now on
*/
- unit &= 0xF0;

/* This can be optimised later - just want to be sure its right for
starters */
@@ -402,7 +398,7 @@
}

i2o_post_message(c,m);
- atomic_inc(&i2ob_queues[c->unit]->queue_depth);
+ i2ob_queues[c->unit]->queue_depth ++;

return 0;
}
@@ -453,8 +449,8 @@
struct i2ob_request *ireq = NULL;
u8 st;
u32 *m = (u32 *)msg;
- u8 unit = (m[2]>>8)&0xF0; /* low 4 bits are partition */
- struct i2ob_device *dev = &i2ob_dev[(unit&0xF0)];
+ u8 unit = m[2]>>8;
+ struct i2ob_device *dev = &i2ob_dev[unit];

/*
* FAILed message
@@ -475,10 +471,10 @@
ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
ireq->req->errors++;

- spin_lock_irqsave(I2O_LOCK(c->unit), flags);
+ spin_lock_irqsave(dev->req_queue->queue_lock, flags);
i2ob_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req);
- spin_unlock_irqrestore(I2O_LOCK(c->unit), flags);
+ spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);

/* Now flush the message by making it a NOP */
m[0]&=0x00FFFFFF;
@@ -509,10 +505,10 @@
ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
ireq->req->errors++;
printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n");
- spin_lock_irqsave(I2O_LOCK(c->unit), flags);
+ spin_lock_irqsave(dev->req_queue->queue_lock, flags);
i2ob_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req);
- spin_unlock_irqrestore(I2O_LOCK(c->unit), flags);
+ spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
return;
}

@@ -576,17 +572,17 @@
*/

i2ob_free_sglist(dev, ireq);
- spin_lock_irqsave(I2O_LOCK(c->unit), flags);
+ spin_lock_irqsave(dev->req_queue->queue_lock, flags);
i2ob_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req);
- atomic_dec(&i2ob_queues[c->unit]->queue_depth);
+ i2ob_queues[c->unit]->queue_depth --;

/*
* We may be able to do more I/O
*/

- i2ob_request(dev->req_queue);
- spin_unlock_irqrestore(I2O_LOCK(c->unit), flags);
+ i2ob_request(dev->gd->queue);
+ spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
}

/*
@@ -598,8 +594,8 @@
{
unsigned int evt;
unsigned long flags;
+ struct i2ob_device *dev;
int unit;
- int i;
//The only event that has data is the SCSI_SMART event.
struct i2o_reply {
u32 header[4];
@@ -638,6 +634,7 @@
unit = le32_to_cpu(evt_local->header[3]);
evt = le32_to_cpu(evt_local->evt_indicator);

+ dev = &i2ob_dev[unit];
switch(evt)
{
/*
@@ -648,10 +645,9 @@
*/
case I2O_EVT_IND_BSA_VOLUME_LOAD:
{
- struct gendisk *p = i2ob_disk[unit>>4];
- i2ob_install_device(i2ob_dev[unit].i2odev->controller,
- i2ob_dev[unit].i2odev, unit);
- add_disk(p);
+ i2ob_install_device(dev->i2odev->controller,
+ dev->i2odev, unit);
+ add_disk(dev->gd);
break;
}

@@ -663,17 +659,18 @@
*/
case I2O_EVT_IND_BSA_VOLUME_UNLOAD:
{
- struct gendisk *p = i2ob_disk[unit>>4];
+ struct gendisk *p = dev->gd;
+ blk_queue_max_sectors(dev->gd->queue, 0);
del_gendisk(p);
- for(i = unit; i <= unit+15; i++)
- blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
- i2ob_media_change_flag[unit] = 1;
+ put_disk(p);
+ dev->gd = NULL;
+ dev->media_change_flag = 1;
break;
}

case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:
printk(KERN_WARNING "%s: Attempt to eject locked media\n",
- i2ob_dev[unit].i2odev->dev_name);
+ dev->i2odev->dev_name);
break;

/*
@@ -691,12 +688,12 @@
{
u64 size;

- if(i2ob_query_device(&i2ob_dev[unit], 0x0004, 0, &size, 8) !=0 )
- i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8);
+ if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )
+ i2ob_query_device(dev, 0x0000, 4, &size, 8);

- spin_lock_irqsave(I2O_LOCK(unit), flags);
- set_capacity(i2ob_disk[unit>>4], size>>9);
- spin_unlock_irqrestore(I2O_LOCK(unit), flags);
+ spin_lock_irqsave(dev->req_queue->queue_lock, flags);
+ set_capacity(dev->gd, size>>9);
+ spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
break;
}

@@ -708,7 +705,7 @@
case I2O_EVT_IND_BSA_SCSI_SMART:
{
char buf[16];
- printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",i2ob_dev[unit].i2odev->dev_name);
+ printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",dev->i2odev->dev_name);
evt_local->data[16]='\0';
sprintf(buf,"%s",&evt_local->data[0]);
printk(KERN_INFO " Disk Serial#:%s\n",buf);
@@ -735,12 +732,12 @@
* hit the fan big time. The card seems to recover but loses
* the pending writes. Deeply ungood except for testing fsck
*/
- if(i2ob_dev[unit].i2odev->controller->promise)
+ if(dev->i2odev->controller->promise)
panic("I2O controller firmware failed. Reboot and force a filesystem check.\n");
default:
printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n"
KERN_INFO " Blame the I2O card manufacturer 8)\n",
- i2ob_dev[unit].i2odev->dev_name, evt);
+ dev->i2odev->dev_name, evt);
break;
}
};
@@ -765,14 +762,6 @@
u32 m;

while ((req = elv_next_request(q)) != NULL) {
- /*
- * On an IRQ completion if there is an inactive
- * request on the queue head it means it isnt yet
- * ready to dispatch.
- */
- if(req->rq_status == RQ_INACTIVE)
- return;
-
dev = req->rq_disk->private_data;

/*
@@ -780,7 +769,7 @@
* generic IOP commit control. Certainly it's not right
* its global!
*/
- if(atomic_read(&i2ob_queues[dev->unit]->queue_depth) >= dev->depth)
+ if(i2ob_queues[dev->unit]->queue_depth >= dev->depth)
break;

/* Get a message */
@@ -788,7 +777,7 @@

if(m==0xFFFFFFFF)
{
- if(atomic_read(&i2ob_queues[dev->unit]->queue_depth) == 0)
+ if(i2ob_queues[dev->unit]->queue_depth == 0)
printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n");
break;
}
@@ -797,13 +786,12 @@
*/
req->errors = 0;
blkdev_dequeue_request(req);
- req->waiting = NULL;

ireq = i2ob_queues[dev->unit]->i2ob_qhead;
i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
ireq->req = req;

- i2ob_send(m, dev, ireq, (dev->unit&0xF0));
+ i2ob_send(m, dev, ireq, dev->index);
}
}

@@ -1065,7 +1053,10 @@
u16 power;
u32 flags, status;
struct i2ob_device *dev=&i2ob_dev[unit];
- int i;
+ struct gendisk *disk;
+ request_queue_t *q;
+ int segments;
+

/*
* For logging purposes...
@@ -1079,21 +1070,35 @@
* before any I/O can be performed. If it fails, this
* device is useless.
*/
- if(!i2ob_queues[unit]) {
- if(i2ob_init_iop(unit))
+ if(!i2ob_queues[c->unit]) {
+ if(i2ob_init_iop(c->unit))
return 1;
}

+ q = i2ob_queues[c->unit]->req_queue;
+
/*
* This will save one level of lookup/indirection in critical
* code so that we can directly get the queue ptr from the
* device instead of having to go the IOP data structure.
*/
- dev->req_queue = i2ob_queues[unit]->req_queue;
+ dev->req_queue = q;

+ /*
+ * Allocate a gendisk structure and initialize it
+ */
+ disk = alloc_disk(16);
+ if (!disk)
+ return 1;
+
+ dev->gd = disk;
/* initialize gendik structure */
- i2ob_disk[unit>>4]->private_data = dev;
- i2ob_disk[unit>>4]->queue = dev->req_queue;
+ disk->major = MAJOR_NR;
+ disk->first_minor = unit<<4;
+ disk->queue = q;
+ disk->fops = &i2ob_fops;
+ sprintf(disk->disk_name, "i2o/hd%c", 'a' + unit);
+ disk->private_data = dev;

/*
* Ask for the current media data. If that isn't supported
@@ -1110,53 +1115,49 @@
power = 0;
i2ob_query_device(dev, 0x0000, 5, &flags, 4);
i2ob_query_device(dev, 0x0000, 6, &status, 4);
- set_capacity(i2ob_disk[unit>>4], size>>9);
+ set_capacity(disk, size>>9);

/*
* Max number of Scatter-Gather Elements
*/

- i2ob_dev[unit].power = power; /* Save power state in device proper */
- i2ob_dev[unit].flags = flags;
+ dev->power = power; /* Save power state in device proper */
+ dev->flags = flags;

- for(i=unit;i<=unit+15;i++)
- {
- request_queue_t *q = i2ob_dev[unit].req_queue;
- int segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
+ segments = (d->controller->status_block->inbound_frame_size - 7) / 2;

- if(segments > 16)
- segments = 16;
-
- i2ob_dev[i].power = power; /* Save power state */
- i2ob_dev[unit].flags = flags; /* Keep the type info */
+ if(segments > 16)
+ segments = 16;
+
+ dev->power = power; /* Save power state */
+ dev->flags = flags; /* Keep the type info */

- blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers
+ blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers
explode on 65536 or higher */
- blk_queue_max_phys_segments(q, segments);
- blk_queue_max_hw_segments(q, segments);
+ blk_queue_max_phys_segments(q, segments);
+ blk_queue_max_hw_segments(q, segments);

- i2ob_dev[i].rcache = CACHE_SMARTFETCH;
- i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
+ dev->rcache = CACHE_SMARTFETCH;
+ dev->wcache = CACHE_WRITETHROUGH;

- if(d->controller->battery == 0)
- i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
+ if(d->controller->battery == 0)
+ dev->wcache = CACHE_WRITETHROUGH;

- if(d->controller->promise)
- i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
+ if(d->controller->promise)
+ dev->wcache = CACHE_WRITETHROUGH;

- if(d->controller->short_req)
- {
- blk_queue_max_sectors(q, 8);
- blk_queue_max_phys_segments(q, 8);
- blk_queue_max_hw_segments(q, 8);
- }
+ if(d->controller->short_req)
+ {
+ blk_queue_max_sectors(q, 8);
+ blk_queue_max_phys_segments(q, 8);
+ blk_queue_max_hw_segments(q, 8);
}

- strcpy(d->dev_name, i2ob_disk[unit>>4]->disk_name);
- strcpy(i2ob_disk[unit>>4]->devfs_name, i2ob_disk[unit>>4]->disk_name);
+ strcpy(d->dev_name, disk->disk_name);
+ strcpy(disk->devfs_name, disk->disk_name);

printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n",
- d->dev_name, i2ob_dev[unit].max_segments, i2ob_dev[unit].depth, i2ob_max_sectors[unit]<<9);
+ d->dev_name, dev->max_segments, dev->depth, dev->max_sectors<<9);

i2ob_query_device(dev, 0x0000, 0, &type, 1);

@@ -1197,7 +1198,7 @@
}
printk(".\n");
printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n",
- d->dev_name, i2ob_max_sectors[unit]);
+ d->dev_name, dev->max_sectors);

/*
* Register for the events we're interested in and that the
@@ -1233,7 +1234,7 @@
/* Queue is MAX_I2OB + 1... */
i2ob_queues[unit]->request_queue[i].next = NULL;
i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0];
- atomic_set(&i2ob_queues[unit]->queue_depth, 0);
+ i2ob_queues[unit]->queue_depth = 0;

i2ob_queues[unit]->lock = SPIN_LOCK_UNLOCKED;
i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock);
@@ -1257,7 +1258,6 @@

struct i2o_device *d, *b=NULL;
struct i2o_controller *c;
- struct i2ob_device *dev;

for(i=0; i< MAX_I2O_CONTROLLERS; i++)
{
@@ -1313,44 +1313,12 @@
continue; /*Already claimed on pass 1 */
}

- if(i2o_claim_device(d, &i2o_block_handler))
- {
- printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit,
- d->lct_data.tid);
- printk(KERN_WARNING "\t%sevice refused claim! Skipping installation\n", bios?"Boot d":"D");
- continue;
- }
-
- i2o_release_device(d, &i2o_block_handler);
-
- if(scan_unit<MAX_I2OB<<4)
- {
- /*
- * Get the device and fill in the
- * Tid and controller.
- */
- dev=&i2ob_dev[scan_unit];
- dev->i2odev = d;
- dev->controller = c;
- dev->unit = c->unit;
- dev->tid = d->lct_data.tid;
-
- if(i2ob_install_device(c,d,scan_unit))
- printk(KERN_WARNING "Could not install I2O block device\n");
- else
- {
- add_disk(i2ob_disk[scan_unit>>4]);
- scan_unit+=16;
- i2ob_dev_count++;
-
- /* We want to know when device goes away */
- i2o_device_notify_on(d, &i2o_block_handler);
- }
- }
+ if(scan_unit<MAX_I2OB)
+ i2ob_new_device(c, d);
else
{
if(!warned++)
- printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit>>4);
+ printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit);
}
}
i2o_unlock_controller(c);
@@ -1399,12 +1367,12 @@
printk(KERN_INFO " Controller %d Tid %d\n",c->unit, d->lct_data.tid);

/* Check for available space */
- if(i2ob_dev_count>=MAX_I2OB<<4)
+ if(i2ob_dev_count>=MAX_I2OB)
{
printk(KERN_ERR "i2o_block: No more devices allowed!\n");
return;
}
- for(unit = 0; unit < (MAX_I2OB<<4); unit += 16)
+ for(unit = 0; unit < MAX_I2OB; unit ++)
{
if(!i2ob_dev[unit].i2odev)
break;
@@ -1420,18 +1388,20 @@
dev->i2odev = d;
dev->controller = c;
dev->tid = d->lct_data.tid;
+ dev->unit = c->unit;

- if(i2ob_install_device(c,d,unit))
+ if(i2ob_install_device(c,d,unit)) {
+ i2o_release_device(d, &i2o_block_handler);
printk(KERN_ERR "i2o_block: Could not install new device\n");
+ }
else
{
- add_disk(i2ob_disk[unit>>4]);
+ i2o_release_device(d, &i2o_block_handler);
+ add_disk(dev->gd);
i2ob_dev_count++;
i2o_device_notify_on(d, &i2o_block_handler);
}

- i2o_release_device(d, &i2o_block_handler);
-
return;
}

@@ -1443,64 +1413,58 @@
void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
{
int unit = 0;
- int i = 0;
unsigned long flags;
+ struct i2ob_device *dev;

- spin_lock_irqsave(I2O_LOCK(c->unit), flags);
-
- /*
- * Need to do this...we somtimes get two events from the IRTOS
- * in a row and that causes lots of problems.
- */
- i2o_device_notify_off(d, &i2o_block_handler);
-
- printk(KERN_INFO "I2O Block Device Deleted\n");
-
- for(unit = 0; unit < MAX_I2OB<<4; unit += 16)
+ for(unit = 0; unit < MAX_I2OB; unit ++)
{
- if(i2ob_dev[unit].i2odev == d)
+ dev = &i2ob_dev[unit];
+ if(dev->i2odev == d)
{
printk(KERN_INFO " /dev/%s: Controller %d Tid %d\n",
d->dev_name, c->unit, d->lct_data.tid);
break;
}
}
- if(unit >= MAX_I2OB<<4)
+
+ printk(KERN_INFO "I2O Block Device Deleted\n");
+
+ if(unit >= MAX_I2OB)
{
printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
- spin_unlock_irqrestore(I2O_LOCK(c->unit), flags);
return;
}

+ spin_lock_irqsave(dev->req_queue->queue_lock, flags);
+
+ /*
+ * Need to do this...we somtimes get two events from the IRTOS
+ * in a row and that causes lots of problems.
+ */
+ i2o_device_notify_off(d, &i2o_block_handler);
+
/*
* This will force errors when i2ob_get_queue() is called
* by the kenrel.
*/
- del_gendisk(i2ob_disk[unit>>4]);
- i2ob_dev[unit].req_queue = NULL;
- for(i = unit; i <= unit+15; i++)
- {
- i2ob_dev[i].i2odev = NULL;
- blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
- }
- spin_unlock_irqrestore(I2O_LOCK(c->unit), flags);
-
- /*
- * Decrease usage count for module
- */
-
- while(i2ob_dev[unit].refcnt--)
- MOD_DEC_USE_COUNT;
-
- i2ob_dev[unit].refcnt = 0;
-
- i2ob_dev[i].tid = 0;
+ if(dev->gd) {
+ struct gendisk *gd = dev->gd;
+ gd->queue = NULL;
+ del_gendisk(gd);
+ put_disk(gd);
+ dev->gd = NULL;
+ }
+ spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
+ dev->req_queue = NULL;
+ dev->i2odev = NULL;
+ dev->refcnt = 0;
+ dev->tid = 0;

/*
* Do we need this?
* The media didn't really change...the device is just gone
*/
- i2ob_media_change_flag[unit] = 1;
+ dev->media_change_flag = 1;

i2ob_dev_count--;
}
@@ -1511,10 +1475,9 @@
static int i2ob_media_change(struct gendisk *disk)
{
struct i2ob_device *p = disk->private_data;
- int i = p->index;
- if(i2ob_media_change_flag[i])
+ if(p->media_change_flag)
{
- i2ob_media_change_flag[i]=0;
+ p->media_change_flag=0;
return 1;
}
return 0;
@@ -1523,7 +1486,7 @@
static int i2ob_revalidate(struct gendisk *disk)
{
struct i2ob_device *p = disk->private_data;
- return i2ob_install_device(p->controller, p->i2odev, p->index<<4);
+ return i2ob_install_device(p->controller, p->i2odev, p->index);
}

/*
@@ -1536,7 +1499,7 @@

for(i=0;i<MAX_I2OB;i++)
{
- struct i2ob_device *dev=&i2ob_dev[(i<<4)];
+ struct i2ob_device *dev=&i2ob_dev[i];

if(dev->refcnt!=0)
{
@@ -1598,51 +1561,36 @@
if (register_blkdev(MAJOR_NR, "i2o_block"))
return -EIO;

- for (i = 0; i < MAX_I2OB; i++) {
- struct gendisk *disk = alloc_disk(16);
- if (!disk)
- goto oom;
- i2ob_dev[i<<4].index = i;
- disk->queue = i2ob_dev[i<<4].req_queue;
- i2ob_disk[i] = disk;
- }
#ifdef MODULE
printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);
#endif

/*
+ * Set up the queue
+ */
+ for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
+ i2ob_queues[i] = NULL;
+
+ /*
* Now fill in the boiler plate
*/

- for (i = 0; i < MAX_I2OB << 4; i++) {
- i2ob_dev[i].refcnt = 0;
- i2ob_dev[i].flags = 0;
- i2ob_dev[i].controller = NULL;
- i2ob_dev[i].i2odev = NULL;
- i2ob_dev[i].tid = 0;
- i2ob_dev[i].head = NULL;
- i2ob_dev[i].tail = NULL;
- i2ob_dev[i].depth = MAX_I2OB_DEPTH;
- i2ob_max_sectors[i] = 2;
- }
-
for (i = 0; i < MAX_I2OB; i++) {
- struct gendisk *disk = i2ob_disk[i];
- disk->major = MAJOR_NR;
- disk->first_minor = i<<4;
- disk->fops = &i2ob_fops;
- sprintf(disk->disk_name, "i2o/hd%c", 'a' + i);
+ struct i2ob_device *dev = &i2ob_dev[i];
+ dev->index = i;
+ dev->refcnt = 0;
+ dev->flags = 0;
+ dev->controller = NULL;
+ dev->i2odev = NULL;
+ dev->tid = 0;
+ dev->head = NULL;
+ dev->tail = NULL;
+ dev->depth = MAX_I2OB_DEPTH;
+ dev->max_sectors = 2;
+ dev->gd = NULL;
}

/*
- * Set up the queue
- */
- for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
- {
- i2ob_queues[i] = NULL;
- }
-
- /*
* Register the OSM handler as we will need this to probe for
* drives, geometry and other goodies.
*/
@@ -1671,9 +1619,6 @@

return 0;

-oom:
- while (i--)
- put_disk(i2ob_disk[i]);
unregister_blkdev(MAJOR_NR, "i2o_block");
return -ENOMEM;
}
@@ -1701,11 +1646,8 @@
if(i2ob_dev_count) {
struct i2o_device *d;
for(i = 0; i < MAX_I2OB; i++)
- if((d=i2ob_dev[i<<4].i2odev)) {
- i2o_device_notify_off(d, &i2o_block_handler);
- i2o_event_register(d->controller, d->lct_data.tid,
- i2ob_context, i<<4, 0);
- }
+ if((d = i2ob_dev[i].i2odev))
+ i2ob_del_device(d->controller, d);
}

/*
@@ -1725,15 +1667,21 @@
*/

i2o_remove_handler(&i2o_block_handler);
-
- for (i = 0; i < MAX_I2OB; i++)
- put_disk(i2ob_disk[i]);

/*
* Return the block device
*/
if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0)
printk("i2o_block: cleanup_module failed\n");
+
+ /*
+ * release request queue
+ */
+ for (i = 0; i < MAX_I2O_CONTROLLERS; i ++)
+ if(i2ob_queues[i]) {
+ blk_cleanup_queue(i2ob_queues[i]->req_queue);
+ kfree(i2ob_queues[i]);
+ }
}

MODULE_AUTHOR("Red Hat");