per device queues for cciss 2.6.0

From: mikem
Date: Tue Mar 09 2004 - 11:55:04 EST


This is resubmission of yesterdays patch. It adds support for per logical device queues in the cciss driver. I have clarified that we only use one lock for all queues and it is held as specified in ll_rw_block.c. The locking needs to be redone for maximum efficiency but schedules don't permit that work at this time. This was done to fix an Oops with multiple logical volumes on a controller.
Please consider this patch for inclusion.

Thanks,
mikem
-------------------------------------------------------------------------------

diff -burN lx264.orig/drivers/block/cciss.c lx264/drivers/block/cciss.c
--- lx264.orig/drivers/block/cciss.c 2004-02-17 21:59:44.000000000 -0600
+++ lx264/drivers/block/cciss.c 2004-03-09 08:43:27.000000000 -0600
@@ -210,7 +210,7 @@

pos += size; len += size;
cciss_proc_tape_report(ctlr, buffer, &pos, &len);
- for(i=0; i<h->highest_lun; i++) {
+ for(i=0; i<=h->highest_lun; i++) {
sector_t tmp;

drv = &h->drv[i];
@@ -991,7 +991,7 @@
drive_info_struct *drv = &(host->drv[i]);
if (!drv->nr_blocks)
continue;
- blk_queue_hardsect_size(host->queue, drv->block_size);
+ blk_queue_hardsect_size(drv->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
}
@@ -2016,7 +2016,7 @@
CommandList_struct *c;
unsigned long flags;
__u32 a, a1;
-
+ int j;

/* Is this interrupt for us? */
if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0))
@@ -2062,11 +2062,23 @@
}
}
}
-
/*
* See if we can queue up some more IO
+ * check every disk that exists on this controller
+ * and start it's IO
+ * At this time we use only one lock for all queues, probably
+ * not an ideal implemetation but it was required to fix
+ * an Oops. We will have to implement per queue locks when
+ * time permits.
+ *
*/
- blk_start_queue(h->queue);
+ for(j=0;j < NWD; j++) {
+ /* make sure the disk has been added and the drive is real */
+ /* because this can be called from the middle of init_one */
+ if(!(h->gendisk[j]->queue) || !(h->drv[j].nr_blocks) )
+ continue;
+ blk_start_queue(h->gendisk[j]->queue);
+ }
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return IRQ_HANDLED;
}
@@ -2513,7 +2525,6 @@
static int __devinit cciss_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- request_queue_t *q;
int i;
int j;

@@ -2571,13 +2582,6 @@
}

spin_lock_init(&hba[i]->lock);
- q = blk_init_queue(do_cciss_request, &hba[i]->lock);
- if (!q)
- goto clean4;
-
- q->backing_dev_info.ra_pages = READ_AHEAD;
- hba[i]->queue = q;
- q->queuedata = hba[i];

/* Initialize the pdev driver private data.
have it point to hba[i]. */
@@ -2599,6 +2603,19 @@

cciss_procinit(i);

+ for(j=0; j<NWD; j++) {
+ drive_info_struct *drv = &(hba[i]->drv[j]);
+ struct gendisk *disk = hba[i]->gendisk[j];
+ request_queue_t *q;
+
+ q = blk_init_queue(do_cciss_request, &hba[i]->lock);
+ if (!q) {
+ printk(KERN_ERR
+ "cciss: unable to allocate queue for disk %d\n",
+ j);
+ break;
+ }
+ drv->queue = q;
blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);

/* This is a hardware imposed limit. */
@@ -2609,21 +2626,17 @@

blk_queue_max_sectors(q, 512);

-
- for(j=0; j<NWD; j++) {
- drive_info_struct *drv = &(hba[i]->drv[j]);
- struct gendisk *disk = hba[i]->gendisk[j];
-
+ q->queuedata = hba[i];
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
sprintf(disk->devfs_name, "cciss/host%d/target%d", i, j);
disk->major = COMPAQ_CISS_MAJOR + i;
disk->first_minor = j << NWD_SHIFT;
disk->fops = &cciss_fops;
- disk->queue = hba[i]->queue;
+ disk->queue = q;
disk->private_data = drv;
if( !(drv->nr_blocks))
continue;
- blk_queue_hardsect_size(hba[i]->queue, drv->block_size);
+ blk_queue_hardsect_size(q, drv->block_size);
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
}
@@ -2693,9 +2706,9 @@
struct gendisk *disk = hba[i]->gendisk[j];
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
+ blk_cleanup_queue(disk->queue);
}

- blk_cleanup_queue(hba[i]->queue);
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
diff -burN lx264.orig/drivers/block/cciss.h lx264/drivers/block/cciss.h
--- lx264.orig/drivers/block/cciss.h 2004-02-17 21:57:11.000000000 -0600
+++ lx264/drivers/block/cciss.h 2004-03-04 15:38:50.000000000 -0600
@@ -27,6 +27,7 @@
{
__u32 LunID;
int usage_count;
+ struct request_queue *queue;
sector_t nr_blocks;
int block_size;
int heads;
@@ -69,7 +70,6 @@
unsigned int maxQsinceinit;
unsigned int maxSG;
spinlock_t lock;
- struct request_queue *queue;

//* pointers to command and error info pool */
CommandList_struct *cmd_pool;
@@ -252,7 +252,7 @@
struct access_method *access;
};

-#define CCISS_LOCK(i) (hba[i]->queue->queue_lock)
+#define CCISS_LOCK(i) (&(hba[i]->lock))

#endif /* CCISS_H */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/