diff options
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r-- | drivers/block/cciss_scsi.c | 151 |
1 files changed, 98 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 | ||
366 | static int | 366 | static int |
367 | cciss_scsi_add_entry(int ctlr, int hostno, | 367 | cciss_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 | ||
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 | static int | 510 | static int |
491 | adjust_cciss_scsi_table(int ctlr, int hostno, | 511 | adjust_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 | ||
1013 | static int | 1035 | static int |
1014 | cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, | 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 | 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 */ | ||
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 | static int | 1098 | static int |
1057 | cciss_scsi_do_report_phys_luns(ctlr_info_t *c, | 1099 | cciss_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 = ¤tsd[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(¤tsd[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) | |||
1240 | out: | 1284 | out: |
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 | ||