i2o_block-cleanup.patch for 2.6.6 with request for review
Hello,
Okay, after some time, i now have a new i2o_block patch, which solves several bugs:
- I2O_LOCK was often called with c->unit, which addresses the controller, and not the device (dev->index). This wasn't discovered yet, because each device uses the same queue on the same controller, and there was only one controller.
- the cleanup function for gendisk (del_gendisk) has a bug, if the queue is shared between different devices. To workaround the queue is removed before. Is this okay, because blk_unregister_queue will not be executed.
- redundant code removed in module initialization and remove, use i2ob_new_device and i2ob_del_device instead.
- added all changes from Jens Axboe (also removed the atomic, which is not needed, because the spinlock is already held, i think).
The patch is as always also available at http://i2o.shadowconnect.com/i2o_block-cleanup.patch
Thank you for your help...
Best regards,
Markus Lidel
------------------------------------------
Markus Lidel (Senior IT Consultant)
Shadow Connect GmbH
Carl-Reisch-Weg 12
D-86381 Krumbach
Germany
Phone: +49 82 82/99 51-0 Fax: +49 82 82/99 51-11
E-Mail: [email protected] URL: http://www.shadowconnect.com
drivers/message/i2o/i2o_block.c +165 -217
@@ -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" );