diff options
| -rw-r--r-- | drivers/block/cciss.c | 336 | ||||
| -rw-r--r-- | drivers/block/cciss.h | 2 |
2 files changed, 216 insertions, 122 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index aeaf465922e5..f9f10a15d253 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -1330,13 +1330,46 @@ static void cciss_softirq_done(struct request *rq) | |||
| 1330 | spin_unlock_irqrestore(&h->lock, flags); | 1330 | spin_unlock_irqrestore(&h->lock, flags); |
| 1331 | } | 1331 | } |
| 1332 | 1332 | ||
| 1333 | /* This function gets the serial number of a logical drive via | ||
| 1334 | * inquiry page 0x83. Serial no. is 16 bytes. If the serial | ||
| 1335 | * number cannot be had, for whatever reason, 16 bytes of 0xff | ||
| 1336 | * are returned instead. | ||
| 1337 | */ | ||
| 1338 | static void cciss_get_serial_no(int ctlr, int logvol, int withirq, | ||
| 1339 | unsigned char *serial_no, int buflen) | ||
| 1340 | { | ||
| 1341 | #define PAGE_83_INQ_BYTES 64 | ||
| 1342 | int rc; | ||
| 1343 | unsigned char *buf; | ||
| 1344 | |||
| 1345 | if (buflen > 16) | ||
| 1346 | buflen = 16; | ||
| 1347 | memset(serial_no, 0xff, buflen); | ||
| 1348 | buf = kzalloc(PAGE_83_INQ_BYTES, GFP_KERNEL); | ||
| 1349 | if (!buf) | ||
| 1350 | return; | ||
| 1351 | memset(serial_no, 0, buflen); | ||
| 1352 | if (withirq) | ||
| 1353 | rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf, | ||
| 1354 | PAGE_83_INQ_BYTES, 1, logvol, 0x83, TYPE_CMD); | ||
| 1355 | else | ||
| 1356 | rc = sendcmd(CISS_INQUIRY, ctlr, buf, | ||
| 1357 | PAGE_83_INQ_BYTES, 1, logvol, 0x83, NULL, TYPE_CMD); | ||
| 1358 | if (rc == IO_OK) | ||
| 1359 | memcpy(serial_no, &buf[8], buflen); | ||
| 1360 | kfree(buf); | ||
| 1361 | return; | ||
| 1362 | } | ||
| 1363 | |||
| 1333 | /* This function will check the usage_count of the drive to be updated/added. | 1364 | /* This function will check the usage_count of the drive to be updated/added. |
| 1334 | * If the usage_count is zero then the drive information will be updated and | 1365 | * If the usage_count is zero and it is a heretofore unknown drive, or, |
| 1335 | * the disk will be re-registered with the kernel. If not then it will be | 1366 | * the drive's capacity, geometry, or serial number has changed, |
| 1336 | * left alone for the next reboot. The exception to this is disk 0 which | 1367 | * then the drive information will be updated and the disk will be |
| 1337 | * will always be left registered with the kernel since it is also the | 1368 | * re-registered with the kernel. If these conditions don't hold, |
| 1338 | * controller node. Any changes to disk 0 will show up on the next | 1369 | * then it will be left alone for the next reboot. The exception to this |
| 1339 | * reboot. | 1370 | * is disk 0 which will always be left registered with the kernel since it |
| 1371 | * is also the controller node. Any changes to disk 0 will show up on | ||
| 1372 | * the next reboot. | ||
| 1340 | */ | 1373 | */ |
| 1341 | static void cciss_update_drive_info(int ctlr, int drv_index) | 1374 | static void cciss_update_drive_info(int ctlr, int drv_index) |
| 1342 | { | 1375 | { |
| @@ -1347,9 +1380,65 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
| 1347 | sector_t total_size; | 1380 | sector_t total_size; |
| 1348 | unsigned long flags = 0; | 1381 | unsigned long flags = 0; |
| 1349 | int ret = 0; | 1382 | int ret = 0; |
| 1383 | drive_info_struct *drvinfo; | ||
| 1384 | |||
| 1385 | /* Get information about the disk and modify the driver structure */ | ||
| 1386 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | ||
| 1387 | drvinfo = kmalloc(sizeof(*drvinfo), GFP_KERNEL); | ||
| 1388 | if (inq_buff == NULL || drvinfo == NULL) | ||
| 1389 | goto mem_msg; | ||
| 1390 | |||
| 1391 | /* testing to see if 16-byte CDBs are already being used */ | ||
| 1392 | if (h->cciss_read == CCISS_READ_16) { | ||
| 1393 | cciss_read_capacity_16(h->ctlr, drv_index, 1, | ||
| 1394 | &total_size, &block_size); | ||
| 1395 | |||
| 1396 | } else { | ||
| 1397 | cciss_read_capacity(ctlr, drv_index, 1, | ||
| 1398 | &total_size, &block_size); | ||
| 1399 | |||
| 1400 | /* if read_capacity returns all F's this volume is >2TB */ | ||
| 1401 | /* in size so we switch to 16-byte CDB's for all */ | ||
| 1402 | /* read/write ops */ | ||
| 1403 | if (total_size == 0xFFFFFFFFULL) { | ||
| 1404 | cciss_read_capacity_16(ctlr, drv_index, 1, | ||
| 1405 | &total_size, &block_size); | ||
| 1406 | h->cciss_read = CCISS_READ_16; | ||
| 1407 | h->cciss_write = CCISS_WRITE_16; | ||
| 1408 | } else { | ||
| 1409 | h->cciss_read = CCISS_READ_10; | ||
| 1410 | h->cciss_write = CCISS_WRITE_10; | ||
| 1411 | } | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, | ||
| 1415 | inq_buff, drvinfo); | ||
| 1416 | drvinfo->block_size = block_size; | ||
| 1417 | drvinfo->nr_blocks = total_size + 1; | ||
| 1418 | |||
| 1419 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, | ||
| 1420 | sizeof(drvinfo->serial_no)); | ||
| 1421 | |||
| 1422 | /* Is it the same disk we already know, and nothing's changed? */ | ||
| 1423 | if (h->drv[drv_index].raid_level != -1 && | ||
| 1424 | ((memcmp(drvinfo->serial_no, | ||
| 1425 | h->drv[drv_index].serial_no, 16) == 0) && | ||
| 1426 | drvinfo->block_size == h->drv[drv_index].block_size && | ||
| 1427 | drvinfo->nr_blocks == h->drv[drv_index].nr_blocks && | ||
| 1428 | drvinfo->heads == h->drv[drv_index].heads && | ||
| 1429 | drvinfo->sectors == h->drv[drv_index].sectors && | ||
| 1430 | drvinfo->cylinders == h->drv[drv_index].cylinders)) { | ||
| 1431 | /* The disk is unchanged, nothing to update */ | ||
| 1432 | goto freeret; | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | /* Not the same disk, or something's changed, so we need to */ | ||
| 1436 | /* deregister it, and re-register it, if it's not in use. */ | ||
| 1350 | 1437 | ||
| 1351 | /* if the disk already exists then deregister it before proceeding */ | 1438 | /* if the disk already exists then deregister it before proceeding */ |
| 1352 | if (h->drv[drv_index].raid_level != -1) { | 1439 | /* (unless it's the first disk (for the controller node). */ |
| 1440 | if (h->drv[drv_index].raid_level != -1 && drv_index != 0) { | ||
| 1441 | printk(KERN_WARNING "disk %d has changed.\n", drv_index); | ||
| 1353 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 1442 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
| 1354 | h->drv[drv_index].busy_configuring = 1; | 1443 | h->drv[drv_index].busy_configuring = 1; |
| 1355 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1444 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
| @@ -1364,43 +1453,23 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
| 1364 | 1453 | ||
| 1365 | /* If the disk is in use return */ | 1454 | /* If the disk is in use return */ |
| 1366 | if (ret) | 1455 | if (ret) |
| 1367 | return; | 1456 | goto freeret; |
| 1368 | 1457 | ||
| 1369 | /* Get information about the disk and modify the driver structure */ | 1458 | /* Save the new information from cciss_geometry_inquiry */ |
| 1370 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 1459 | /* and serial number inquiry. */ |
| 1371 | if (inq_buff == NULL) | 1460 | h->drv[drv_index].block_size = drvinfo->block_size; |
| 1372 | goto mem_msg; | 1461 | h->drv[drv_index].nr_blocks = drvinfo->nr_blocks; |
| 1373 | 1462 | h->drv[drv_index].heads = drvinfo->heads; | |
| 1374 | /* testing to see if 16-byte CDBs are already being used */ | 1463 | h->drv[drv_index].sectors = drvinfo->sectors; |
| 1375 | if (h->cciss_read == CCISS_READ_16) { | 1464 | h->drv[drv_index].cylinders = drvinfo->cylinders; |
| 1376 | cciss_read_capacity_16(h->ctlr, drv_index, 1, | 1465 | h->drv[drv_index].raid_level = drvinfo->raid_level; |
| 1377 | &total_size, &block_size); | 1466 | memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); |
| 1378 | goto geo_inq; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | cciss_read_capacity(ctlr, drv_index, 1, | ||
| 1382 | &total_size, &block_size); | ||
| 1383 | |||
| 1384 | /* if read_capacity returns all F's this volume is >2TB in size */ | ||
| 1385 | /* so we switch to 16-byte CDB's for all read/write ops */ | ||
| 1386 | if (total_size == 0xFFFFFFFFULL) { | ||
| 1387 | cciss_read_capacity_16(ctlr, drv_index, 1, | ||
| 1388 | &total_size, &block_size); | ||
| 1389 | h->cciss_read = CCISS_READ_16; | ||
| 1390 | h->cciss_write = CCISS_WRITE_16; | ||
| 1391 | } else { | ||
| 1392 | h->cciss_read = CCISS_READ_10; | ||
| 1393 | h->cciss_write = CCISS_WRITE_10; | ||
| 1394 | } | ||
| 1395 | geo_inq: | ||
| 1396 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, | ||
| 1397 | inq_buff, &h->drv[drv_index]); | ||
| 1398 | 1467 | ||
| 1399 | ++h->num_luns; | 1468 | ++h->num_luns; |
| 1400 | disk = h->gendisk[drv_index]; | 1469 | disk = h->gendisk[drv_index]; |
| 1401 | set_capacity(disk, h->drv[drv_index].nr_blocks); | 1470 | set_capacity(disk, h->drv[drv_index].nr_blocks); |
| 1402 | 1471 | ||
| 1403 | /* if it's the controller it's already added */ | 1472 | /* if it's the controller (if drv_index == 0) it's already added */ |
| 1404 | if (drv_index) { | 1473 | if (drv_index) { |
| 1405 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); | 1474 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); |
| 1406 | sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); | 1475 | sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); |
| @@ -1437,6 +1506,7 @@ geo_inq: | |||
| 1437 | 1506 | ||
| 1438 | freeret: | 1507 | freeret: |
| 1439 | kfree(inq_buff); | 1508 | kfree(inq_buff); |
| 1509 | kfree(drvinfo); | ||
| 1440 | return; | 1510 | return; |
| 1441 | mem_msg: | 1511 | mem_msg: |
| 1442 | printk(KERN_ERR "cciss: out of memory\n"); | 1512 | printk(KERN_ERR "cciss: out of memory\n"); |
| @@ -1478,7 +1548,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
| 1478 | int ctlr = h->ctlr; | 1548 | int ctlr = h->ctlr; |
| 1479 | int num_luns; | 1549 | int num_luns; |
| 1480 | ReportLunData_struct *ld_buff = NULL; | 1550 | ReportLunData_struct *ld_buff = NULL; |
| 1481 | drive_info_struct *drv = NULL; | ||
| 1482 | int return_code; | 1551 | int return_code; |
| 1483 | int listlength = 0; | 1552 | int listlength = 0; |
| 1484 | int i; | 1553 | int i; |
| @@ -1494,98 +1563,117 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
| 1494 | return -EBUSY; | 1563 | return -EBUSY; |
| 1495 | } | 1564 | } |
| 1496 | h->busy_configuring = 1; | 1565 | h->busy_configuring = 1; |
| 1566 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 1497 | 1567 | ||
| 1498 | /* if del_disk is NULL then we are being called to add a new disk | 1568 | if (!capable(CAP_SYS_RAWIO)) |
| 1499 | * and update the logical drive table. If it is not NULL then | 1569 | return -EPERM; |
| 1500 | * we will check if the disk is in use or not. | ||
| 1501 | */ | ||
| 1502 | if (del_disk != NULL) { | ||
| 1503 | drv = get_drv(del_disk); | ||
| 1504 | drv->busy_configuring = 1; | ||
| 1505 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 1506 | return_code = deregister_disk(del_disk, drv, 1); | ||
| 1507 | drv->busy_configuring = 0; | ||
| 1508 | h->busy_configuring = 0; | ||
| 1509 | return return_code; | ||
| 1510 | } else { | ||
| 1511 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 1512 | if (!capable(CAP_SYS_RAWIO)) | ||
| 1513 | return -EPERM; | ||
| 1514 | 1570 | ||
| 1515 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); | 1571 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); |
| 1516 | if (ld_buff == NULL) | 1572 | if (ld_buff == NULL) |
| 1517 | goto mem_msg; | 1573 | goto mem_msg; |
| 1518 | 1574 | ||
| 1519 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, | 1575 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, |
| 1520 | sizeof(ReportLunData_struct), 0, | 1576 | sizeof(ReportLunData_struct), 0, |
| 1521 | 0, 0, TYPE_CMD); | 1577 | 0, 0, TYPE_CMD); |
| 1522 | |||
| 1523 | if (return_code == IO_OK) { | ||
| 1524 | listlength = | ||
| 1525 | be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); | ||
| 1526 | } else { /* reading number of logical volumes failed */ | ||
| 1527 | printk(KERN_WARNING "cciss: report logical volume" | ||
| 1528 | " command failed\n"); | ||
| 1529 | listlength = 0; | ||
| 1530 | goto freeret; | ||
| 1531 | } | ||
| 1532 | 1578 | ||
| 1533 | num_luns = listlength / 8; /* 8 bytes per entry */ | 1579 | if (return_code == IO_OK) |
| 1534 | if (num_luns > CISS_MAX_LUN) { | 1580 | listlength = be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); |
| 1535 | num_luns = CISS_MAX_LUN; | 1581 | else { /* reading number of logical volumes failed */ |
| 1536 | printk(KERN_WARNING "cciss: more luns configured" | 1582 | printk(KERN_WARNING "cciss: report logical volume" |
| 1537 | " on controller than can be handled by" | 1583 | " command failed\n"); |
| 1538 | " this driver.\n"); | 1584 | listlength = 0; |
| 1585 | goto freeret; | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | num_luns = listlength / 8; /* 8 bytes per entry */ | ||
| 1589 | if (num_luns > CISS_MAX_LUN) { | ||
| 1590 | num_luns = CISS_MAX_LUN; | ||
| 1591 | printk(KERN_WARNING "cciss: more luns configured" | ||
| 1592 | " on controller than can be handled by" | ||
| 1593 | " this driver.\n"); | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | /* Compare controller drive array to driver's drive array */ | ||
| 1597 | /* to see if any drives are missing on the controller due */ | ||
| 1598 | /* to action of Array Config Utility (user deletes drive) */ | ||
| 1599 | /* and deregister logical drives which have disappeared. */ | ||
| 1600 | for (i = 0; i <= h->highest_lun; i++) { | ||
| 1601 | int j; | ||
| 1602 | drv_found = 0; | ||
| 1603 | for (j = 0; j < num_luns; j++) { | ||
| 1604 | memcpy(&lunid, &ld_buff->LUN[j][0], 4); | ||
| 1605 | lunid = le32_to_cpu(lunid); | ||
| 1606 | if (h->drv[i].LunID == lunid) { | ||
| 1607 | drv_found = 1; | ||
| 1608 | break; | ||
| 1609 | } | ||
| 1610 | } | ||
| 1611 | if (!drv_found) { | ||
| 1612 | /* Deregister it from the OS, it's gone. */ | ||
| 1613 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
| 1614 | h->drv[i].busy_configuring = 1; | ||
| 1615 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 1616 | return_code = deregister_disk(h->gendisk[i], | ||
| 1617 | &h->drv[i], 1); | ||
| 1618 | h->drv[i].busy_configuring = 0; | ||
| 1539 | } | 1619 | } |
| 1620 | } | ||
| 1540 | 1621 | ||
| 1541 | /* Compare controller drive array to drivers drive array. | 1622 | /* Compare controller drive array to driver's drive array. |
| 1542 | * Check for updates in the drive information and any new drives | 1623 | * Check for updates in the drive information and any new drives |
| 1543 | * on the controller. | 1624 | * on the controller due to ACU adding logical drives, or changing |
| 1544 | */ | 1625 | * a logical drive's size, etc. Reregister any new/changed drives |
| 1545 | for (i = 0; i < num_luns; i++) { | 1626 | */ |
| 1546 | int j; | 1627 | for (i = 0; i < num_luns; i++) { |
| 1628 | int j; | ||
| 1547 | 1629 | ||
| 1548 | drv_found = 0; | 1630 | drv_found = 0; |
| 1549 | 1631 | ||
| 1550 | lunid = (0xff & | 1632 | memcpy(&lunid, &ld_buff->LUN[i][0], 4); |
| 1551 | (unsigned int)(ld_buff->LUN[i][3])) << 24; | 1633 | lunid = le32_to_cpu(lunid); |
| 1552 | lunid |= (0xff & | ||
| 1553 | (unsigned int)(ld_buff->LUN[i][2])) << 16; | ||
| 1554 | lunid |= (0xff & | ||
| 1555 | (unsigned int)(ld_buff->LUN[i][1])) << 8; | ||
| 1556 | lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); | ||
| 1557 | 1634 | ||
| 1558 | /* Find if the LUN is already in the drive array | 1635 | /* Find if the LUN is already in the drive array |
| 1559 | * of the controller. If so then update its info | 1636 | * of the driver. If so then update its info |
| 1560 | * if not is use. If it does not exist then find | 1637 | * if not in use. If it does not exist then find |
| 1561 | * the first free index and add it. | 1638 | * the first free index and add it. |
| 1562 | */ | 1639 | */ |
| 1563 | for (j = 0; j <= h->highest_lun; j++) { | 1640 | for (j = 0; j <= h->highest_lun; j++) { |
| 1564 | if (h->drv[j].LunID == lunid) { | 1641 | if (h->drv[j].raid_level != -1 && |
| 1565 | drv_index = j; | 1642 | h->drv[j].LunID == lunid) { |
| 1566 | drv_found = 1; | 1643 | drv_index = j; |
| 1567 | } | 1644 | drv_found = 1; |
| 1645 | break; | ||
| 1568 | } | 1646 | } |
| 1647 | } | ||
| 1569 | 1648 | ||
| 1570 | /* check if the drive was found already in the array */ | 1649 | /* check if the drive was found already in the array */ |
| 1571 | if (!drv_found) { | 1650 | if (!drv_found) { |
| 1572 | drv_index = cciss_find_free_drive_index(ctlr); | 1651 | drv_index = cciss_find_free_drive_index(ctlr); |
| 1573 | if (drv_index == -1) | 1652 | if (drv_index == -1) |
| 1574 | goto freeret; | 1653 | goto freeret; |
| 1575 | 1654 | /*Check if the gendisk needs to be allocated */ | |
| 1576 | /*Check if the gendisk needs to be allocated */ | 1655 | if (!h->gendisk[drv_index]) { |
| 1656 | h->gendisk[drv_index] = | ||
| 1657 | alloc_disk(1 << NWD_SHIFT); | ||
| 1577 | if (!h->gendisk[drv_index]){ | 1658 | if (!h->gendisk[drv_index]){ |
| 1578 | h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT); | 1659 | printk(KERN_ERR "cciss: could not " |
| 1579 | if (!h->gendisk[drv_index]){ | 1660 | "allocate new disk %d\n", |
| 1580 | printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index); | 1661 | drv_index); |
| 1581 | goto mem_msg; | 1662 | goto mem_msg; |
| 1582 | } | ||
| 1583 | } | 1663 | } |
| 1584 | } | 1664 | } |
| 1585 | h->drv[drv_index].LunID = lunid; | 1665 | h->drv[drv_index].LunID = lunid; |
| 1586 | cciss_update_drive_info(ctlr, drv_index); | 1666 | |
| 1587 | } /* end for */ | 1667 | /* Don't need to mark this busy because nobody |
| 1588 | } /* end else */ | 1668 | * else knows about this disk yet to contend |
| 1669 | * for access to it. | ||
| 1670 | */ | ||
| 1671 | h->drv[drv_index].busy_configuring = 0; | ||
| 1672 | wmb(); | ||
| 1673 | |||
| 1674 | } | ||
| 1675 | cciss_update_drive_info(ctlr, drv_index); | ||
| 1676 | } /* end for */ | ||
| 1589 | 1677 | ||
| 1590 | freeret: | 1678 | freeret: |
| 1591 | kfree(ld_buff); | 1679 | kfree(ld_buff); |
| @@ -1597,6 +1685,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
| 1597 | return -1; | 1685 | return -1; |
| 1598 | mem_msg: | 1686 | mem_msg: |
| 1599 | printk(KERN_ERR "cciss: out of memory\n"); | 1687 | printk(KERN_ERR "cciss: out of memory\n"); |
| 1688 | h->busy_configuring = 0; | ||
| 1600 | goto freeret; | 1689 | goto freeret; |
| 1601 | } | 1690 | } |
| 1602 | 1691 | ||
| @@ -1652,15 +1741,15 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
| 1652 | * other than disk 0 we will call put_disk. We do not | 1741 | * other than disk 0 we will call put_disk. We do not |
| 1653 | * do this for disk 0 as we need it to be able to | 1742 | * do this for disk 0 as we need it to be able to |
| 1654 | * configure the controller. | 1743 | * configure the controller. |
| 1655 | */ | 1744 | */ |
| 1656 | if (clear_all){ | 1745 | if (clear_all){ |
| 1657 | /* This isn't pretty, but we need to find the | 1746 | /* This isn't pretty, but we need to find the |
| 1658 | * disk in our array and NULL our the pointer. | 1747 | * disk in our array and NULL our the pointer. |
| 1659 | * This is so that we will call alloc_disk if | 1748 | * This is so that we will call alloc_disk if |
| 1660 | * this index is used again later. | 1749 | * this index is used again later. |
| 1661 | */ | 1750 | */ |
| 1662 | for (i=0; i < CISS_MAX_LUN; i++){ | 1751 | for (i=0; i < CISS_MAX_LUN; i++){ |
| 1663 | if(h->gendisk[i] == disk){ | 1752 | if (h->gendisk[i] == disk) { |
| 1664 | h->gendisk[i] = NULL; | 1753 | h->gendisk[i] = NULL; |
| 1665 | break; | 1754 | break; |
| 1666 | } | 1755 | } |
| @@ -1688,7 +1777,7 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
| 1688 | if (drv == h->drv + h->highest_lun) { | 1777 | if (drv == h->drv + h->highest_lun) { |
| 1689 | /* if so, find the new hightest lun */ | 1778 | /* if so, find the new hightest lun */ |
| 1690 | int i, newhighest = -1; | 1779 | int i, newhighest = -1; |
| 1691 | for (i = 0; i < h->highest_lun; i++) { | 1780 | for (i = 0; i <= h->highest_lun; i++) { |
| 1692 | /* if the disk has size > 0, it is available */ | 1781 | /* if the disk has size > 0, it is available */ |
| 1693 | if (h->drv[i].heads) | 1782 | if (h->drv[i].heads) |
| 1694 | newhighest = i; | 1783 | newhighest = i; |
| @@ -3318,6 +3407,9 @@ geo_inq: | |||
| 3318 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, | 3407 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, |
| 3319 | block_size, inq_buff, | 3408 | block_size, inq_buff, |
| 3320 | &hba[cntl_num]->drv[i]); | 3409 | &hba[cntl_num]->drv[i]); |
| 3410 | cciss_get_serial_no(cntl_num, i, 0, | ||
| 3411 | hba[cntl_num]->drv[i].serial_no, | ||
| 3412 | sizeof(hba[cntl_num]->drv[i].serial_no)); | ||
| 3321 | } else { | 3413 | } else { |
| 3322 | /* initialize raid_level to indicate a free space */ | 3414 | /* initialize raid_level to indicate a free space */ |
| 3323 | hba[cntl_num]->drv[i].raid_level = -1; | 3415 | hba[cntl_num]->drv[i].raid_level = -1; |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index b70988dd33ec..24a7efa993ab 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
| @@ -39,6 +39,8 @@ typedef struct _drive_info_struct | |||
| 39 | *to prevent it from being opened or it's queue | 39 | *to prevent it from being opened or it's queue |
| 40 | *from being started. | 40 | *from being started. |
| 41 | */ | 41 | */ |
| 42 | __u8 serial_no[16]; /* from inquiry page 0x83, */ | ||
| 43 | /* not necc. null terminated. */ | ||
| 42 | } drive_info_struct; | 44 | } drive_info_struct; |
| 43 | 45 | ||
| 44 | #ifdef CONFIG_CISS_SCSI_TAPE | 46 | #ifdef CONFIG_CISS_SCSI_TAPE |
