aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike Miller <mike.miller@hp.com>2005-09-13 04:25:22 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-13 11:22:30 -0400
commitddd474420a0b0dfeda38b6b5f83c7af751235cc3 (patch)
treee081ba3d447eb4c1dd5a6ab38d7902c2db03ae59 /drivers
parent1f8ef3806c40e74733f45f436d44b3d8e9a2fa48 (diff)
[PATCH] cciss: new disk register/deregister routines
This patch removes a couple of functions dealing with configuration and replaces them with new functions. This implementation fixes some bugs associated with the ACUXE. It also allows a logical volume to be removed from the middle without deleting all volumes behind it. If a user has 5 logical volumes and decides he wants to reconfigure volume number 3, he can now do that without removing volumes 4 & 5 first. This code has been tested in our labs against all application software. Signed-off-by: Chase Maupin <chase.maupin@hp.com> Signed-off-by: Mike Miller <mike.miller@hp.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/cciss.c515
-rw-r--r--drivers/block/cciss.h8
2 files changed, 333 insertions, 190 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 8bcd6c498c60..3c6a6a21d540 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -155,15 +155,24 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
155 155
156static int revalidate_allvol(ctlr_info_t *host); 156static int revalidate_allvol(ctlr_info_t *host);
157static int cciss_revalidate(struct gendisk *disk); 157static int cciss_revalidate(struct gendisk *disk);
158static int deregister_disk(struct gendisk *disk); 158static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
159static int register_new_disk(ctlr_info_t *h); 159static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
160 160
161static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
162 int withirq, unsigned int *total_size, unsigned int *block_size);
163static void cciss_geometry_inquiry(int ctlr, int logvol,
164 int withirq, unsigned int total_size,
165 unsigned int block_size, InquiryData_struct *inq_buff,
166 drive_info_struct *drv);
161static void cciss_getgeometry(int cntl_num); 167static void cciss_getgeometry(int cntl_num);
162 168
163static void start_io( ctlr_info_t *h); 169static void start_io( ctlr_info_t *h);
164static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, 170static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
165 unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, 171 unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
166 unsigned char *scsi3addr, int cmd_type); 172 unsigned char *scsi3addr, int cmd_type);
173static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
174 unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
175 int cmd_type);
167 176
168#ifdef CONFIG_PROC_FS 177#ifdef CONFIG_PROC_FS
169static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 178static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
@@ -280,7 +289,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
280 for(i=0; i<=h->highest_lun; i++) { 289 for(i=0; i<=h->highest_lun; i++) {
281 290
282 drv = &h->drv[i]; 291 drv = &h->drv[i];
283 if (drv->block_size == 0) 292 if (drv->heads == 0)
284 continue; 293 continue;
285 294
286 vol_sz = drv->nr_blocks; 295 vol_sz = drv->nr_blocks;
@@ -471,6 +480,8 @@ static int cciss_open(struct inode *inode, struct file *filep)
471 if (host->busy_initializing) 480 if (host->busy_initializing)
472 return -EBUSY; 481 return -EBUSY;
473 482
483 if (host->busy_initializing || drv->busy_configuring)
484 return -EBUSY;
474 /* 485 /*
475 * Root is allowed to open raw volume zero even if it's not configured 486 * Root is allowed to open raw volume zero even if it's not configured
476 * so array config can still work. Root is also allowed to open any 487 * so array config can still work. Root is also allowed to open any
@@ -814,10 +825,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
814 return(0); 825 return(0);
815 } 826 }
816 case CCISS_DEREGDISK: 827 case CCISS_DEREGDISK:
817 return deregister_disk(disk); 828 return rebuild_lun_table(host, disk);
818 829
819 case CCISS_REGNEWD: 830 case CCISS_REGNEWD:
820 return register_new_disk(host); 831 return rebuild_lun_table(host, NULL);
821 832
822 case CCISS_PASSTHRU: 833 case CCISS_PASSTHRU:
823 { 834 {
@@ -1161,48 +1172,323 @@ static int revalidate_allvol(ctlr_info_t *host)
1161 return 0; 1172 return 0;
1162} 1173}
1163 1174
1164static int deregister_disk(struct gendisk *disk) 1175/* This function will check the usage_count of the drive to be updated/added.
1176 * If the usage_count is zero then the drive information will be updated and
1177 * the disk will be re-registered with the kernel. If not then it will be
1178 * left alone for the next reboot. The exception to this is disk 0 which
1179 * will always be left registered with the kernel since it is also the
1180 * controller node. Any changes to disk 0 will show up on the next
1181 * reboot.
1182*/
1183static void cciss_update_drive_info(int ctlr, int drv_index)
1184 {
1185 ctlr_info_t *h = hba[ctlr];
1186 struct gendisk *disk;
1187 ReadCapdata_struct *size_buff = NULL;
1188 InquiryData_struct *inq_buff = NULL;
1189 unsigned int block_size;
1190 unsigned int total_size;
1191 unsigned long flags = 0;
1192 int ret = 0;
1193
1194 /* if the disk already exists then deregister it before proceeding*/
1195 if (h->drv[drv_index].raid_level != -1){
1196 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
1197 h->drv[drv_index].busy_configuring = 1;
1198 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1199 ret = deregister_disk(h->gendisk[drv_index],
1200 &h->drv[drv_index], 0);
1201 h->drv[drv_index].busy_configuring = 0;
1202 }
1203
1204 /* If the disk is in use return */
1205 if (ret)
1206 return;
1207
1208
1209 /* Get information about the disk and modify the driver sturcture */
1210 size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
1211 if (size_buff == NULL)
1212 goto mem_msg;
1213 inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
1214 if (inq_buff == NULL)
1215 goto mem_msg;
1216
1217 cciss_read_capacity(ctlr, drv_index, size_buff, 1,
1218 &total_size, &block_size);
1219 cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
1220 inq_buff, &h->drv[drv_index]);
1221
1222 ++h->num_luns;
1223 disk = h->gendisk[drv_index];
1224 set_capacity(disk, h->drv[drv_index].nr_blocks);
1225
1226
1227 /* if it's the controller it's already added */
1228 if (drv_index){
1229 disk->queue = blk_init_queue(do_cciss_request, &h->lock);
1230
1231 /* Set up queue information */
1232 disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
1233 blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
1234
1235 /* This is a hardware imposed limit. */
1236 blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
1237
1238 /* This is a limit in the driver and could be eliminated. */
1239 blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
1240
1241 blk_queue_max_sectors(disk->queue, 512);
1242
1243 disk->queue->queuedata = hba[ctlr];
1244
1245 blk_queue_hardsect_size(disk->queue,
1246 hba[ctlr]->drv[drv_index].block_size);
1247
1248 h->drv[drv_index].queue = disk->queue;
1249 add_disk(disk);
1250 }
1251
1252freeret:
1253 kfree(size_buff);
1254 kfree(inq_buff);
1255 return;
1256mem_msg:
1257 printk(KERN_ERR "cciss: out of memory\n");
1258 goto freeret;
1259}
1260
1261/* This function will find the first index of the controllers drive array
1262 * that has a -1 for the raid_level and will return that index. This is
1263 * where new drives will be added. If the index to be returned is greater
1264 * than the highest_lun index for the controller then highest_lun is set
1265 * to this new index. If there are no available indexes then -1 is returned.
1266*/
1267static int cciss_find_free_drive_index(int ctlr)
1268{
1269 int i;
1270
1271 for (i=0; i < CISS_MAX_LUN; i++){
1272 if (hba[ctlr]->drv[i].raid_level == -1){
1273 if (i > hba[ctlr]->highest_lun)
1274 hba[ctlr]->highest_lun = i;
1275 return i;
1276 }
1277 }
1278 return -1;
1279}
1280
1281/* This function will add and remove logical drives from the Logical
1282 * drive array of the controller and maintain persistancy of ordering
1283 * so that mount points are preserved until the next reboot. This allows
1284 * for the removal of logical drives in the middle of the drive array
1285 * without a re-ordering of those drives.
1286 * INPUT
1287 * h = The controller to perform the operations on
1288 * del_disk = The disk to remove if specified. If the value given
1289 * is NULL then no disk is removed.
1290*/
1291static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
1165{ 1292{
1293 int ctlr = h->ctlr;
1294 int num_luns;
1295 ReportLunData_struct *ld_buff = NULL;
1296 drive_info_struct *drv = NULL;
1297 int return_code;
1298 int listlength = 0;
1299 int i;
1300 int drv_found;
1301 int drv_index = 0;
1302 __u32 lunid = 0;
1166 unsigned long flags; 1303 unsigned long flags;
1304
1305 /* Set busy_configuring flag for this operation */
1306 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
1307 if (h->num_luns >= CISS_MAX_LUN){
1308 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1309 return -EINVAL;
1310 }
1311
1312 if (h->busy_configuring){
1313 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1314 return -EBUSY;
1315 }
1316 h->busy_configuring = 1;
1317
1318 /* if del_disk is NULL then we are being called to add a new disk
1319 * and update the logical drive table. If it is not NULL then
1320 * we will check if the disk is in use or not.
1321 */
1322 if (del_disk != NULL){
1323 drv = get_drv(del_disk);
1324 drv->busy_configuring = 1;
1325 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1326 return_code = deregister_disk(del_disk, drv, 1);
1327 drv->busy_configuring = 0;
1328 h->busy_configuring = 0;
1329 return return_code;
1330 } else {
1331 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1332 if (!capable(CAP_SYS_RAWIO))
1333 return -EPERM;
1334
1335 ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
1336 if (ld_buff == NULL)
1337 goto mem_msg;
1338
1339 return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
1340 sizeof(ReportLunData_struct), 0, 0, 0,
1341 TYPE_CMD);
1342
1343 if (return_code == IO_OK){
1344 listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
1345 listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
1346 listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
1347 listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
1348 } else{ /* reading number of logical volumes failed */
1349 printk(KERN_WARNING "cciss: report logical volume"
1350 " command failed\n");
1351 listlength = 0;
1352 goto freeret;
1353 }
1354
1355 num_luns = listlength / 8; /* 8 bytes per entry */
1356 if (num_luns > CISS_MAX_LUN){
1357 num_luns = CISS_MAX_LUN;
1358 printk(KERN_WARNING "cciss: more luns configured"
1359 " on controller than can be handled by"
1360 " this driver.\n");
1361 }
1362
1363 /* Compare controller drive array to drivers drive array.
1364 * Check for updates in the drive information and any new drives
1365 * on the controller.
1366 */
1367 for (i=0; i < num_luns; i++){
1368 int j;
1369
1370 drv_found = 0;
1371
1372 lunid = (0xff &
1373 (unsigned int)(ld_buff->LUN[i][3])) << 24;
1374 lunid |= (0xff &
1375 (unsigned int)(ld_buff->LUN[i][2])) << 16;
1376 lunid |= (0xff &
1377 (unsigned int)(ld_buff->LUN[i][1])) << 8;
1378 lunid |= 0xff &
1379 (unsigned int)(ld_buff->LUN[i][0]);
1380
1381 /* Find if the LUN is already in the drive array
1382 * of the controller. If so then update its info
1383 * if not is use. If it does not exist then find
1384 * the first free index and add it.
1385 */
1386 for (j=0; j <= h->highest_lun; j++){
1387 if (h->drv[j].LunID == lunid){
1388 drv_index = j;
1389 drv_found = 1;
1390 }
1391 }
1392
1393 /* check if the drive was found already in the array */
1394 if (!drv_found){
1395 drv_index = cciss_find_free_drive_index(ctlr);
1396 if (drv_index == -1)
1397 goto freeret;
1398
1399 }
1400 h->drv[drv_index].LunID = lunid;
1401 cciss_update_drive_info(ctlr, drv_index);
1402 } /* end for */
1403 } /* end else */
1404
1405freeret:
1406 kfree(ld_buff);
1407 h->busy_configuring = 0;
1408 /* We return -1 here to tell the ACU that we have registered/updated
1409 * all of the drives that we can and to keep it from calling us
1410 * additional times.
1411 */
1412 return -1;
1413mem_msg:
1414 printk(KERN_ERR "cciss: out of memory\n");
1415 goto freeret;
1416}
1417
1418/* This function will deregister the disk and it's queue from the
1419 * kernel. It must be called with the controller lock held and the
1420 * drv structures busy_configuring flag set. It's parameters are:
1421 *
1422 * disk = This is the disk to be deregistered
1423 * drv = This is the drive_info_struct associated with the disk to be
1424 * deregistered. It contains information about the disk used
1425 * by the driver.
1426 * clear_all = This flag determines whether or not the disk information
1427 * is going to be completely cleared out and the highest_lun
1428 * reset. Sometimes we want to clear out information about
1429 * the disk in preperation for re-adding it. In this case
1430 * the highest_lun should be left unchanged and the LunID
1431 * should not be cleared.
1432*/
1433static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
1434 int clear_all)
1435{
1167 ctlr_info_t *h = get_host(disk); 1436 ctlr_info_t *h = get_host(disk);
1168 drive_info_struct *drv = get_drv(disk);
1169 int ctlr = h->ctlr;
1170 1437
1171 if (!capable(CAP_SYS_RAWIO)) 1438 if (!capable(CAP_SYS_RAWIO))
1172 return -EPERM; 1439 return -EPERM;
1173 1440
1174 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
1175 /* make sure logical volume is NOT is use */ 1441 /* make sure logical volume is NOT is use */
1176 if( drv->usage_count > 1) { 1442 if(clear_all || (h->gendisk[0] == disk)) {
1177 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1443 if (drv->usage_count > 1)
1178 return -EBUSY; 1444 return -EBUSY;
1179 } 1445 }
1180 drv->usage_count++; 1446 else
1181 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1447 if( drv->usage_count > 0 )
1448 return -EBUSY;
1182 1449
1183 /* invalidate the devices and deregister the disk */ 1450 /* invalidate the devices and deregister the disk. If it is disk
1184 if (disk->flags & GENHD_FL_UP) 1451 * zero do not deregister it but just zero out it's values. This
1452 * allows us to delete disk zero but keep the controller registered.
1453 */
1454 if (h->gendisk[0] != disk){
1455 if (disk->flags & GENHD_FL_UP){
1456 blk_cleanup_queue(disk->queue);
1185 del_gendisk(disk); 1457 del_gendisk(disk);
1458 drv->queue = NULL;
1459 }
1460 }
1461
1462 --h->num_luns;
1463 /* zero out the disk size info */
1464 drv->nr_blocks = 0;
1465 drv->block_size = 0;
1466 drv->heads = 0;
1467 drv->sectors = 0;
1468 drv->cylinders = 0;
1469 drv->raid_level = -1; /* This can be used as a flag variable to
1470 * indicate that this element of the drive
1471 * array is free.
1472 */
1473
1474 if (clear_all){
1186 /* check to see if it was the last disk */ 1475 /* check to see if it was the last disk */
1187 if (drv == h->drv + h->highest_lun) { 1476 if (drv == h->drv + h->highest_lun) {
1188 /* if so, find the new hightest lun */ 1477 /* if so, find the new hightest lun */
1189 int i, newhighest =-1; 1478 int i, newhighest =-1;
1190 for(i=0; i<h->highest_lun; i++) { 1479 for(i=0; i<h->highest_lun; i++) {
1191 /* if the disk has size > 0, it is available */ 1480 /* if the disk has size > 0, it is available */
1192 if (h->drv[i].nr_blocks) 1481 if (h->drv[i].heads)
1193 newhighest = i; 1482 newhighest = i;
1194 } 1483 }
1195 h->highest_lun = newhighest; 1484 h->highest_lun = newhighest;
1196
1197 } 1485 }
1198 --h->num_luns; 1486
1199 /* zero out the disk size info */
1200 drv->nr_blocks = 0;
1201 drv->block_size = 0;
1202 drv->cylinders = 0;
1203 drv->LunID = 0; 1487 drv->LunID = 0;
1488 }
1204 return(0); 1489 return(0);
1205} 1490}
1491
1206static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, 1492static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
1207 size_t size, 1493 size_t size,
1208 unsigned int use_unit_num, /* 0: address the controller, 1494 unsigned int use_unit_num, /* 0: address the controller,
@@ -1513,164 +1799,6 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
1513 return; 1799 return;
1514} 1800}
1515 1801
1516static int register_new_disk(ctlr_info_t *h)
1517{
1518 struct gendisk *disk;
1519 int ctlr = h->ctlr;
1520 int i;
1521 int num_luns;
1522 int logvol;
1523 int new_lun_found = 0;
1524 int new_lun_index = 0;
1525 int free_index_found = 0;
1526 int free_index = 0;
1527 ReportLunData_struct *ld_buff = NULL;
1528 ReadCapdata_struct *size_buff = NULL;
1529 InquiryData_struct *inq_buff = NULL;
1530 int return_code;
1531 int listlength = 0;
1532 __u32 lunid = 0;
1533 unsigned int block_size;
1534 unsigned int total_size;
1535
1536 if (!capable(CAP_SYS_RAWIO))
1537 return -EPERM;
1538 /* if we have no space in our disk array left to add anything */
1539 if( h->num_luns >= CISS_MAX_LUN)
1540 return -EINVAL;
1541
1542 ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
1543 if (ld_buff == NULL)
1544 goto mem_msg;
1545 memset(ld_buff, 0, sizeof(ReportLunData_struct));
1546 size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
1547 if (size_buff == NULL)
1548 goto mem_msg;
1549 inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
1550 if (inq_buff == NULL)
1551 goto mem_msg;
1552
1553 return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
1554 sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
1555
1556 if( return_code == IO_OK)
1557 {
1558
1559 // printk("LUN Data\n--------------------------\n");
1560
1561 listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
1562 listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
1563 listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
1564 listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
1565 } else /* reading number of logical volumes failed */
1566 {
1567 printk(KERN_WARNING "cciss: report logical volume"
1568 " command failed\n");
1569 listlength = 0;
1570 goto free_err;
1571 }
1572 num_luns = listlength / 8; // 8 bytes pre entry
1573 if (num_luns > CISS_MAX_LUN)
1574 {
1575 num_luns = CISS_MAX_LUN;
1576 }
1577#ifdef CCISS_DEBUG
1578 printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
1579 ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
1580 ld_buff->LUNListLength[3], num_luns);
1581#endif
1582 for(i=0; i< num_luns; i++)
1583 {
1584 int j;
1585 int lunID_found = 0;
1586
1587 lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
1588 lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
1589 lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
1590 lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
1591
1592 /* check to see if this is a new lun */
1593 for(j=0; j <= h->highest_lun; j++)
1594 {
1595#ifdef CCISS_DEBUG
1596 printk("Checking %d %x against %x\n", j,h->drv[j].LunID,
1597 lunid);
1598#endif /* CCISS_DEBUG */
1599 if (h->drv[j].LunID == lunid)
1600 {
1601 lunID_found = 1;
1602 break;
1603 }
1604
1605 }
1606 if( lunID_found == 1)
1607 continue;
1608 else
1609 { /* It is the new lun we have been looking for */
1610#ifdef CCISS_DEBUG
1611 printk("new lun found at %d\n", i);
1612#endif /* CCISS_DEBUG */
1613 new_lun_index = i;
1614 new_lun_found = 1;
1615 break;
1616 }
1617 }
1618 if (!new_lun_found)
1619 {
1620 printk(KERN_WARNING "cciss: New Logical Volume not found\n");
1621 goto free_err;
1622 }
1623 /* Now find the free index */
1624 for(i=0; i <CISS_MAX_LUN; i++)
1625 {
1626#ifdef CCISS_DEBUG
1627 printk("Checking Index %d\n", i);
1628#endif /* CCISS_DEBUG */
1629 if(h->drv[i].LunID == 0)
1630 {
1631#ifdef CCISS_DEBUG
1632 printk("free index found at %d\n", i);
1633#endif /* CCISS_DEBUG */
1634 free_index_found = 1;
1635 free_index = i;
1636 break;
1637 }
1638 }
1639 if (!free_index_found)
1640 {
1641 printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
1642 goto free_err;
1643 }
1644
1645 logvol = free_index;
1646 h->drv[logvol].LunID = lunid;
1647 /* there could be gaps in lun numbers, track hightest */
1648 if(h->highest_lun < lunid)
1649 h->highest_lun = logvol;
1650 cciss_read_capacity(ctlr, logvol, size_buff, 1,
1651 &total_size, &block_size);
1652 cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
1653 inq_buff, &h->drv[logvol]);
1654 h->drv[logvol].usage_count = 0;
1655 ++h->num_luns;
1656 /* setup partitions per disk */
1657 disk = h->gendisk[logvol];
1658 set_capacity(disk, h->drv[logvol].nr_blocks);
1659 /* if it's the controller it's already added */
1660 if(logvol)
1661 add_disk(disk);
1662freeret:
1663 kfree(ld_buff);
1664 kfree(size_buff);
1665 kfree(inq_buff);
1666 return (logvol);
1667mem_msg:
1668 printk(KERN_ERR "cciss: out of memory\n");
1669free_err:
1670 logvol = -1;
1671 goto freeret;
1672}
1673
1674static int cciss_revalidate(struct gendisk *disk) 1802static int cciss_revalidate(struct gendisk *disk)
1675{ 1803{
1676 ctlr_info_t *h = get_host(disk); 1804 ctlr_info_t *h = get_host(disk);
@@ -2652,12 +2780,16 @@ static void cciss_getgeometry(int cntl_num)
2652#endif /* CCISS_DEBUG */ 2780#endif /* CCISS_DEBUG */
2653 2781
2654 hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1; 2782 hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
2655 for(i=0; i< hba[cntl_num]->num_luns; i++) 2783// for(i=0; i< hba[cntl_num]->num_luns; i++)
2784 for(i=0; i < CISS_MAX_LUN; i++)
2656 { 2785 {
2657 2786 if (i < hba[cntl_num]->num_luns){
2658 lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24; 2787 lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
2659 lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16; 2788 << 24;
2660 lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8; 2789 lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
2790 << 16;
2791 lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
2792 << 8;
2661 lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); 2793 lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
2662 2794
2663 hba[cntl_num]->drv[i].LunID = lunid; 2795 hba[cntl_num]->drv[i].LunID = lunid;
@@ -2665,13 +2797,18 @@ static void cciss_getgeometry(int cntl_num)
2665 2797
2666#ifdef CCISS_DEBUG 2798#ifdef CCISS_DEBUG
2667 printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, 2799 printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i,
2668 ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], 2800 ld_buff->LUN[i][0], ld_buff->LUN[i][1],
2669 ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); 2801 ld_buff->LUN[i][2], ld_buff->LUN[i][3],
2802 hba[cntl_num]->drv[i].LunID);
2670#endif /* CCISS_DEBUG */ 2803#endif /* CCISS_DEBUG */
2671 cciss_read_capacity(cntl_num, i, size_buff, 0, 2804 cciss_read_capacity(cntl_num, i, size_buff, 0,
2672 &total_size, &block_size); 2805 &total_size, &block_size);
2673 cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size, 2806 cciss_geometry_inquiry(cntl_num, i, 0, total_size,
2674 inq_buff, &hba[cntl_num]->drv[i]); 2807 block_size, inq_buff, &hba[cntl_num]->drv[i]);
2808 } else {
2809 /* initialize raid_level to indicate a free space */
2810 hba[cntl_num]->drv[i].raid_level = -1;
2811 }
2675 } 2812 }
2676 kfree(ld_buff); 2813 kfree(ld_buff);
2677 kfree(size_buff); 2814 kfree(size_buff);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 11ee83504b38..dec27a961120 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -35,7 +35,13 @@ typedef struct _drive_info_struct
35 int heads; 35 int heads;
36 int sectors; 36 int sectors;
37 int cylinders; 37 int cylinders;
38 int raid_level; 38 int raid_level; /* set to -1 to indicate that
39 * the drive is not in use/configured
40 */
41 int busy_configuring; /*This is set when the drive is being removed
42 *to prevent it from being opened or it's queue
43 *from being started.
44 */
39} drive_info_struct; 45} drive_info_struct;
40 46
41struct ctlr_info 47struct ctlr_info