diff options
author | James Bottomley <jejb@titanic.(none)> | 2005-06-15 19:48:29 -0400 |
---|---|---|
committer | James Bottomley <jejb@titanic.(none)> | 2005-08-28 11:46:40 -0400 |
commit | 392160335c798bbe94ab3aae6ea0c85d32b81bbc (patch) | |
tree | ce664010089283f464d88cd89c11a60d35923851 /drivers/scsi/scsi_scan.c | |
parent | 8e6401187ef7fb1edc2740832b48bf47ed2c90f2 (diff) |
[SCSI] use scatter lists for all block pc requests and simplify hw handlers
Original From: Mike Christie <michaelc@cs.wisc.edu>
Add scsi_execute_req() as a replacement for scsi_wait_req()
Fixed up various pieces (added REQ_SPECIAL and caught req use after
free)
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 112 |
1 files changed, 49 insertions, 63 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 48edd67982a5..d2ca4b8fbc13 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,26 @@ 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 */ | 449 | char sense[SCSI_SENSE_BUFFERSIZE]; |
452 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; | 450 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; |
453 | int first_inquiry_len, try_inquiry_len, next_inquiry_len; | 451 | int first_inquiry_len, try_inquiry_len, next_inquiry_len; |
454 | int response_len = 0; | 452 | int response_len = 0; |
455 | int pass, count; | 453 | int pass, count, result; |
456 | struct scsi_sense_hdr sshdr; | 454 | struct scsi_sense_hdr sshdr; |
457 | 455 | ||
458 | *bflags = 0; | 456 | *bflags = 0; |
@@ -475,28 +473,28 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
475 | memset(scsi_cmd, 0, 6); | 473 | memset(scsi_cmd, 0, 6); |
476 | scsi_cmd[0] = INQUIRY; | 474 | scsi_cmd[0] = INQUIRY; |
477 | scsi_cmd[4] = (unsigned char) try_inquiry_len; | 475 | scsi_cmd[4] = (unsigned char) try_inquiry_len; |
478 | sreq->sr_cmd_len = 0; | ||
479 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
480 | 476 | ||
477 | memset(sense, 0, sizeof(sense)); | ||
481 | memset(inq_result, 0, try_inquiry_len); | 478 | memset(inq_result, 0, try_inquiry_len); |
482 | scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, | 479 | |
483 | try_inquiry_len, | 480 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, |
484 | HZ/2 + HZ*scsi_inq_timeout, 3); | 481 | inq_result, try_inquiry_len, sense, |
482 | HZ / 2 + HZ * scsi_inq_timeout, 3); | ||
485 | 483 | ||
486 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " | 484 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " |
487 | "with code 0x%x\n", | 485 | "with code 0x%x\n", |
488 | sreq->sr_result ? "failed" : "successful", | 486 | result ? "failed" : "successful", result)); |
489 | sreq->sr_result)); | ||
490 | 487 | ||
491 | if (sreq->sr_result) { | 488 | if (result) { |
492 | /* | 489 | /* |
493 | * not-ready to ready transition [asc/ascq=0x28/0x0] | 490 | * not-ready to ready transition [asc/ascq=0x28/0x0] |
494 | * or power-on, reset [asc/ascq=0x29/0x0], continue. | 491 | * or power-on, reset [asc/ascq=0x29/0x0], continue. |
495 | * INQUIRY should not yield UNIT_ATTENTION | 492 | * INQUIRY should not yield UNIT_ATTENTION |
496 | * but many buggy devices do so anyway. | 493 | * but many buggy devices do so anyway. |
497 | */ | 494 | */ |
498 | if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && | 495 | if ((driver_byte(result) & DRIVER_SENSE) && |
499 | scsi_request_normalize_sense(sreq, &sshdr)) { | 496 | scsi_normalize_sense(sense, sizeof(sense), |
497 | &sshdr)) { | ||
500 | if ((sshdr.sense_key == UNIT_ATTENTION) && | 498 | if ((sshdr.sense_key == UNIT_ATTENTION) && |
501 | ((sshdr.asc == 0x28) || | 499 | ((sshdr.asc == 0x28) || |
502 | (sshdr.asc == 0x29)) && | 500 | (sshdr.asc == 0x29)) && |
@@ -507,7 +505,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
507 | break; | 505 | break; |
508 | } | 506 | } |
509 | 507 | ||
510 | if (sreq->sr_result == 0) { | 508 | if (result == 0) { |
511 | response_len = (unsigned char) inq_result[4] + 5; | 509 | response_len = (unsigned char) inq_result[4] + 5; |
512 | if (response_len > 255) | 510 | if (response_len > 255) |
513 | response_len = first_inquiry_len; /* sanity */ | 511 | response_len = first_inquiry_len; /* sanity */ |
@@ -556,8 +554,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
556 | 554 | ||
557 | /* If the last transfer attempt got an error, assume the | 555 | /* If the last transfer attempt got an error, assume the |
558 | * peripheral doesn't exist or is dead. */ | 556 | * peripheral doesn't exist or is dead. */ |
559 | if (sreq->sr_result) | 557 | if (result) |
560 | return; | 558 | return -EIO; |
561 | 559 | ||
562 | /* Don't report any more data than the device says is valid */ | 560 | /* Don't report any more data than the device says is valid */ |
563 | sdev->inquiry_len = min(try_inquiry_len, response_len); | 561 | sdev->inquiry_len = min(try_inquiry_len, response_len); |
@@ -593,7 +591,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, | |||
593 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) | 591 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) |
594 | sdev->scsi_level++; | 592 | sdev->scsi_level++; |
595 | 593 | ||
596 | return; | 594 | return 0; |
597 | } | 595 | } |
598 | 596 | ||
599 | /** | 597 | /** |
@@ -800,9 +798,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
800 | void *hostdata) | 798 | void *hostdata) |
801 | { | 799 | { |
802 | struct scsi_device *sdev; | 800 | struct scsi_device *sdev; |
803 | struct scsi_request *sreq; | ||
804 | unsigned char *result; | 801 | unsigned char *result; |
805 | int bflags, res = SCSI_SCAN_NO_RESPONSE; | 802 | int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; |
806 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 803 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
807 | 804 | ||
808 | /* | 805 | /* |
@@ -831,16 +828,13 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
831 | sdev = scsi_alloc_sdev(starget, lun, hostdata); | 828 | sdev = scsi_alloc_sdev(starget, lun, hostdata); |
832 | if (!sdev) | 829 | if (!sdev) |
833 | goto out; | 830 | goto out; |
834 | sreq = scsi_allocate_request(sdev, GFP_ATOMIC); | 831 | |
835 | if (!sreq) | 832 | 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)); | 833 | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); |
839 | if (!result) | 834 | if (!result) |
840 | goto out_free_sreq; | 835 | goto out_free_sdev; |
841 | 836 | ||
842 | scsi_probe_lun(sreq, result, &bflags); | 837 | if (scsi_probe_lun(sdev, result, result_len, &bflags)) |
843 | if (sreq->sr_result) | ||
844 | goto out_free_result; | 838 | goto out_free_result; |
845 | 839 | ||
846 | /* | 840 | /* |
@@ -868,7 +862,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
868 | if (res == SCSI_SCAN_LUN_PRESENT) { | 862 | if (res == SCSI_SCAN_LUN_PRESENT) { |
869 | if (bflags & BLIST_KEY) { | 863 | if (bflags & BLIST_KEY) { |
870 | sdev->lockable = 0; | 864 | sdev->lockable = 0; |
871 | scsi_unlock_floptical(sreq, result); | 865 | scsi_unlock_floptical(sdev, result); |
872 | } | 866 | } |
873 | if (bflagsp) | 867 | if (bflagsp) |
874 | *bflagsp = bflags; | 868 | *bflagsp = bflags; |
@@ -876,8 +870,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
876 | 870 | ||
877 | out_free_result: | 871 | out_free_result: |
878 | kfree(result); | 872 | kfree(result); |
879 | out_free_sreq: | ||
880 | scsi_release_request(sreq); | ||
881 | out_free_sdev: | 873 | out_free_sdev: |
882 | if (res == SCSI_SCAN_LUN_PRESENT) { | 874 | if (res == SCSI_SCAN_LUN_PRESENT) { |
883 | if (sdevp) { | 875 | if (sdevp) { |
@@ -1065,13 +1057,14 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1065 | int rescan) | 1057 | int rescan) |
1066 | { | 1058 | { |
1067 | char devname[64]; | 1059 | char devname[64]; |
1060 | char sense[SCSI_SENSE_BUFFERSIZE]; | ||
1068 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; | 1061 | unsigned char scsi_cmd[MAX_COMMAND_SIZE]; |
1069 | unsigned int length; | 1062 | unsigned int length; |
1070 | unsigned int lun; | 1063 | unsigned int lun; |
1071 | unsigned int num_luns; | 1064 | unsigned int num_luns; |
1072 | unsigned int retries; | 1065 | unsigned int retries; |
1066 | int result; | ||
1073 | struct scsi_lun *lunp, *lun_data; | 1067 | struct scsi_lun *lunp, *lun_data; |
1074 | struct scsi_request *sreq; | ||
1075 | u8 *data; | 1068 | u8 *data; |
1076 | struct scsi_sense_hdr sshdr; | 1069 | struct scsi_sense_hdr sshdr; |
1077 | struct scsi_target *starget = scsi_target(sdev); | 1070 | struct scsi_target *starget = scsi_target(sdev); |
@@ -1089,10 +1082,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1089 | if (bflags & BLIST_NOLUN) | 1082 | if (bflags & BLIST_NOLUN) |
1090 | return 0; | 1083 | return 0; |
1091 | 1084 | ||
1092 | sreq = scsi_allocate_request(sdev, GFP_ATOMIC); | ||
1093 | if (!sreq) | ||
1094 | goto out; | ||
1095 | |||
1096 | sprintf(devname, "host %d channel %d id %d", | 1085 | sprintf(devname, "host %d channel %d id %d", |
1097 | sdev->host->host_no, sdev->channel, sdev->id); | 1086 | sdev->host->host_no, sdev->channel, sdev->id); |
1098 | 1087 | ||
@@ -1110,7 +1099,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1110 | lun_data = kmalloc(length, GFP_ATOMIC | | 1099 | lun_data = kmalloc(length, GFP_ATOMIC | |
1111 | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); | 1100 | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); |
1112 | if (!lun_data) | 1101 | if (!lun_data) |
1113 | goto out_release_request; | 1102 | goto out; |
1114 | 1103 | ||
1115 | scsi_cmd[0] = REPORT_LUNS; | 1104 | scsi_cmd[0] = REPORT_LUNS; |
1116 | 1105 | ||
@@ -1129,8 +1118,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1129 | 1118 | ||
1130 | scsi_cmd[10] = 0; /* reserved */ | 1119 | scsi_cmd[10] = 0; /* reserved */ |
1131 | scsi_cmd[11] = 0; /* control */ | 1120 | scsi_cmd[11] = 0; /* control */ |
1132 | sreq->sr_cmd_len = 0; | ||
1133 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
1134 | 1121 | ||
1135 | /* | 1122 | /* |
1136 | * We can get a UNIT ATTENTION, for example a power on/reset, so | 1123 | * We can get a UNIT ATTENTION, for example a power on/reset, so |
@@ -1146,29 +1133,30 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1146 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" | 1133 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" |
1147 | " REPORT LUNS to %s (try %d)\n", devname, | 1134 | " REPORT LUNS to %s (try %d)\n", devname, |
1148 | retries)); | 1135 | retries)); |
1149 | scsi_wait_req(sreq, scsi_cmd, lun_data, length, | 1136 | |
1150 | SCSI_TIMEOUT + 4*HZ, 3); | 1137 | memset(sense, 0, sizeof(sense)); |
1138 | result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, | ||
1139 | lun_data, length, sense, | ||
1140 | SCSI_TIMEOUT + 4 * HZ, 3); | ||
1141 | |||
1151 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" | 1142 | SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" |
1152 | " %s (try %d) result 0x%x\n", sreq->sr_result | 1143 | " %s (try %d) result 0x%x\n", result |
1153 | ? "failed" : "successful", retries, | 1144 | ? "failed" : "successful", retries, result)); |
1154 | sreq->sr_result)); | 1145 | if (result == 0) |
1155 | if (sreq->sr_result == 0) | ||
1156 | break; | 1146 | break; |
1157 | else if (scsi_request_normalize_sense(sreq, &sshdr)) { | 1147 | else if (scsi_normalize_sense(sense, sizeof(sense), &sshdr)) { |
1158 | if (sshdr.sense_key != UNIT_ATTENTION) | 1148 | if (sshdr.sense_key != UNIT_ATTENTION) |
1159 | break; | 1149 | break; |
1160 | } | 1150 | } |
1161 | } | 1151 | } |
1162 | 1152 | ||
1163 | if (sreq->sr_result) { | 1153 | if (result) { |
1164 | /* | 1154 | /* |
1165 | * The device probably does not support a REPORT LUN command | 1155 | * The device probably does not support a REPORT LUN command |
1166 | */ | 1156 | */ |
1167 | kfree(lun_data); | 1157 | kfree(lun_data); |
1168 | scsi_release_request(sreq); | ||
1169 | return 1; | 1158 | return 1; |
1170 | } | 1159 | } |
1171 | scsi_release_request(sreq); | ||
1172 | 1160 | ||
1173 | /* | 1161 | /* |
1174 | * Get the length from the first four bytes of lun_data. | 1162 | * Get the length from the first four bytes of lun_data. |
@@ -1242,8 +1230,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, | |||
1242 | kfree(lun_data); | 1230 | kfree(lun_data); |
1243 | return 0; | 1231 | return 0; |
1244 | 1232 | ||
1245 | out_release_request: | ||
1246 | scsi_release_request(sreq); | ||
1247 | out: | 1233 | out: |
1248 | /* | 1234 | /* |
1249 | * We are out of memory, don't try scanning any further. | 1235 | * We are out of memory, don't try scanning any further. |