aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_scan.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@titanic.(none)>2005-06-15 19:48:29 -0400
committerJames Bottomley <jejb@titanic.(none)>2005-08-28 11:46:40 -0400
commit392160335c798bbe94ab3aae6ea0c85d32b81bbc (patch)
treece664010089283f464d88cd89c11a60d35923851 /drivers/scsi/scsi_scan.c
parent8e6401187ef7fb1edc2740832b48bf47ed2c90f2 (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.c112
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 **/
122static void scsi_unlock_floptical(struct scsi_request *sreq, 121static 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 **/
448static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, 446static 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.