diff options
author | Mike Miller <mike.miller@hp.com> | 2006-12-06 23:35:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:30 -0500 |
commit | 799202cbd0ef6a201446d99fcbd78b9f0bda6ae5 (patch) | |
tree | cfc6a988170f4e65b810ee6a523e6d858ee01ce2 | |
parent | 3833a748aa75dd39494bb861ab018216b0a2c14e (diff) |
[PATCH] cciss: add support for 1024 logical volumes
Add the support for a large number of logical volumes. We will soon have
hardware that support up to 1024 logical volumes.
Signed-off-by: Mike Miller <mike.miller@hp.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/block/cciss.c | 114 | ||||
-rw-r--r-- | drivers/block/cciss.h | 3 | ||||
-rw-r--r-- | drivers/block/cciss_cmd.h | 2 | ||||
-rw-r--r-- | include/linux/cciss_ioctl.h | 2 |
4 files changed, 80 insertions, 41 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 70cf9321ef54..c99cb7ed57f7 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -1315,6 +1315,11 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1315 | /* if it's the controller it's already added */ | 1315 | /* if it's the controller it's already added */ |
1316 | if (drv_index) { | 1316 | if (drv_index) { |
1317 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); | 1317 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); |
1318 | sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); | ||
1319 | disk->major = h->major; | ||
1320 | disk->first_minor = drv_index << NWD_SHIFT; | ||
1321 | disk->fops = &cciss_fops; | ||
1322 | disk->private_data = &h->drv[drv_index]; | ||
1318 | 1323 | ||
1319 | /* Set up queue information */ | 1324 | /* Set up queue information */ |
1320 | disk->queue->backing_dev_info.ra_pages = READ_AHEAD; | 1325 | disk->queue->backing_dev_info.ra_pages = READ_AHEAD; |
@@ -1393,11 +1398,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1393 | 1398 | ||
1394 | /* Set busy_configuring flag for this operation */ | 1399 | /* Set busy_configuring flag for this operation */ |
1395 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 1400 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
1396 | if (h->num_luns >= CISS_MAX_LUN) { | ||
1397 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1398 | return -EINVAL; | ||
1399 | } | ||
1400 | |||
1401 | if (h->busy_configuring) { | 1401 | if (h->busy_configuring) { |
1402 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1402 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
1403 | return -EBUSY; | 1403 | return -EBUSY; |
@@ -1430,17 +1430,8 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1430 | 0, 0, TYPE_CMD); | 1430 | 0, 0, TYPE_CMD); |
1431 | 1431 | ||
1432 | if (return_code == IO_OK) { | 1432 | if (return_code == IO_OK) { |
1433 | listlength |= | 1433 | listlength = |
1434 | (0xff & (unsigned int)(ld_buff->LUNListLength[0])) | 1434 | be32_to_cpu(*(__u32 *) ld_buff->LUNListLength); |
1435 | << 24; | ||
1436 | listlength |= | ||
1437 | (0xff & (unsigned int)(ld_buff->LUNListLength[1])) | ||
1438 | << 16; | ||
1439 | listlength |= | ||
1440 | (0xff & (unsigned int)(ld_buff->LUNListLength[2])) | ||
1441 | << 8; | ||
1442 | listlength |= | ||
1443 | 0xff & (unsigned int)(ld_buff->LUNListLength[3]); | ||
1444 | } else { /* reading number of logical volumes failed */ | 1435 | } else { /* reading number of logical volumes failed */ |
1445 | printk(KERN_WARNING "cciss: report logical volume" | 1436 | printk(KERN_WARNING "cciss: report logical volume" |
1446 | " command failed\n"); | 1437 | " command failed\n"); |
@@ -1491,6 +1482,14 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1491 | if (drv_index == -1) | 1482 | if (drv_index == -1) |
1492 | goto freeret; | 1483 | goto freeret; |
1493 | 1484 | ||
1485 | /*Check if the gendisk needs to be allocated */ | ||
1486 | if (!h->gendisk[drv_index]){ | ||
1487 | h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT); | ||
1488 | if (!h->gendisk[drv_index]){ | ||
1489 | printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index); | ||
1490 | goto mem_msg; | ||
1491 | } | ||
1492 | } | ||
1494 | } | 1493 | } |
1495 | h->drv[drv_index].LunID = lunid; | 1494 | h->drv[drv_index].LunID = lunid; |
1496 | cciss_update_drive_info(ctlr, drv_index); | 1495 | cciss_update_drive_info(ctlr, drv_index); |
@@ -1528,6 +1527,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1528 | static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | 1527 | static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, |
1529 | int clear_all) | 1528 | int clear_all) |
1530 | { | 1529 | { |
1530 | int i; | ||
1531 | ctlr_info_t *h = get_host(disk); | 1531 | ctlr_info_t *h = get_host(disk); |
1532 | 1532 | ||
1533 | if (!capable(CAP_SYS_RAWIO)) | 1533 | if (!capable(CAP_SYS_RAWIO)) |
@@ -1551,9 +1551,35 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
1551 | del_gendisk(disk); | 1551 | del_gendisk(disk); |
1552 | if (q) { | 1552 | if (q) { |
1553 | blk_cleanup_queue(q); | 1553 | blk_cleanup_queue(q); |
1554 | /* Set drv->queue to NULL so that we do not try | ||
1555 | * to call blk_start_queue on this queue in the | ||
1556 | * interrupt handler | ||
1557 | */ | ||
1554 | drv->queue = NULL; | 1558 | drv->queue = NULL; |
1555 | } | 1559 | } |
1560 | /* If clear_all is set then we are deleting the logical | ||
1561 | * drive, not just refreshing its info. For drives | ||
1562 | * other than disk 0 we will call put_disk. We do not | ||
1563 | * do this for disk 0 as we need it to be able to | ||
1564 | * configure the controller. | ||
1565 | */ | ||
1566 | if (clear_all){ | ||
1567 | /* This isn't pretty, but we need to find the | ||
1568 | * disk in our array and NULL our the pointer. | ||
1569 | * This is so that we will call alloc_disk if | ||
1570 | * this index is used again later. | ||
1571 | */ | ||
1572 | for (i=0; i < CISS_MAX_LUN; i++){ | ||
1573 | if(h->gendisk[i] == disk){ | ||
1574 | h->gendisk[i] = NULL; | ||
1575 | break; | ||
1576 | } | ||
1577 | } | ||
1578 | put_disk(disk); | ||
1579 | } | ||
1556 | } | 1580 | } |
1581 | } else { | ||
1582 | set_capacity(disk, 0); | ||
1557 | } | 1583 | } |
1558 | 1584 | ||
1559 | --h->num_luns; | 1585 | --h->num_luns; |
@@ -3119,13 +3145,7 @@ geo_inq: | |||
3119 | /* Returns -1 if no free entries are left. */ | 3145 | /* Returns -1 if no free entries are left. */ |
3120 | static int alloc_cciss_hba(void) | 3146 | static int alloc_cciss_hba(void) |
3121 | { | 3147 | { |
3122 | struct gendisk *disk[NWD]; | 3148 | int i; |
3123 | int i, n; | ||
3124 | for (n = 0; n < NWD; n++) { | ||
3125 | disk[n] = alloc_disk(1 << NWD_SHIFT); | ||
3126 | if (!disk[n]) | ||
3127 | goto out; | ||
3128 | } | ||
3129 | 3149 | ||
3130 | for (i = 0; i < MAX_CTLR; i++) { | 3150 | for (i = 0; i < MAX_CTLR; i++) { |
3131 | if (!hba[i]) { | 3151 | if (!hba[i]) { |
@@ -3133,20 +3153,18 @@ static int alloc_cciss_hba(void) | |||
3133 | p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); | 3153 | p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); |
3134 | if (!p) | 3154 | if (!p) |
3135 | goto Enomem; | 3155 | goto Enomem; |
3136 | for (n = 0; n < NWD; n++) | 3156 | p->gendisk[0] = alloc_disk(1 << NWD_SHIFT); |
3137 | p->gendisk[n] = disk[n]; | 3157 | if (!p->gendisk[0]) |
3158 | goto Enomem; | ||
3138 | hba[i] = p; | 3159 | hba[i] = p; |
3139 | return i; | 3160 | return i; |
3140 | } | 3161 | } |
3141 | } | 3162 | } |
3142 | printk(KERN_WARNING "cciss: This driver supports a maximum" | 3163 | printk(KERN_WARNING "cciss: This driver supports a maximum" |
3143 | " of %d controllers.\n", MAX_CTLR); | 3164 | " of %d controllers.\n", MAX_CTLR); |
3144 | goto out; | 3165 | return -1; |
3145 | Enomem: | 3166 | Enomem: |
3146 | printk(KERN_ERR "cciss: out of memory.\n"); | 3167 | printk(KERN_ERR "cciss: out of memory.\n"); |
3147 | out: | ||
3148 | while (n--) | ||
3149 | put_disk(disk[n]); | ||
3150 | return -1; | 3168 | return -1; |
3151 | } | 3169 | } |
3152 | 3170 | ||
@@ -3156,7 +3174,7 @@ static void free_hba(int i) | |||
3156 | int n; | 3174 | int n; |
3157 | 3175 | ||
3158 | hba[i] = NULL; | 3176 | hba[i] = NULL; |
3159 | for (n = 0; n < NWD; n++) | 3177 | for (n = 0; n < CISS_MAX_LUN; n++) |
3160 | put_disk(p->gendisk[n]); | 3178 | put_disk(p->gendisk[n]); |
3161 | kfree(p); | 3179 | kfree(p); |
3162 | } | 3180 | } |
@@ -3169,9 +3187,8 @@ static void free_hba(int i) | |||
3169 | static int __devinit cciss_init_one(struct pci_dev *pdev, | 3187 | static int __devinit cciss_init_one(struct pci_dev *pdev, |
3170 | const struct pci_device_id *ent) | 3188 | const struct pci_device_id *ent) |
3171 | { | 3189 | { |
3172 | request_queue_t *q; | ||
3173 | int i; | 3190 | int i; |
3174 | int j; | 3191 | int j = 0; |
3175 | int rc; | 3192 | int rc; |
3176 | int dac; | 3193 | int dac; |
3177 | 3194 | ||
@@ -3283,16 +3300,29 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3283 | 3300 | ||
3284 | hba[i]->busy_initializing = 0; | 3301 | hba[i]->busy_initializing = 0; |
3285 | 3302 | ||
3286 | for (j = 0; j < NWD; j++) { /* mfm */ | 3303 | do { |
3287 | drive_info_struct *drv = &(hba[i]->drv[j]); | 3304 | drive_info_struct *drv = &(hba[i]->drv[j]); |
3288 | struct gendisk *disk = hba[i]->gendisk[j]; | 3305 | struct gendisk *disk = hba[i]->gendisk[j]; |
3306 | request_queue_t *q; | ||
3307 | |||
3308 | /* Check if the disk was allocated already */ | ||
3309 | if (!disk){ | ||
3310 | hba[i]->gendisk[j] = alloc_disk(1 << NWD_SHIFT); | ||
3311 | disk = hba[i]->gendisk[j]; | ||
3312 | } | ||
3313 | |||
3314 | /* Check that the disk was able to be allocated */ | ||
3315 | if (!disk) { | ||
3316 | printk(KERN_ERR "cciss: unable to allocate memory for disk %d\n", j); | ||
3317 | goto clean4; | ||
3318 | } | ||
3289 | 3319 | ||
3290 | q = blk_init_queue(do_cciss_request, &hba[i]->lock); | 3320 | q = blk_init_queue(do_cciss_request, &hba[i]->lock); |
3291 | if (!q) { | 3321 | if (!q) { |
3292 | printk(KERN_ERR | 3322 | printk(KERN_ERR |
3293 | "cciss: unable to allocate queue for disk %d\n", | 3323 | "cciss: unable to allocate queue for disk %d\n", |
3294 | j); | 3324 | j); |
3295 | break; | 3325 | goto clean4; |
3296 | } | 3326 | } |
3297 | drv->queue = q; | 3327 | drv->queue = q; |
3298 | 3328 | ||
@@ -3324,7 +3354,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3324 | blk_queue_hardsect_size(q, drv->block_size); | 3354 | blk_queue_hardsect_size(q, drv->block_size); |
3325 | set_capacity(disk, drv->nr_blocks); | 3355 | set_capacity(disk, drv->nr_blocks); |
3326 | add_disk(disk); | 3356 | add_disk(disk); |
3327 | } | 3357 | j++; |
3358 | } while (j <= hba[i]->highest_lun); | ||
3328 | 3359 | ||
3329 | return 1; | 3360 | return 1; |
3330 | 3361 | ||
@@ -3347,6 +3378,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3347 | unregister_blkdev(hba[i]->major, hba[i]->devname); | 3378 | unregister_blkdev(hba[i]->major, hba[i]->devname); |
3348 | clean1: | 3379 | clean1: |
3349 | hba[i]->busy_initializing = 0; | 3380 | hba[i]->busy_initializing = 0; |
3381 | /* cleanup any queues that may have been initialized */ | ||
3382 | for (j=0; j <= hba[i]->highest_lun; j++){ | ||
3383 | drive_info_struct *drv = &(hba[i]->drv[j]); | ||
3384 | if (drv->queue) | ||
3385 | blk_cleanup_queue(drv->queue); | ||
3386 | } | ||
3387 | pci_release_regions(pdev); | ||
3388 | pci_disable_device(pdev); | ||
3389 | pci_set_drvdata(pdev, NULL); | ||
3350 | free_hba(i); | 3390 | free_hba(i); |
3351 | return -1; | 3391 | return -1; |
3352 | } | 3392 | } |
@@ -3394,7 +3434,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
3394 | remove_proc_entry(hba[i]->devname, proc_cciss); | 3434 | remove_proc_entry(hba[i]->devname, proc_cciss); |
3395 | 3435 | ||
3396 | /* remove it from the disk list */ | 3436 | /* remove it from the disk list */ |
3397 | for (j = 0; j < NWD; j++) { | 3437 | for (j = 0; j < CISS_MAX_LUN; j++) { |
3398 | struct gendisk *disk = hba[i]->gendisk[j]; | 3438 | struct gendisk *disk = hba[i]->gendisk[j]; |
3399 | if (disk) { | 3439 | if (disk) { |
3400 | request_queue_t *q = disk->queue; | 3440 | request_queue_t *q = disk->queue; |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index c3df673f860b..b70988dd33ec 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -6,7 +6,6 @@ | |||
6 | #include "cciss_cmd.h" | 6 | #include "cciss_cmd.h" |
7 | 7 | ||
8 | 8 | ||
9 | #define NWD 16 | ||
10 | #define NWD_SHIFT 4 | 9 | #define NWD_SHIFT 4 |
11 | #define MAX_PART (1 << NWD_SHIFT) | 10 | #define MAX_PART (1 << NWD_SHIFT) |
12 | 11 | ||
@@ -112,7 +111,7 @@ struct ctlr_info | |||
112 | int next_to_run; | 111 | int next_to_run; |
113 | 112 | ||
114 | // Disk structures we need to pass back | 113 | // Disk structures we need to pass back |
115 | struct gendisk *gendisk[NWD]; | 114 | struct gendisk *gendisk[CISS_MAX_LUN]; |
116 | #ifdef CONFIG_CISS_SCSI_TAPE | 115 | #ifdef CONFIG_CISS_SCSI_TAPE |
117 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ | 116 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ |
118 | /* list of block side commands the scsi error handling sucked up */ | 117 | /* list of block side commands the scsi error handling sucked up */ |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index b2147cca5acd..43bf5593b59b 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -89,7 +89,7 @@ typedef union _u64bit | |||
89 | //########################################################################### | 89 | //########################################################################### |
90 | //STRUCTURES | 90 | //STRUCTURES |
91 | //########################################################################### | 91 | //########################################################################### |
92 | #define CISS_MAX_LUN 16 | 92 | #define CISS_MAX_LUN 1024 |
93 | #define CISS_MAX_PHYS_LUN 1024 | 93 | #define CISS_MAX_PHYS_LUN 1024 |
94 | // SCSI-3 Cmmands | 94 | // SCSI-3 Cmmands |
95 | 95 | ||
diff --git a/include/linux/cciss_ioctl.h b/include/linux/cciss_ioctl.h index 6e27f42e3a57..cb57c30081a8 100644 --- a/include/linux/cciss_ioctl.h +++ b/include/linux/cciss_ioctl.h | |||
@@ -80,7 +80,7 @@ typedef __u32 DriverVer_type; | |||
80 | #define HWORD __u16 | 80 | #define HWORD __u16 |
81 | #define DWORD __u32 | 81 | #define DWORD __u32 |
82 | 82 | ||
83 | #define CISS_MAX_LUN 16 | 83 | #define CISS_MAX_LUN 1024 |
84 | 84 | ||
85 | #define LEVEL2LUN 1 // index into Target(x) structure, due to byte swapping | 85 | #define LEVEL2LUN 1 // index into Target(x) structure, due to byte swapping |
86 | #define LEVEL3LUN 0 | 86 | #define LEVEL3LUN 0 |