aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscameron@beardog.cca.cpqcorp.net <scameron@beardog.cca.cpqcorp.net>2008-09-19 21:27:47 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:18 -0400
commit905bd78f2188da69e74966918e3d71df3dff382b (patch)
treebfe96fedd70cf56a9a7c1585bc7f5965c3fb47e3
parent79eb014578b79fcfb9d9e7dc979d1316079220aa (diff)
cciss: Fix cciss SCSI rescan code to better notice device changes
Fix cciss SCSI rescan code to better notice device changes. If you hot-unplug a tape drive, then hot-plug a different tape drive into the same slot in a storage enclosure, the cciss driver wouldn't notice anything had changed, as it was only looking at the LUN address and device type. Now it looks at the inquiry page 0x83 device identifier, and vendor and model strings as well. Signed-off-by: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--drivers/block/cciss_scsi.c151
-rw-r--r--drivers/block/cciss_scsi.h4
2 files changed, 102 insertions, 53 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e1233aabda77..a3fd87b41444 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -365,7 +365,7 @@ struct scsi2map {
365 365
366static int 366static int
367cciss_scsi_add_entry(int ctlr, int hostno, 367cciss_scsi_add_entry(int ctlr, int hostno,
368 unsigned char *scsi3addr, int devtype, 368 struct cciss_scsi_dev_t *device,
369 struct scsi2map *added, int *nadded) 369 struct scsi2map *added, int *nadded)
370{ 370{
371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
@@ -384,12 +384,12 @@ cciss_scsi_add_entry(int ctlr, int hostno,
384 lun = 0; 384 lun = 0;
385 /* Is this device a non-zero lun of a multi-lun device */ 385 /* Is this device a non-zero lun of a multi-lun device */
386 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */ 386 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
387 if (scsi3addr[4] != 0) { 387 if (device->scsi3addr[4] != 0) {
388 /* Search through our list and find the device which */ 388 /* Search through our list and find the device which */
389 /* has the same 8 byte LUN address, excepting byte 4. */ 389 /* has the same 8 byte LUN address, excepting byte 4. */
390 /* Assign the same bus and target for this new LUN. */ 390 /* Assign the same bus and target for this new LUN. */
391 /* Use the logical unit number from the firmware. */ 391 /* Use the logical unit number from the firmware. */
392 memcpy(addr1, scsi3addr, 8); 392 memcpy(addr1, device->scsi3addr, 8);
393 addr1[4] = 0; 393 addr1[4] = 0;
394 for (i = 0; i < n; i++) { 394 for (i = 0; i < n; i++) {
395 sd = &ccissscsi[ctlr].dev[i]; 395 sd = &ccissscsi[ctlr].dev[i];
@@ -399,7 +399,7 @@ cciss_scsi_add_entry(int ctlr, int hostno,
399 if (memcmp(addr1, addr2, 8) == 0) { 399 if (memcmp(addr1, addr2, 8) == 0) {
400 bus = sd->bus; 400 bus = sd->bus;
401 target = sd->target; 401 target = sd->target;
402 lun = scsi3addr[4]; 402 lun = device->scsi3addr[4];
403 break; 403 break;
404 } 404 }
405 } 405 }
@@ -420,8 +420,12 @@ cciss_scsi_add_entry(int ctlr, int hostno,
420 added[*nadded].lun = sd->lun; 420 added[*nadded].lun = sd->lun;
421 (*nadded)++; 421 (*nadded)++;
422 422
423 memcpy(&sd->scsi3addr[0], scsi3addr, 8); 423 memcpy(sd->scsi3addr, device->scsi3addr, 8);
424 sd->devtype = devtype; 424 memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
425 memcpy(sd->revision, device->revision, sizeof(sd->revision));
426 memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
427 sd->devtype = device->devtype;
428
425 ccissscsi[ctlr].ndevices++; 429 ccissscsi[ctlr].ndevices++;
426 430
427 /* initially, (before registering with scsi layer) we don't 431 /* initially, (before registering with scsi layer) we don't
@@ -487,6 +491,22 @@ static void fixup_botched_add(int ctlr, char *scsi3addr)
487 CPQ_TAPE_UNLOCK(ctlr, flags); 491 CPQ_TAPE_UNLOCK(ctlr, flags);
488} 492}
489 493
494static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
495 struct cciss_scsi_dev_t *dev2)
496{
497 return dev1->devtype == dev2->devtype &&
498 memcmp(dev1->scsi3addr, dev2->scsi3addr,
499 sizeof(dev1->scsi3addr)) == 0 &&
500 memcmp(dev1->device_id, dev2->device_id,
501 sizeof(dev1->device_id)) == 0 &&
502 memcmp(dev1->vendor, dev2->vendor,
503 sizeof(dev1->vendor)) == 0 &&
504 memcmp(dev1->model, dev2->model,
505 sizeof(dev1->model)) == 0 &&
506 memcmp(dev1->revision, dev2->revision,
507 sizeof(dev1->revision)) == 0;
508}
509
490static int 510static int
491adjust_cciss_scsi_table(int ctlr, int hostno, 511adjust_cciss_scsi_table(int ctlr, int hostno,
492 struct cciss_scsi_dev_t sd[], int nsds) 512 struct cciss_scsi_dev_t sd[], int nsds)
@@ -532,7 +552,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
532 for (j=0;j<nsds;j++) { 552 for (j=0;j<nsds;j++) {
533 if (SCSI3ADDR_EQ(sd[j].scsi3addr, 553 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
534 csd->scsi3addr)) { 554 csd->scsi3addr)) {
535 if (sd[j].devtype == csd->devtype) 555 if (device_is_the_same(&sd[j], csd))
536 found=2; 556 found=2;
537 else 557 else
538 found=1; 558 found=1;
@@ -548,22 +568,26 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
548 cciss_scsi_remove_entry(ctlr, hostno, i, 568 cciss_scsi_remove_entry(ctlr, hostno, i,
549 removed, &nremoved); 569 removed, &nremoved);
550 /* remove ^^^, hence i not incremented */ 570 /* remove ^^^, hence i not incremented */
551 } 571 } else if (found == 1) { /* device is different in some way */
552 else if (found == 1) { /* device is different kind */
553 changes++; 572 changes++;
554 printk("cciss%d: device c%db%dt%dl%d type changed " 573 printk("cciss%d: device c%db%dt%dl%d has changed.\n",
555 "(device type now %s).\n", 574 ctlr, hostno, csd->bus, csd->target, csd->lun);
556 ctlr, hostno, csd->bus, csd->target, csd->lun,
557 scsi_device_type(csd->devtype));
558 cciss_scsi_remove_entry(ctlr, hostno, i, 575 cciss_scsi_remove_entry(ctlr, hostno, i,
559 removed, &nremoved); 576 removed, &nremoved);
560 /* remove ^^^, hence i not incremented */ 577 /* remove ^^^, hence i not incremented */
561 if (cciss_scsi_add_entry(ctlr, hostno, 578 if (cciss_scsi_add_entry(ctlr, hostno, &sd[j],
562 &sd[j].scsi3addr[0], sd[j].devtype,
563 added, &nadded) != 0) 579 added, &nadded) != 0)
564 /* we just removed one, so add can't fail. */ 580 /* we just removed one, so add can't fail. */
565 BUG(); 581 BUG();
566 csd->devtype = sd[j].devtype; 582 csd->devtype = sd[j].devtype;
583 memcpy(csd->device_id, sd[j].device_id,
584 sizeof(csd->device_id));
585 memcpy(csd->vendor, sd[j].vendor,
586 sizeof(csd->vendor));
587 memcpy(csd->model, sd[j].model,
588 sizeof(csd->model));
589 memcpy(csd->revision, sd[j].revision,
590 sizeof(csd->revision));
567 } else /* device is same as it ever was, */ 591 } else /* device is same as it ever was, */
568 i++; /* so just move along. */ 592 i++; /* so just move along. */
569 } 593 }
@@ -577,7 +601,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
577 csd = &ccissscsi[ctlr].dev[j]; 601 csd = &ccissscsi[ctlr].dev[j];
578 if (SCSI3ADDR_EQ(sd[i].scsi3addr, 602 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
579 csd->scsi3addr)) { 603 csd->scsi3addr)) {
580 if (sd[i].devtype == csd->devtype) 604 if (device_is_the_same(&sd[i], csd))
581 found=2; /* found device */ 605 found=2; /* found device */
582 else 606 else
583 found=1; /* found a bug. */ 607 found=1; /* found a bug. */
@@ -586,16 +610,14 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
586 } 610 }
587 if (!found) { 611 if (!found) {
588 changes++; 612 changes++;
589 if (cciss_scsi_add_entry(ctlr, hostno, 613 if (cciss_scsi_add_entry(ctlr, hostno, &sd[i],
590
591 &sd[i].scsi3addr[0], sd[i].devtype,
592 added, &nadded) != 0) 614 added, &nadded) != 0)
593 break; 615 break;
594 } else if (found == 1) { 616 } else if (found == 1) {
595 /* should never happen... */ 617 /* should never happen... */
596 changes++; 618 changes++;
597 printk("cciss%d: device unexpectedly changed type\n", 619 printk(KERN_WARNING "cciss%d: device "
598 ctlr); 620 "unexpectedly changed\n", ctlr);
599 /* but if it does happen, we just ignore that device */ 621 /* but if it does happen, we just ignore that device */
600 } 622 }
601 } 623 }
@@ -1012,7 +1034,8 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
1012 1034
1013static int 1035static int
1014cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 1036cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
1015 unsigned char *buf, unsigned char bufsize) 1037 unsigned char page, unsigned char *buf,
1038 unsigned char bufsize)
1016{ 1039{
1017 int rc; 1040 int rc;
1018 CommandList_struct *cp; 1041 CommandList_struct *cp;
@@ -1032,8 +1055,8 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
1032 ei = cp->err_info; 1055 ei = cp->err_info;
1033 1056
1034 cdb[0] = CISS_INQUIRY; 1057 cdb[0] = CISS_INQUIRY;
1035 cdb[1] = 0; 1058 cdb[1] = (page != 0);
1036 cdb[2] = 0; 1059 cdb[2] = page;
1037 cdb[3] = 0; 1060 cdb[3] = 0;
1038 cdb[4] = bufsize; 1061 cdb[4] = bufsize;
1039 cdb[5] = 0; 1062 cdb[5] = 0;
@@ -1053,6 +1076,25 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
1053 return rc; 1076 return rc;
1054} 1077}
1055 1078
1079/* Get the device id from inquiry page 0x83 */
1080static int cciss_scsi_get_device_id(ctlr_info_t *c, unsigned char *scsi3addr,
1081 unsigned char *device_id, int buflen)
1082{
1083 int rc;
1084 unsigned char *buf;
1085
1086 if (buflen > 16)
1087 buflen = 16;
1088 buf = kzalloc(64, GFP_KERNEL);
1089 if (!buf)
1090 return -1;
1091 rc = cciss_scsi_do_inquiry(c, scsi3addr, 0x83, buf, 64);
1092 if (rc == 0)
1093 memcpy(device_id, &buf[8], buflen);
1094 kfree(buf);
1095 return rc != 0;
1096}
1097
1056static int 1098static int
1057cciss_scsi_do_report_phys_luns(ctlr_info_t *c, 1099cciss_scsi_do_report_phys_luns(ctlr_info_t *c,
1058 ReportLunData_struct *buf, int bufsize) 1100 ReportLunData_struct *buf, int bufsize)
@@ -1142,25 +1184,21 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1142 ctlr_info_t *c; 1184 ctlr_info_t *c;
1143 __u32 num_luns=0; 1185 __u32 num_luns=0;
1144 unsigned char *ch; 1186 unsigned char *ch;
1145 /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */ 1187 struct cciss_scsi_dev_t *currentsd, *this_device;
1146 struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
1147 int ncurrent=0; 1188 int ncurrent=0;
1148 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; 1189 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1149 int i; 1190 int i;
1150 1191
1151 c = (ctlr_info_t *) hba[cntl_num]; 1192 c = (ctlr_info_t *) hba[cntl_num];
1152 ld_buff = kzalloc(reportlunsize, GFP_KERNEL); 1193 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
1153 if (ld_buff == NULL) {
1154 printk(KERN_ERR "cciss: out of memory\n");
1155 return;
1156 }
1157 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); 1194 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
1158 if (inq_buff == NULL) { 1195 currentsd = kzalloc(sizeof(*currentsd) *
1159 printk(KERN_ERR "cciss: out of memory\n"); 1196 (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
1160 kfree(ld_buff); 1197 if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1161 return; 1198 printk(KERN_ERR "cciss: out of memory\n");
1199 goto out;
1162 } 1200 }
1163 1201 this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
1164 if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) { 1202 if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) {
1165 ch = &ld_buff->LUNListLength[0]; 1203 ch = &ld_buff->LUNListLength[0];
1166 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8; 1204 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
@@ -1179,23 +1217,34 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1179 1217
1180 1218
1181 /* adjust our table of devices */ 1219 /* adjust our table of devices */
1182 for(i=0; i<num_luns; i++) 1220 for (i = 0; i < num_luns; i++) {
1183 {
1184 int devtype;
1185
1186 /* for each physical lun, do an inquiry */ 1221 /* for each physical lun, do an inquiry */
1187 if (ld_buff->LUN[i][3] & 0xC0) continue; 1222 if (ld_buff->LUN[i][3] & 0xC0) continue;
1188 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); 1223 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
1189 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); 1224 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1190 1225
1191 if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff, 1226 if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff,
1192 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { 1227 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
1193 /* Inquiry failed (msg printed already) */ 1228 /* Inquiry failed (msg printed already) */
1194 devtype = 0; /* so we will skip this device. */ 1229 continue; /* so we will skip this device. */
1195 } else /* what kind of device is this? */ 1230
1196 devtype = (inq_buff[0] & 0x1f); 1231 this_device->devtype = (inq_buff[0] & 0x1f);
1197 1232 this_device->bus = -1;
1198 switch (devtype) 1233 this_device->target = -1;
1234 this_device->lun = -1;
1235 memcpy(this_device->scsi3addr, scsi3addr, 8);
1236 memcpy(this_device->vendor, &inq_buff[8],
1237 sizeof(this_device->vendor));
1238 memcpy(this_device->model, &inq_buff[16],
1239 sizeof(this_device->model));
1240 memcpy(this_device->revision, &inq_buff[32],
1241 sizeof(this_device->revision));
1242 memset(this_device->device_id, 0,
1243 sizeof(this_device->device_id));
1244 cciss_scsi_get_device_id(hba[cntl_num], scsi3addr,
1245 this_device->device_id, sizeof(this_device->device_id));
1246
1247 switch (this_device->devtype)
1199 { 1248 {
1200 case 0x05: /* CD-ROM */ { 1249 case 0x05: /* CD-ROM */ {
1201 1250
@@ -1220,15 +1269,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1220 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { 1269 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1221 printk(KERN_INFO "cciss%d: %s ignored, " 1270 printk(KERN_INFO "cciss%d: %s ignored, "
1222 "too many devices.\n", cntl_num, 1271 "too many devices.\n", cntl_num,
1223 scsi_device_type(devtype)); 1272 scsi_device_type(this_device->devtype));
1224 break; 1273 break;
1225 } 1274 }
1226 memcpy(&currentsd[ncurrent].scsi3addr[0], 1275 currentsd[ncurrent] = *this_device;
1227 &scsi3addr[0], 8);
1228 currentsd[ncurrent].devtype = devtype;
1229 currentsd[ncurrent].bus = -1;
1230 currentsd[ncurrent].target = -1;
1231 currentsd[ncurrent].lun = -1;
1232 ncurrent++; 1276 ncurrent++;
1233 break; 1277 break;
1234 default: 1278 default:
@@ -1240,6 +1284,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1240out: 1284out:
1241 kfree(inq_buff); 1285 kfree(inq_buff);
1242 kfree(ld_buff); 1286 kfree(ld_buff);
1287 kfree(currentsd);
1243 return; 1288 return;
1244} 1289}
1245 1290
diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
index d9c2c586502f..7b750245ae76 100644
--- a/drivers/block/cciss_scsi.h
+++ b/drivers/block/cciss_scsi.h
@@ -66,6 +66,10 @@ struct cciss_scsi_dev_t {
66 int devtype; 66 int devtype;
67 int bus, target, lun; /* as presented to the OS */ 67 int bus, target, lun; /* as presented to the OS */
68 unsigned char scsi3addr[8]; /* as presented to the HW */ 68 unsigned char scsi3addr[8]; /* as presented to the HW */
69 unsigned char device_id[16]; /* from inquiry pg. 0x83 */
70 unsigned char vendor[8]; /* bytes 8-15 of inquiry data */
71 unsigned char model[16]; /* bytes 16-31 of inquiry data */
72 unsigned char revision[4]; /* bytes 32-35 of inquiry data */
69}; 73};
70 74
71struct cciss_scsi_hba_t { 75struct cciss_scsi_hba_t {