diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:41:28 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:41:28 -0400 |
commit | 142e27fc8a3619471669d6241784eec9167c47d1 (patch) | |
tree | e88850b63ec910ee28874f93c43fb66421bb8119 /drivers/scsi/scsi_scan.c | |
parent | a9053d0494d3c92807701c0f47df61d50c971581 (diff) | |
parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 128 |
1 files changed, 58 insertions, 70 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 48edd67982a5..19c9a232a754 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout, | |||
111 | 111 | ||
112 | /** | 112 | /** |
113 | * scsi_unlock_floptical - unlock device via a special MODE SENSE command | 113 | * scsi_unlock_floptical - unlock device via a special MODE SENSE command |
114 | * @sreq: used to send the command | 114 | * @sdev: scsi device to send command to |
115 | * @result: area to store the result of the MODE SENSE | 115 | * @result: area to store the result of the MODE SENSE |
116 | * | 116 | * |
117 | * Description: | 117 | * Description: |
118 | * Send a vendor specific MODE SENSE (not a MODE SELECT) command using | 118 | * Send a vendor specific MODE SENSE (not a MODE SELECT) command. |
119 | * @sreq to unlock a device, storing the (unused) results into result. | ||
120 | * Called for BLIST_KEY devices. | 119 | * Called for BLIST_KEY devices. |
121 | **/ | 120 | **/ |
122 | static void scsi_unlock_floptical(struct scsi_request *sreq, | 121 | static void scsi_unlock_floptical(struct scsi_device *sdev, |
123 | unsigned char *result) | 122 | unsigned char *result) |
124 | { | 123 | { |
125 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; | 124 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; |
@@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct scsi_request *sreq, | |||
129 | scsi_cmd[1] = 0; | 128 | scsi_cmd[1] = 0; |
130 | scsi_cmd[2] = 0x2e; | 129 | scsi_cmd[2] = 0x2e; |
131 | scsi_cmd[3] = 0; | 130 | scsi_cmd[3] = 0; |
132 | scsi_cmd[4] = 0x2a; /* size */ | 131 | scsi_cmd[4] = 0x2a; /* size */ |
133 | scsi_cmd[5] = 0; | 132 | scsi_cmd[5] = 0; |
134 | sreq->sr_cmd_len = 0; | 133 | scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, |
135 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 134 | SCSI_TIMEOUT, 3); |
136 | scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3); | ||
137 | } | 135 | } |
138 | 136 | ||
139 | /** | 137 | /** |
@@ -433,26 +431,25 @@ void scsi_target_reap(struct scsi_target *starget) | |||
433 | 431 | ||
434 | /** | 432 | /** |
435 | * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY | 433 | * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY |
436 | * @sreq: used to send the INQUIRY | 434 | * @sdev: scsi_device to probe |
437 | * @inq_result: area to store the INQUIRY result | 435 | * @inq_result: area to store the INQUIRY result |
436 | * @result_len: len of inq_result | ||
438 | * @bflags: store any bflags found here | 437 | * @bflags: store any bflags found here |
439 | * | 438 | * |
440 | * Description: | 439 | * Description: |
441 | * Probe the lun associated with @sreq using a standard SCSI INQUIRY; | 440 | * Probe the lun associated with @req using a standard SCSI INQUIRY; |
442 | * | 441 | * |
443 | * If the INQUIRY is successful, sreq->sr_result is zero and: the | 442 | * If the INQUIRY is successful, zero is returned and the |
444 | * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length | 443 | * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length |
445 | * are copied to the Scsi_Device at @sreq->sr_device (sdev); | 444 | * are copied to the Scsi_Device any flags value is stored in *@bflags. |
446 | * any flags value is stored in *@bflags. | ||
447 | **/ | 445 | **/ |
448 | static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | 446 | static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, |
449 | int *bflags) | 447 | int result_len, int *bflags) |
450 | { | 448 | { |
451 | struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ | ||
452 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; | 449 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; |
453 | int first_inquiry_len, try_inquiry_len, next_inquiry_len; | 450 | int first_inquiry_len, try_inquiry_len, next_inquiry_len; |
454 | int response_len = 0; | 451 | int response_len = 0; |
455 | int pass, count; | 452 | int pass, count, result; |
456 | struct scsi_sense_hdr sshdr; | 453 | struct scsi_sense_hdr sshdr; |
457 | 454 | ||
458 | *bflags = 0; | 455 | *bflags = 0; |
@@ -475,28 +472,26 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
475 | memset(scsi_cmd, 0, 6); | 472 | memset(scsi_cmd, 0, 6); |
476 | scsi_cmd[0] = INQUIRY; | 473 | scsi_cmd[0] = INQUIRY; |
477 | scsi_cmd[4] = (unsigned char) try_inquiry_len; | 474 | scsi_cmd[4] = (unsigned char) try_inquiry_len; |
478 | sreq->sr_cmd_len = 0; | ||
479 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
480 | 475 | ||
481 | memset(inq_result, 0, try_inquiry_len); | 476 | memset(inq_result, 0, try_inquiry_len); |
482 | scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, | 477 | |
483 | try_inquiry_len, | 478 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
484 | HZ/2 + HZ*scsi_inq_timeout, 3); | 479 | inq_result, try_inquiry_len, &sshdr, |
480 | HZ / 2 + HZ * scsi_inq_timeout, 3); | ||
485 | 481 | ||
486 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " | 482 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " |
487 | "with code 0x%x\n", | 483 | "with code 0x%x\n", |
488 | sreq->sr_result ? "failed" : "successful", | 484 | result ? "failed" : "successful", result)); |
489 | sreq->sr_result)); | ||
490 | 485 | ||
491 | if (sreq->sr_result) { | 486 | if (result) { |
492 | /* | 487 | /* |
493 | * not-ready to ready transition [asc/ascq=0x28/0x0] | 488 | * not-ready to ready transition [asc/ascq=0x28/0x0] |
494 | * or power-on, reset [asc/ascq=0x29/0x0], continue. | 489 | * or power-on, reset [asc/ascq=0x29/0x0], continue. |
495 | * INQUIRY should not yield UNIT_ATTENTION | 490 | * INQUIRY should not yield UNIT_ATTENTION |
496 | * but many buggy devices do so anyway. | 491 | * but many buggy devices do so anyway. |
497 | */ | 492 | */ |
498 | if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && | 493 | if ((driver_byte(result) & DRIVER_SENSE) && |
499 | scsi_request_normalize_sense(sreq, &sshdr)) { | 494 | scsi_sense_valid(&sshdr)) { |
500 | if ((sshdr.sense_key == UNIT_ATTENTION) && | 495 | if ((sshdr.sense_key == UNIT_ATTENTION) && |
501 | ((sshdr.asc == 0x28) || | 496 | ((sshdr.asc == 0x28) || |
502 | (sshdr.asc == 0x29)) && | 497 | (sshdr.asc == 0x29)) && |
@@ -507,7 +502,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
507 | break; | 502 | break; |
508 | } | 503 | } |
509 | 504 | ||
510 | if (sreq->sr_result == 0) { | 505 | if (result == 0) { |
511 | response_len = (unsigned char) inq_result[4] + 5; | 506 | response_len = (unsigned char) inq_result[4] + 5; |
512 | if (response_len > 255) | 507 | if (response_len > 255) |
513 | response_len = first_inquiry_len; /* sanity */ | 508 | response_len = first_inquiry_len; /* sanity */ |
@@ -556,8 +551,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
556 | 551 | ||
557 | /* If the last transfer attempt got an error, assume the | 552 | /* If the last transfer attempt got an error, assume the |
558 | * peripheral doesn't exist or is dead. */ | 553 | * peripheral doesn't exist or is dead. */ |
559 | if (sreq->sr_result) | 554 | if (result) |
560 | return; | 555 | return -EIO; |
561 | 556 | ||
562 | /* Don't report any more data than the device says is valid */ | 557 | /* Don't report any more data than the device says is valid */ |
563 | sdev->inquiry_len = min(try_inquiry_len, response_len); | 558 | sdev->inquiry_len = min(try_inquiry_len, response_len); |
@@ -593,7 +588,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
593 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) | 588 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) |
594 | sdev->scsi_level++; | 589 | sdev->scsi_level++; |
595 | 590 | ||
596 | return; | 591 | return 0; |
597 | } | 592 | } |
598 | 593 | ||
599 | /** | 594 | /** |
@@ -800,9 +795,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
800 | void *hostdata) | 795 | void *hostdata) |
801 | { | 796 | { |
802 | struct scsi_device *sdev; | 797 | struct scsi_device *sdev; |
803 | struct scsi_request *sreq; | ||
804 | unsigned char *result; | 798 | unsigned char *result; |
805 | int bflags, res = SCSI_SCAN_NO_RESPONSE; | 799 | int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; |
806 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 800 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
807 | 801 | ||
808 | /* | 802 | /* |
@@ -831,16 +825,13 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
831 | sdev = scsi_alloc_sdev(starget, lun, hostdata); | 825 | sdev = scsi_alloc_sdev(starget, lun, hostdata); |
832 | if (!sdev) | 826 | if (!sdev) |
833 | goto out; | 827 | goto out; |
834 | sreq = scsi_allocate_request(sdev, GFP_ATOMIC); | 828 | |
835 | if (!sreq) | 829 | result = kmalloc(result_len, GFP_ATOMIC | |
836 | goto out_free_sdev; | ||
837 | result = kmalloc(256, GFP_ATOMIC | | ||
838 | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); | 830 | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); |
839 | if (!result) | 831 | if (!result) |
840 | goto out_free_sreq; | 832 | goto out_free_sdev; |
841 | 833 | ||
842 | scsi_probe_lun(sreq, result, &bflags); | 834 | if (scsi_probe_lun(sdev, result, result_len, &bflags)) |
843 | if (sreq->sr_result) | ||
844 | goto out_free_result; | 835 | goto out_free_result; |
845 | 836 | ||
846 | /* | 837 | /* |
@@ -868,7 +859,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
868 | if (res == SCSI_SCAN_LUN_PRESENT) { | 859 | if (res == SCSI_SCAN_LUN_PRESENT) { |
869 | if (bflags & BLIST_KEY) { | 860 | if (bflags & BLIST_KEY) { |
870 | sdev->lockable = 0; | 861 | sdev->lockable = 0; |
871 | scsi_unlock_floptical(sreq, result); | 862 | scsi_unlock_floptical(sdev, result); |
872 | } | 863 | } |
873 | if (bflagsp) | 864 | if (bflagsp) |
874 | *bflagsp = bflags; | 865 | *bflagsp = bflags; |
@@ -876,8 +867,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
876 | 867 | ||
877 | out_free_result: | 868 | out_free_result: |
878 | kfree(result); | 869 | kfree(result); |
879 | out_free_sreq: | ||
880 | scsi_release_request(sreq); | ||
881 | out_free_sdev: | 870 | out_free_sdev: |
882 | if (res == SCSI_SCAN_LUN_PRESENT) { | 871 | if (res == SCSI_SCAN_LUN_PRESENT) { |
883 | if (sdevp) { | 872 | if (sdevp) { |
@@ -1070,8 +1059,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1070 | unsigned int lun; | 1059 | unsigned int lun; |
1071 | unsigned int num_luns; | 1060 | unsigned int num_luns; |
1072 | unsigned int retries; | 1061 | unsigned int retries; |
1062 | int result; | ||
1073 | struct scsi_lun *lunp, *lun_data; | 1063 | struct scsi_lun *lunp, *lun_data; |
1074 | struct scsi_request *sreq; | ||
1075 | u8 *data; | 1064 | u8 *data; |
1076 | struct scsi_sense_hdr sshdr; | 1065 | struct scsi_sense_hdr sshdr; |
1077 | struct scsi_target *starget = scsi_target(sdev); | 1066 | struct scsi_target *starget = scsi_target(sdev); |
@@ -1089,10 +1078,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1089 | if (bflags & BLIST_NOLUN) | 1078 | if (bflags & BLIST_NOLUN) |
1090 | return 0; | 1079 | return 0; |
1091 | 1080 | ||
1092 | sreq = scsi_allocate_request(sdev, GFP_ATOMIC); | ||
1093 | if (!sreq) | ||
1094 | goto out; | ||
1095 | |||
1096 | sprintf(devname, "host %d channel %d id %d", | 1081 | sprintf(devname, "host %d channel %d id %d", |
1097 | sdev->host->host_no, sdev->channel, sdev->id); | 1082 | sdev->host->host_no, sdev->channel, sdev->id); |
1098 | 1083 | ||
@@ -1110,7 +1095,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1110 | lun_data = kmalloc(length, GFP_ATOMIC | | 1095 | lun_data = kmalloc(length, GFP_ATOMIC | |
1111 | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); | 1096 | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); |
1112 | if (!lun_data) | 1097 | if (!lun_data) |
1113 | goto out_release_request; | 1098 | goto out; |
1114 | 1099 | ||
1115 | scsi_cmd[0] = REPORT_LUNS; | 1100 | scsi_cmd[0] = REPORT_LUNS; |
1116 | 1101 | ||
@@ -1129,8 +1114,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1129 | 1114 | ||
1130 | scsi_cmd[10] = 0; /* reserved */ | 1115 | scsi_cmd[10] = 0; /* reserved */ |
1131 | scsi_cmd[11] = 0; /* control */ | 1116 | scsi_cmd[11] = 0; /* control */ |
1132 | sreq->sr_cmd_len = 0; | ||
1133 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
1134 | 1117 | ||
1135 | /* | 1118 | /* |
1136 | * We can get a UNIT ATTENTION, for example a power on/reset, so | 1119 | * We can get a UNIT ATTENTION, for example a power on/reset, so |
@@ -1146,29 +1129,29 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1146 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" | 1129 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" |
1147 | " REPORT LUNS to %s (try %d)\n", devname, | 1130 | " REPORT LUNS to %s (try %d)\n", devname, |
1148 | retries)); | 1131 | retries)); |
1149 | scsi_wait_req(sreq, scsi_cmd, lun_data, length, | 1132 | |
1150 | SCSI_TIMEOUT + 4*HZ, 3); | 1133 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
1134 | lun_data, length, &sshdr, | ||
1135 | SCSI_TIMEOUT + 4 * HZ, 3); | ||
1136 | |||
1151 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" | 1137 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" |
1152 | " %s (try %d) result 0x%x\n", sreq->sr_result | 1138 | " %s (try %d) result 0x%x\n", result |
1153 | ? "failed" : "successful", retries, | 1139 | ? "failed" : "successful", retries, result)); |
1154 | sreq->sr_result)); | 1140 | if (result == 0) |
1155 | if (sreq->sr_result == 0) | ||
1156 | break; | 1141 | break; |
1157 | else if (scsi_request_normalize_sense(sreq, &sshdr)) { | 1142 | else if (scsi_sense_valid(&sshdr)) { |
1158 | if (sshdr.sense_key != UNIT_ATTENTION) | 1143 | if (sshdr.sense_key != UNIT_ATTENTION) |
1159 | break; | 1144 | break; |
1160 | } | 1145 | } |
1161 | } | 1146 | } |
1162 | 1147 | ||
1163 | if (sreq->sr_result) { | 1148 | if (result) { |
1164 | /* | 1149 | /* |
1165 | * The device probably does not support a REPORT LUN command | 1150 | * The device probably does not support a REPORT LUN command |
1166 | */ | 1151 | */ |
1167 | kfree(lun_data); | 1152 | kfree(lun_data); |
1168 | scsi_release_request(sreq); | ||
1169 | return 1; | 1153 | return 1; |
1170 | } | 1154 | } |
1171 | scsi_release_request(sreq); | ||
1172 | 1155 | ||
1173 | /* | 1156 | /* |
1174 | * Get the length from the first four bytes of lun_data. | 1157 | * Get the length from the first four bytes of lun_data. |
@@ -1242,8 +1225,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1242 | kfree(lun_data); | 1225 | kfree(lun_data); |
1243 | return 0; | 1226 | return 0; |
1244 | 1227 | ||
1245 | out_release_request: | ||
1246 | scsi_release_request(sreq); | ||
1247 | out: | 1228 | out: |
1248 | /* | 1229 | /* |
1249 | * We are out of memory, don't try scanning any further. | 1230 | * We are out of memory, don't try scanning any further. |
@@ -1265,9 +1246,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1265 | 1246 | ||
1266 | get_device(&starget->dev); | 1247 | get_device(&starget->dev); |
1267 | down(&shost->scan_mutex); | 1248 | down(&shost->scan_mutex); |
1268 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); | 1249 | if (scsi_host_scan_allowed(shost)) { |
1269 | if (res != SCSI_SCAN_LUN_PRESENT) | 1250 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, |
1270 | sdev = ERR_PTR(-ENODEV); | 1251 | hostdata); |
1252 | if (res != SCSI_SCAN_LUN_PRESENT) | ||
1253 | sdev = ERR_PTR(-ENODEV); | ||
1254 | } | ||
1271 | up(&shost->scan_mutex); | 1255 | up(&shost->scan_mutex); |
1272 | scsi_target_reap(starget); | 1256 | scsi_target_reap(starget); |
1273 | put_device(&starget->dev); | 1257 | put_device(&starget->dev); |
@@ -1417,11 +1401,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1417 | return -EINVAL; | 1401 | return -EINVAL; |
1418 | 1402 | ||
1419 | down(&shost->scan_mutex); | 1403 | down(&shost->scan_mutex); |
1420 | if (channel == SCAN_WILD_CARD) | 1404 | if (scsi_host_scan_allowed(shost)) { |
1421 | for (channel = 0; channel <= shost->max_channel; channel++) | 1405 | if (channel == SCAN_WILD_CARD) |
1406 | for (channel = 0; channel <= shost->max_channel; | ||
1407 | channel++) | ||
1408 | scsi_scan_channel(shost, channel, id, lun, | ||
1409 | rescan); | ||
1410 | else | ||
1422 | scsi_scan_channel(shost, channel, id, lun, rescan); | 1411 | scsi_scan_channel(shost, channel, id, lun, rescan); |
1423 | else | 1412 | } |
1424 | scsi_scan_channel(shost, channel, id, lun, rescan); | ||
1425 | up(&shost->scan_mutex); | 1413 | up(&shost->scan_mutex); |
1426 | 1414 | ||
1427 | return 0; | 1415 | return 0; |