Commit 96005e5a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

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

From: Markus Lidel <Markus.Lidel@shadowconnect.com>

* more than 3 "visible" disks (hda, hdb, hdc, hdd) lead to kernel panics.

* removes some unused code with partitions.

* I2O_LOCK was often called with the addresses of the controller, and not
  with the address of the device.  Fixed.

* the cleanup function for gendisk (del_gendisk) doesn't work if the queue
  is shared between different devices.  To workaround the queue is removed
  before.

* redundant code removed in module initialization and remove, use
  i2ob_new_device and i2ob_del_device instead.

* removed atomic_t queue_depth

* removed unnecessary and bogus code for queue handling
parent a94a0bb4
...@@ -83,7 +83,6 @@ ...@@ -83,7 +83,6 @@
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/atomic.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -111,16 +110,12 @@ ...@@ -111,16 +110,12 @@
I2O_EVT_IND_BSA_SCSI_SMART ) 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 * 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 int i2ob_context;
static struct block_device_operations i2ob_fops;
/* /*
* I2O Block device descriptor * I2O Block device descriptor
...@@ -143,6 +138,9 @@ struct i2ob_device ...@@ -143,6 +138,9 @@ struct i2ob_device
int wcache; int wcache;
int power; int power;
int index; int index;
int media_change_flag;
u32 max_sectors;
struct gendisk *gd;
}; };
/* /*
...@@ -162,16 +160,16 @@ struct i2ob_request ...@@ -162,16 +160,16 @@ struct i2ob_request
}; };
/* /*
* 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 * loaded I2O block device on an IOP does not starve block devices
* across all I2O controllers. * across all I2O controllers.
* *
*/ */
struct i2ob_iop_queue struct i2ob_iop_queue
{ {
atomic_t queue_depth; unsigned int queue_depth;
struct i2ob_request request_queue[MAX_I2OB_DEPTH]; struct i2ob_request request_queue[MAX_I2OB_DEPTH];
struct i2ob_request *i2ob_qhead; struct i2ob_request *i2ob_qhead;
request_queue_t *req_queue; request_queue_t *req_queue;
...@@ -183,9 +181,8 @@ static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS]; ...@@ -183,9 +181,8 @@ static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS];
* Each I2O disk is one of these. * 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 int i2ob_dev_count = 0;
static struct gendisk *i2ob_disk[MAX_I2OB];
/* /*
* Mutex and spin lock for event handling synchronization * Mutex and spin lock for event handling synchronization
...@@ -312,7 +309,6 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, ...@@ -312,7 +309,6 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
/* /*
* Mask out partitions from now on * Mask out partitions from now on
*/ */
unit &= 0xF0;
/* This can be optimised later - just want to be sure its right for /* This can be optimised later - just want to be sure its right for
starters */ starters */
...@@ -402,7 +398,7 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, ...@@ -402,7 +398,7 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
} }
i2o_post_message(c,m); i2o_post_message(c,m);
atomic_inc(&i2ob_queues[c->unit]->queue_depth); i2ob_queues[c->unit]->queue_depth ++;
return 0; return 0;
} }
...@@ -453,8 +449,8 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str ...@@ -453,8 +449,8 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
struct i2ob_request *ireq = NULL; struct i2ob_request *ireq = NULL;
u8 st; u8 st;
u32 *m = (u32 *)msg; u32 *m = (u32 *)msg;
u8 unit = (m[2]>>8)&0xF0; /* low 4 bits are partition */ u8 unit = m[2]>>8;
struct i2ob_device *dev = &i2ob_dev[(unit&0xF0)]; struct i2ob_device *dev = &i2ob_dev[unit];
/* /*
* FAILed message * FAILed message
...@@ -475,10 +471,10 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str ...@@ -475,10 +471,10 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
ireq->req->errors++; 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_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req); 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 */ /* Now flush the message by making it a NOP */
m[0]&=0x00FFFFFF; m[0]&=0x00FFFFFF;
...@@ -509,10 +505,10 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str ...@@ -509,10 +505,10 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
ireq->req->errors++; ireq->req->errors++;
printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n"); 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_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req); i2ob_end_request(ireq->req);
spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
return; return;
} }
...@@ -576,17 +572,17 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str ...@@ -576,17 +572,17 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
*/ */
i2ob_free_sglist(dev, ireq); 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_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req); 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 * We may be able to do more I/O
*/ */
i2ob_request(dev->req_queue); i2ob_request(dev->gd->queue);
spin_unlock_irqrestore(I2O_LOCK(c->unit), flags); spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
} }
/* /*
...@@ -598,8 +594,8 @@ static int i2ob_evt(void *dummy) ...@@ -598,8 +594,8 @@ static int i2ob_evt(void *dummy)
{ {
unsigned int evt; unsigned int evt;
unsigned long flags; unsigned long flags;
struct i2ob_device *dev;
int unit; int unit;
int i;
//The only event that has data is the SCSI_SMART event. //The only event that has data is the SCSI_SMART event.
struct i2o_reply { struct i2o_reply {
u32 header[4]; u32 header[4];
...@@ -638,6 +634,7 @@ static int i2ob_evt(void *dummy) ...@@ -638,6 +634,7 @@ static int i2ob_evt(void *dummy)
unit = le32_to_cpu(evt_local->header[3]); unit = le32_to_cpu(evt_local->header[3]);
evt = le32_to_cpu(evt_local->evt_indicator); evt = le32_to_cpu(evt_local->evt_indicator);
dev = &i2ob_dev[unit];
switch(evt) switch(evt)
{ {
/* /*
...@@ -648,10 +645,9 @@ static int i2ob_evt(void *dummy) ...@@ -648,10 +645,9 @@ static int i2ob_evt(void *dummy)
*/ */
case I2O_EVT_IND_BSA_VOLUME_LOAD: case I2O_EVT_IND_BSA_VOLUME_LOAD:
{ {
struct gendisk *p = i2ob_disk[unit>>4]; i2ob_install_device(dev->i2odev->controller,
i2ob_install_device(i2ob_dev[unit].i2odev->controller, dev->i2odev, unit);
i2ob_dev[unit].i2odev, unit); add_disk(dev->gd);
add_disk(p);
break; break;
} }
...@@ -663,17 +659,18 @@ static int i2ob_evt(void *dummy) ...@@ -663,17 +659,18 @@ static int i2ob_evt(void *dummy)
*/ */
case I2O_EVT_IND_BSA_VOLUME_UNLOAD: 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); del_gendisk(p);
for(i = unit; i <= unit+15; i++) put_disk(p);
blk_queue_max_sectors(i2ob_dev[i].req_queue, 0); dev->gd = NULL;
i2ob_media_change_flag[unit] = 1; dev->media_change_flag = 1;
break; break;
} }
case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ: case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:
printk(KERN_WARNING "%s: Attempt to eject locked media\n", printk(KERN_WARNING "%s: Attempt to eject locked media\n",
i2ob_dev[unit].i2odev->dev_name); dev->i2odev->dev_name);
break; break;
/* /*
...@@ -691,12 +688,12 @@ static int i2ob_evt(void *dummy) ...@@ -691,12 +688,12 @@ static int i2ob_evt(void *dummy)
{ {
u64 size; u64 size;
if(i2ob_query_device(&i2ob_dev[unit], 0x0004, 0, &size, 8) !=0 ) if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )
i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8); i2ob_query_device(dev, 0x0000, 4, &size, 8);
spin_lock_irqsave(I2O_LOCK(unit), flags); spin_lock_irqsave(dev->req_queue->queue_lock, flags);
set_capacity(i2ob_disk[unit>>4], size>>9); set_capacity(dev->gd, size>>9);
spin_unlock_irqrestore(I2O_LOCK(unit), flags); spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
break; break;
} }
...@@ -708,7 +705,7 @@ static int i2ob_evt(void *dummy) ...@@ -708,7 +705,7 @@ static int i2ob_evt(void *dummy)
case I2O_EVT_IND_BSA_SCSI_SMART: case I2O_EVT_IND_BSA_SCSI_SMART:
{ {
char buf[16]; 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'; evt_local->data[16]='\0';
sprintf(buf,"%s",&evt_local->data[0]); sprintf(buf,"%s",&evt_local->data[0]);
printk(KERN_INFO " Disk Serial#:%s\n",buf); printk(KERN_INFO " Disk Serial#:%s\n",buf);
...@@ -735,12 +732,12 @@ static int i2ob_evt(void *dummy) ...@@ -735,12 +732,12 @@ static int i2ob_evt(void *dummy)
* hit the fan big time. The card seems to recover but loses * hit the fan big time. The card seems to recover but loses
* the pending writes. Deeply ungood except for testing fsck * 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"); panic("I2O controller firmware failed. Reboot and force a filesystem check.\n");
default: default:
printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n" printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n"
KERN_INFO " Blame the I2O card manufacturer 8)\n", KERN_INFO " Blame the I2O card manufacturer 8)\n",
i2ob_dev[unit].i2odev->dev_name, evt); dev->i2odev->dev_name, evt);
break; break;
} }
}; };
...@@ -765,14 +762,6 @@ static void i2ob_request(request_queue_t *q) ...@@ -765,14 +762,6 @@ static void i2ob_request(request_queue_t *q)
u32 m; u32 m;
while ((req = elv_next_request(q)) != NULL) { 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; dev = req->rq_disk->private_data;
/* /*
...@@ -780,7 +769,7 @@ static void i2ob_request(request_queue_t *q) ...@@ -780,7 +769,7 @@ static void i2ob_request(request_queue_t *q)
* generic IOP commit control. Certainly it's not right * generic IOP commit control. Certainly it's not right
* its global! * its global!
*/ */
if(atomic_read(&i2ob_queues[dev->unit]->queue_depth) >= dev->depth) if(i2ob_queues[dev->unit]->queue_depth >= dev->depth)
break; break;
/* Get a message */ /* Get a message */
...@@ -788,7 +777,7 @@ static void i2ob_request(request_queue_t *q) ...@@ -788,7 +777,7 @@ static void i2ob_request(request_queue_t *q)
if(m==0xFFFFFFFF) 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"); printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n");
break; break;
} }
...@@ -797,13 +786,12 @@ static void i2ob_request(request_queue_t *q) ...@@ -797,13 +786,12 @@ static void i2ob_request(request_queue_t *q)
*/ */
req->errors = 0; req->errors = 0;
blkdev_dequeue_request(req); blkdev_dequeue_request(req);
req->waiting = NULL;
ireq = i2ob_queues[dev->unit]->i2ob_qhead; ireq = i2ob_queues[dev->unit]->i2ob_qhead;
i2ob_queues[dev->unit]->i2ob_qhead = ireq->next; i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
ireq->req = req; ireq->req = req;
i2ob_send(m, dev, ireq, (dev->unit&0xF0)); i2ob_send(m, dev, ireq, dev->index);
} }
} }
...@@ -1065,7 +1053,10 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1065,7 +1053,10 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
u16 power; u16 power;
u32 flags, status; u32 flags, status;
struct i2ob_device *dev=&i2ob_dev[unit]; struct i2ob_device *dev=&i2ob_dev[unit];
int i; struct gendisk *disk;
request_queue_t *q;
int segments;
/* /*
* For logging purposes... * For logging purposes...
...@@ -1079,21 +1070,35 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1079,21 +1070,35 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
* before any I/O can be performed. If it fails, this * before any I/O can be performed. If it fails, this
* device is useless. * device is useless.
*/ */
if(!i2ob_queues[unit]) { if(!i2ob_queues[c->unit]) {
if(i2ob_init_iop(unit)) if(i2ob_init_iop(c->unit))
return 1; return 1;
} }
q = i2ob_queues[c->unit]->req_queue;
/* /*
* This will save one level of lookup/indirection in critical * This will save one level of lookup/indirection in critical
* code so that we can directly get the queue ptr from the * code so that we can directly get the queue ptr from the
* device instead of having to go the IOP data structure. * 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 */ /* initialize gendik structure */
i2ob_disk[unit>>4]->private_data = dev; disk->major = MAJOR_NR;
i2ob_disk[unit>>4]->queue = dev->req_queue; 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 * Ask for the current media data. If that isn't supported
...@@ -1110,39 +1115,36 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1110,39 +1115,36 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
power = 0; power = 0;
i2ob_query_device(dev, 0x0000, 5, &flags, 4); i2ob_query_device(dev, 0x0000, 5, &flags, 4);
i2ob_query_device(dev, 0x0000, 6, &status, 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 * Max number of Scatter-Gather Elements
*/ */
i2ob_dev[unit].power = power; /* Save power state in device proper */ dev->power = power; /* Save power state in device proper */
i2ob_dev[unit].flags = flags; dev->flags = flags;
for(i=unit;i<=unit+15;i++) segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
{
request_queue_t *q = i2ob_dev[unit].req_queue;
int segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
if(segments > 16) if(segments > 16)
segments = 16; segments = 16;
i2ob_dev[i].power = power; /* Save power state */ dev->power = power; /* Save power state */
i2ob_dev[unit].flags = flags; /* Keep the type info */ 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 */ explode on 65536 or higher */
blk_queue_max_phys_segments(q, segments); blk_queue_max_phys_segments(q, segments);
blk_queue_max_hw_segments(q, segments); blk_queue_max_hw_segments(q, segments);
i2ob_dev[i].rcache = CACHE_SMARTFETCH; dev->rcache = CACHE_SMARTFETCH;
i2ob_dev[i].wcache = CACHE_WRITETHROUGH; dev->wcache = CACHE_WRITETHROUGH;
if(d->controller->battery == 0) if(d->controller->battery == 0)
i2ob_dev[i].wcache = CACHE_WRITETHROUGH; dev->wcache = CACHE_WRITETHROUGH;
if(d->controller->promise) if(d->controller->promise)
i2ob_dev[i].wcache = CACHE_WRITETHROUGH; dev->wcache = CACHE_WRITETHROUGH;
if(d->controller->short_req) if(d->controller->short_req)
{ {
...@@ -1150,13 +1152,12 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1150,13 +1152,12 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
blk_queue_max_phys_segments(q, 8); blk_queue_max_phys_segments(q, 8);
blk_queue_max_hw_segments(q, 8); blk_queue_max_hw_segments(q, 8);
} }
}
strcpy(d->dev_name, i2ob_disk[unit>>4]->disk_name); strcpy(d->dev_name, disk->disk_name);
strcpy(i2ob_disk[unit>>4]->devfs_name, i2ob_disk[unit>>4]->disk_name); strcpy(disk->devfs_name, disk->disk_name);
printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n", 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); i2ob_query_device(dev, 0x0000, 0, &type, 1);
...@@ -1197,7 +1198,7 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1197,7 +1198,7 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
} }
printk(".\n"); printk(".\n");
printk(KERN_INFO "%s: Maximum sectors/read set to %d.\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 * Register for the events we're interested in and that the
...@@ -1233,7 +1234,7 @@ static int i2ob_init_iop(unsigned int unit) ...@@ -1233,7 +1234,7 @@ static int i2ob_init_iop(unsigned int unit)
/* Queue is MAX_I2OB + 1... */ /* Queue is MAX_I2OB + 1... */
i2ob_queues[unit]->request_queue[i].next = NULL; i2ob_queues[unit]->request_queue[i].next = NULL;
i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0]; 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]->lock = SPIN_LOCK_UNLOCKED;
i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock); i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock);
...@@ -1257,7 +1258,6 @@ static void i2ob_scan(int bios) ...@@ -1257,7 +1258,6 @@ static void i2ob_scan(int bios)
struct i2o_device *d, *b=NULL; struct i2o_device *d, *b=NULL;
struct i2o_controller *c; struct i2o_controller *c;
struct i2ob_device *dev;
for(i=0; i< MAX_I2O_CONTROLLERS; i++) for(i=0; i< MAX_I2O_CONTROLLERS; i++)
{ {
...@@ -1313,44 +1313,12 @@ static void i2ob_scan(int bios) ...@@ -1313,44 +1313,12 @@ static void i2ob_scan(int bios)
continue; /*Already claimed on pass 1 */ continue; /*Already claimed on pass 1 */
} }
if(i2o_claim_device(d, &i2o_block_handler)) if(scan_unit<MAX_I2OB)
{ i2ob_new_device(c, d);
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);
}
}
else else
{ {
if(!warned++) 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); i2o_unlock_controller(c);
...@@ -1399,12 +1367,12 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d) ...@@ -1399,12 +1367,12 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
printk(KERN_INFO " Controller %d Tid %d\n",c->unit, d->lct_data.tid); printk(KERN_INFO " Controller %d Tid %d\n",c->unit, d->lct_data.tid);
/* Check for available space */ /* 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"); printk(KERN_ERR "i2o_block: No more devices allowed!\n");
return; return;
} }
for(unit = 0; unit < (MAX_I2OB<<4); unit += 16) for(unit = 0; unit < MAX_I2OB; unit ++)
{ {
if(!i2ob_dev[unit].i2odev) if(!i2ob_dev[unit].i2odev)
break; break;
...@@ -1420,18 +1388,20 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d) ...@@ -1420,18 +1388,20 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
dev->i2odev = d; dev->i2odev = d;
dev->controller = c; dev->controller = c;
dev->tid = d->lct_data.tid; 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"); printk(KERN_ERR "i2o_block: Could not install new device\n");
}
else else
{ {
add_disk(i2ob_disk[unit>>4]); i2o_release_device(d, &i2o_block_handler);
add_disk(dev->gd);
i2ob_dev_count++; i2ob_dev_count++;
i2o_device_notify_on(d, &i2o_block_handler); i2o_device_notify_on(d, &i2o_block_handler);
} }
i2o_release_device(d, &i2o_block_handler);
return; return;
} }
...@@ -1443,64 +1413,58 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d) ...@@ -1443,64 +1413,58 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d) void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
{ {
int unit = 0; int unit = 0;
int i = 0;
unsigned long flags; unsigned long flags;
struct i2ob_device *dev;
spin_lock_irqsave(I2O_LOCK(c->unit), flags); for(unit = 0; unit < MAX_I2OB; unit ++)
/*
* 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)
{ {
if(i2ob_dev[unit].i2odev == d) dev = &i2ob_dev[unit];
if(dev->i2odev == d)
{ {
printk(KERN_INFO " /dev/%s: Controller %d Tid %d\n", printk(KERN_INFO " /dev/%s: Controller %d Tid %d\n",
d->dev_name, c->unit, d->lct_data.tid); d->dev_name, c->unit, d->lct_data.tid);
break; 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"); printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
spin_unlock_irqrestore(I2O_LOCK(c->unit), flags);
return; return;
} }
spin_lock_irqsave(dev->req_queue->queue_lock, flags);
/* /*
* This will force errors when i2ob_get_queue() is called * Need to do this...we somtimes get two events from the IRTOS
* by the kenrel. * in a row and that causes lots of problems.
*/ */
del_gendisk(i2ob_disk[unit>>4]); i2o_device_notify_off(d, &i2o_block_handler);
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 * This will force errors when i2ob_get_queue() is called
* by the kenrel.
*/ */
if(dev->gd) {
while(i2ob_dev[unit].refcnt--) struct gendisk *gd = dev->gd;
MOD_DEC_USE_COUNT; gd->queue = NULL;
del_gendisk(gd);
i2ob_dev[unit].refcnt = 0; put_disk(gd);
dev->gd = NULL;
i2ob_dev[i].tid = 0; }
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? * Do we need this?
* The media didn't really change...the device is just gone * 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--; i2ob_dev_count--;
} }
...@@ -1511,10 +1475,9 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d) ...@@ -1511,10 +1475,9 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
static int i2ob_media_change(struct gendisk *disk) static int i2ob_media_change(struct gendisk *disk)
{ {
struct i2ob_device *p = disk->private_data; struct i2ob_device *p = disk->private_data;
int i = p->index; if(p->media_change_flag)
if(i2ob_media_change_flag[i])
{ {
i2ob_media_change_flag[i]=0; p->media_change_flag=0;
return 1; return 1;
} }
return 0; return 0;
...@@ -1523,7 +1486,7 @@ static int i2ob_media_change(struct gendisk *disk) ...@@ -1523,7 +1486,7 @@ static int i2ob_media_change(struct gendisk *disk)
static int i2ob_revalidate(struct gendisk *disk) static int i2ob_revalidate(struct gendisk *disk)
{ {
struct i2ob_device *p = disk->private_data; 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 @@ static void i2ob_reboot_event(void) ...@@ -1536,7 +1499,7 @@ static void i2ob_reboot_event(void)
for(i=0;i<MAX_I2OB;i++) 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) if(dev->refcnt!=0)
{ {
...@@ -1598,48 +1561,33 @@ static int i2o_block_init(void) ...@@ -1598,48 +1561,33 @@ static int i2o_block_init(void)
if (register_blkdev(MAJOR_NR, "i2o_block")) if (register_blkdev(MAJOR_NR, "i2o_block"))
return -EIO; 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 #ifdef MODULE
printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR); printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);
#endif #endif
/*
* 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);
}
/* /*
* Set up the queue * Set up the queue
*/ */
for(i = 0; i < MAX_I2O_CONTROLLERS; i++) for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
{
i2ob_queues[i] = NULL; i2ob_queues[i] = NULL;
/*
* Now fill in the boiler plate
*/
for (i = 0; i < MAX_I2OB; 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;
} }
/* /*
...@@ -1671,9 +1619,6 @@ static int i2o_block_init(void) ...@@ -1671,9 +1619,6 @@ static int i2o_block_init(void)
return 0; return 0;
oom:
while (i--)
put_disk(i2ob_disk[i]);
unregister_blkdev(MAJOR_NR, "i2o_block"); unregister_blkdev(MAJOR_NR, "i2o_block");
return -ENOMEM; return -ENOMEM;
} }
...@@ -1701,11 +1646,8 @@ static void i2o_block_exit(void) ...@@ -1701,11 +1646,8 @@ static void i2o_block_exit(void)
if(i2ob_dev_count) { if(i2ob_dev_count) {
struct i2o_device *d; struct i2o_device *d;
for(i = 0; i < MAX_I2OB; i++) for(i = 0; i < MAX_I2OB; i++)
if((d=i2ob_dev[i<<4].i2odev)) { if((d = i2ob_dev[i].i2odev))
i2o_device_notify_off(d, &i2o_block_handler); i2ob_del_device(d->controller, d);
i2o_event_register(d->controller, d->lct_data.tid,
i2ob_context, i<<4, 0);
}
} }
/* /*
...@@ -1726,14 +1668,20 @@ static void i2o_block_exit(void) ...@@ -1726,14 +1668,20 @@ static void i2o_block_exit(void)
i2o_remove_handler(&i2o_block_handler); i2o_remove_handler(&i2o_block_handler);
for (i = 0; i < MAX_I2OB; i++)
put_disk(i2ob_disk[i]);
/* /*
* Return the block device * Return the block device
*/ */
if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0) if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0)
printk("i2o_block: cleanup_module failed\n"); 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"); MODULE_AUTHOR("Red Hat");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment