Commit 905bd78f2188da69e74966918e3d71df3dff382b

Authored by scameron@beardog.cca.cpqcorp.net
Committed by Jens Axboe
1 parent 79eb014578

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>

Showing 2 changed files with 102 additions and 53 deletions Side-by-side Diff

drivers/block/cciss_scsi.c
... ... @@ -365,7 +365,7 @@
365 365  
366 366 static int
367 367 cciss_scsi_add_entry(int ctlr, int hostno,
368   - unsigned char *scsi3addr, int devtype,
  368 + struct cciss_scsi_dev_t *device,
369 369 struct scsi2map *added, int *nadded)
370 370 {
371 371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
372 372  
... ... @@ -384,12 +384,12 @@
384 384 lun = 0;
385 385 /* Is this device a non-zero lun of a multi-lun device */
386 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 388 /* Search through our list and find the device which */
389 389 /* has the same 8 byte LUN address, excepting byte 4. */
390 390 /* Assign the same bus and target for this new LUN. */
391 391 /* Use the logical unit number from the firmware. */
392   - memcpy(addr1, scsi3addr, 8);
  392 + memcpy(addr1, device->scsi3addr, 8);
393 393 addr1[4] = 0;
394 394 for (i = 0; i < n; i++) {
395 395 sd = &ccissscsi[ctlr].dev[i];
... ... @@ -399,7 +399,7 @@
399 399 if (memcmp(addr1, addr2, 8) == 0) {
400 400 bus = sd->bus;
401 401 target = sd->target;
402   - lun = scsi3addr[4];
  402 + lun = device->scsi3addr[4];
403 403 break;
404 404 }
405 405 }
... ... @@ -420,8 +420,12 @@
420 420 added[*nadded].lun = sd->lun;
421 421 (*nadded)++;
422 422  
423   - memcpy(&sd->scsi3addr[0], scsi3addr, 8);
424   - sd->devtype = devtype;
  423 + memcpy(sd->scsi3addr, device->scsi3addr, 8);
  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 429 ccissscsi[ctlr].ndevices++;
426 430  
427 431 /* initially, (before registering with scsi layer) we don't
... ... @@ -487,6 +491,22 @@
487 491 CPQ_TAPE_UNLOCK(ctlr, flags);
488 492 }
489 493  
  494 +static 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 +
490 510 static int
491 511 adjust_cciss_scsi_table(int ctlr, int hostno,
492 512 struct cciss_scsi_dev_t sd[], int nsds)
... ... @@ -532,7 +552,7 @@
532 552 for (j=0;j<nsds;j++) {
533 553 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
534 554 csd->scsi3addr)) {
535   - if (sd[j].devtype == csd->devtype)
  555 + if (device_is_the_same(&sd[j], csd))
536 556 found=2;
537 557 else
538 558 found=1;
539 559  
540 560  
541 561  
... ... @@ -548,22 +568,26 @@
548 568 cciss_scsi_remove_entry(ctlr, hostno, i,
549 569 removed, &nremoved);
550 570 /* remove ^^^, hence i not incremented */
551   - }
552   - else if (found == 1) { /* device is different kind */
  571 + } else if (found == 1) { /* device is different in some way */
553 572 changes++;
554   - printk("cciss%d: device c%db%dt%dl%d type changed "
555   - "(device type now %s).\n",
556   - ctlr, hostno, csd->bus, csd->target, csd->lun,
557   - scsi_device_type(csd->devtype));
  573 + printk("cciss%d: device c%db%dt%dl%d has changed.\n",
  574 + ctlr, hostno, csd->bus, csd->target, csd->lun);
558 575 cciss_scsi_remove_entry(ctlr, hostno, i,
559 576 removed, &nremoved);
560 577 /* remove ^^^, hence i not incremented */
561   - if (cciss_scsi_add_entry(ctlr, hostno,
562   - &sd[j].scsi3addr[0], sd[j].devtype,
  578 + if (cciss_scsi_add_entry(ctlr, hostno, &sd[j],
563 579 added, &nadded) != 0)
564 580 /* we just removed one, so add can't fail. */
565 581 BUG();
566 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 591 } else /* device is same as it ever was, */
568 592 i++; /* so just move along. */
569 593 }
... ... @@ -577,7 +601,7 @@
577 601 csd = &ccissscsi[ctlr].dev[j];
578 602 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
579 603 csd->scsi3addr)) {
580   - if (sd[i].devtype == csd->devtype)
  604 + if (device_is_the_same(&sd[i], csd))
581 605 found=2; /* found device */
582 606 else
583 607 found=1; /* found a bug. */
584 608  
... ... @@ -586,16 +610,14 @@
586 610 }
587 611 if (!found) {
588 612 changes++;
589   - if (cciss_scsi_add_entry(ctlr, hostno,
590   -
591   - &sd[i].scsi3addr[0], sd[i].devtype,
  613 + if (cciss_scsi_add_entry(ctlr, hostno, &sd[i],
592 614 added, &nadded) != 0)
593 615 break;
594 616 } else if (found == 1) {
595 617 /* should never happen... */
596 618 changes++;
597   - printk("cciss%d: device unexpectedly changed type\n",
598   - ctlr);
  619 + printk(KERN_WARNING "cciss%d: device "
  620 + "unexpectedly changed\n", ctlr);
599 621 /* but if it does happen, we just ignore that device */
600 622 }
601 623 }
... ... @@ -1012,7 +1034,8 @@
1012 1034  
1013 1035 static int
1014 1036 cciss_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 1040 int rc;
1018 1041 CommandList_struct *cp;
... ... @@ -1032,8 +1055,8 @@
1032 1055 ei = cp->err_info;
1033 1056  
1034 1057 cdb[0] = CISS_INQUIRY;
1035   - cdb[1] = 0;
1036   - cdb[2] = 0;
  1058 + cdb[1] = (page != 0);
  1059 + cdb[2] = page;
1037 1060 cdb[3] = 0;
1038 1061 cdb[4] = bufsize;
1039 1062 cdb[5] = 0;
... ... @@ -1053,6 +1076,25 @@
1053 1076 return rc;
1054 1077 }
1055 1078  
  1079 +/* Get the device id from inquiry page 0x83 */
  1080 +static 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 +
1056 1098 static int
1057 1099 cciss_scsi_do_report_phys_luns(ctlr_info_t *c,
1058 1100 ReportLunData_struct *buf, int bufsize)
1059 1101  
1060 1102  
1061 1103  
... ... @@ -1142,25 +1184,21 @@
1142 1184 ctlr_info_t *c;
1143 1185 __u32 num_luns=0;
1144 1186 unsigned char *ch;
1145   - /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */
1146   - struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
  1187 + struct cciss_scsi_dev_t *currentsd, *this_device;
1147 1188 int ncurrent=0;
1148 1189 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1149 1190 int i;
1150 1191  
1151 1192 c = (ctlr_info_t *) hba[cntl_num];
1152 1193 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
1153   - if (ld_buff == NULL) {
  1194 + inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
  1195 + currentsd = kzalloc(sizeof(*currentsd) *
  1196 + (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
  1197 + if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1154 1198 printk(KERN_ERR "cciss: out of memory\n");
1155   - return;
  1199 + goto out;
1156 1200 }
1157   - inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
1158   - if (inq_buff == NULL) {
1159   - printk(KERN_ERR "cciss: out of memory\n");
1160   - kfree(ld_buff);
1161   - return;
1162   - }
1163   -
  1201 + this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
1164 1202 if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) {
1165 1203 ch = &ld_buff->LUNListLength[0];
1166 1204 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
1167 1205  
1168 1206  
1169 1207  
... ... @@ -1179,23 +1217,34 @@
1179 1217  
1180 1218  
1181 1219 /* adjust our table of devices */
1182   - for(i=0; i<num_luns; i++)
1183   - {
1184   - int devtype;
1185   -
  1220 + for (i = 0; i < num_luns; i++) {
1186 1221 /* for each physical lun, do an inquiry */
1187 1222 if (ld_buff->LUN[i][3] & 0xC0) continue;
1188 1223 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
1189 1224 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1190 1225  
1191   - if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
1192   - (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
  1226 + if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff,
  1227 + (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
1193 1228 /* Inquiry failed (msg printed already) */
1194   - devtype = 0; /* so we will skip this device. */
1195   - } else /* what kind of device is this? */
1196   - devtype = (inq_buff[0] & 0x1f);
  1229 + continue; /* so we will skip this device. */
1197 1230  
1198   - switch (devtype)
  1231 + this_device->devtype = (inq_buff[0] & 0x1f);
  1232 + this_device->bus = -1;
  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 1249 case 0x05: /* CD-ROM */ {
1201 1250  
1202 1251  
... ... @@ -1220,15 +1269,10 @@
1220 1269 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1221 1270 printk(KERN_INFO "cciss%d: %s ignored, "
1222 1271 "too many devices.\n", cntl_num,
1223   - scsi_device_type(devtype));
  1272 + scsi_device_type(this_device->devtype));
1224 1273 break;
1225 1274 }
1226   - memcpy(&currentsd[ncurrent].scsi3addr[0],
1227   - &scsi3addr[0], 8);
1228   - currentsd[ncurrent].devtype = devtype;
1229   - currentsd[ncurrent].bus = -1;
1230   - currentsd[ncurrent].target = -1;
1231   - currentsd[ncurrent].lun = -1;
  1275 + currentsd[ncurrent] = *this_device;
1232 1276 ncurrent++;
1233 1277 break;
1234 1278 default:
... ... @@ -1240,6 +1284,7 @@
1240 1284 out:
1241 1285 kfree(inq_buff);
1242 1286 kfree(ld_buff);
  1287 + kfree(currentsd);
1243 1288 return;
1244 1289 }
1245 1290  
drivers/block/cciss_scsi.h
... ... @@ -66,6 +66,10 @@
66 66 int devtype;
67 67 int bus, target, lun; /* as presented to the OS */
68 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  
71 75 struct cciss_scsi_hba_t {