diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 148 |
1 files changed, 111 insertions, 37 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 060010bccabc..278e0c99b2ae 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -232,23 +232,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd, | |||
232 | } | 232 | } |
233 | EXPORT_SYMBOL(scsi_do_req); | 233 | EXPORT_SYMBOL(scsi_do_req); |
234 | 234 | ||
235 | static void scsi_wait_done(struct scsi_cmnd *cmd) | ||
236 | { | ||
237 | struct request *req = cmd->request; | ||
238 | struct request_queue *q = cmd->device->request_queue; | ||
239 | unsigned long flags; | ||
240 | |||
241 | req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ | ||
242 | |||
243 | spin_lock_irqsave(q->queue_lock, flags); | ||
244 | if (blk_rq_tagged(req)) | ||
245 | blk_queue_end_tag(q, req); | ||
246 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
247 | |||
248 | if (req->waiting) | ||
249 | complete(req->waiting); | ||
250 | } | ||
251 | |||
252 | /* This is the end routine we get to if a command was never attached | 235 | /* This is the end routine we get to if a command was never attached |
253 | * to the request. Simply complete the request without changing | 236 | * to the request. Simply complete the request without changing |
254 | * rq_status; this will cause a DRIVER_ERROR. */ | 237 | * rq_status; this will cause a DRIVER_ERROR. */ |
@@ -263,21 +246,90 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, | |||
263 | unsigned bufflen, int timeout, int retries) | 246 | unsigned bufflen, int timeout, int retries) |
264 | { | 247 | { |
265 | DECLARE_COMPLETION(wait); | 248 | DECLARE_COMPLETION(wait); |
266 | 249 | int write = (sreq->sr_data_direction == DMA_TO_DEVICE); | |
267 | sreq->sr_request->waiting = &wait; | 250 | struct request *req; |
268 | sreq->sr_request->rq_status = RQ_SCSI_BUSY; | 251 | |
269 | sreq->sr_request->end_io = scsi_wait_req_end_io; | 252 | req = blk_get_request(sreq->sr_device->request_queue, write, |
270 | scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done, | 253 | __GFP_WAIT); |
271 | timeout, retries); | 254 | if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req, |
255 | buffer, bufflen, __GFP_WAIT)) { | ||
256 | sreq->sr_result = DRIVER_ERROR << 24; | ||
257 | blk_put_request(req); | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | req->flags |= REQ_NOMERGE; | ||
262 | req->waiting = &wait; | ||
263 | req->end_io = scsi_wait_req_end_io; | ||
264 | req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]); | ||
265 | req->sense = sreq->sr_sense_buffer; | ||
266 | req->sense_len = 0; | ||
267 | memcpy(req->cmd, cmnd, req->cmd_len); | ||
268 | req->timeout = timeout; | ||
269 | req->flags |= REQ_BLOCK_PC; | ||
270 | req->rq_disk = NULL; | ||
271 | blk_insert_request(sreq->sr_device->request_queue, req, | ||
272 | sreq->sr_data_direction == DMA_TO_DEVICE, NULL); | ||
272 | wait_for_completion(&wait); | 273 | wait_for_completion(&wait); |
273 | sreq->sr_request->waiting = NULL; | 274 | sreq->sr_request->waiting = NULL; |
274 | if (sreq->sr_request->rq_status != RQ_SCSI_DONE) | 275 | sreq->sr_result = req->errors; |
276 | if (req->errors) | ||
275 | sreq->sr_result |= (DRIVER_ERROR << 24); | 277 | sreq->sr_result |= (DRIVER_ERROR << 24); |
276 | 278 | ||
277 | __scsi_release_request(sreq); | 279 | blk_put_request(req); |
278 | } | 280 | } |
281 | |||
279 | EXPORT_SYMBOL(scsi_wait_req); | 282 | EXPORT_SYMBOL(scsi_wait_req); |
280 | 283 | ||
284 | /** | ||
285 | * scsi_execute_req - insert request and wait for the result | ||
286 | * @sdev: scsi device | ||
287 | * @cmd: scsi command | ||
288 | * @data_direction: data direction | ||
289 | * @buffer: data buffer | ||
290 | * @bufflen: len of buffer | ||
291 | * @sense: optional sense buffer | ||
292 | * @timeout: request timeout in seconds | ||
293 | * @retries: number of times to retry request | ||
294 | * | ||
295 | * scsi_execute_req returns the req->errors value which is the | ||
296 | * the scsi_cmnd result field. | ||
297 | **/ | ||
298 | int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, | ||
299 | int data_direction, void *buffer, unsigned bufflen, | ||
300 | unsigned char *sense, int timeout, int retries) | ||
301 | { | ||
302 | struct request *req; | ||
303 | int write = (data_direction == DMA_TO_DEVICE); | ||
304 | int ret = DRIVER_ERROR << 24; | ||
305 | |||
306 | req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); | ||
307 | |||
308 | if (bufflen && blk_rq_map_kern(sdev->request_queue, req, | ||
309 | buffer, bufflen, __GFP_WAIT)) | ||
310 | goto out; | ||
311 | |||
312 | req->cmd_len = COMMAND_SIZE(cmd[0]); | ||
313 | memcpy(req->cmd, cmd, req->cmd_len); | ||
314 | req->sense = sense; | ||
315 | req->sense_len = 0; | ||
316 | req->timeout = timeout; | ||
317 | req->flags |= REQ_BLOCK_PC | REQ_SPECIAL; | ||
318 | |||
319 | /* | ||
320 | * head injection *required* here otherwise quiesce won't work | ||
321 | */ | ||
322 | blk_execute_rq(req->q, NULL, req, 1); | ||
323 | |||
324 | ret = req->errors; | ||
325 | out: | ||
326 | blk_put_request(req); | ||
327 | |||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | EXPORT_SYMBOL(scsi_execute_req); | ||
332 | |||
281 | /* | 333 | /* |
282 | * Function: scsi_init_cmd_errh() | 334 | * Function: scsi_init_cmd_errh() |
283 | * | 335 | * |
@@ -878,11 +930,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
878 | return; | 930 | return; |
879 | } | 931 | } |
880 | if (result) { | 932 | if (result) { |
881 | printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " | 933 | if (!(req->flags & REQ_SPECIAL)) |
882 | "= 0x%x\n", cmd->device->host->host_no, | 934 | printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " |
883 | cmd->device->channel, | 935 | "= 0x%x\n", cmd->device->host->host_no, |
884 | cmd->device->id, | 936 | cmd->device->channel, |
885 | cmd->device->lun, result); | 937 | cmd->device->id, |
938 | cmd->device->lun, result); | ||
886 | 939 | ||
887 | if (driver_byte(result) & DRIVER_SENSE) | 940 | if (driver_byte(result) & DRIVER_SENSE) |
888 | scsi_print_sense("", cmd); | 941 | scsi_print_sense("", cmd); |
@@ -1020,6 +1073,12 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, | |||
1020 | return -EOPNOTSUPP; | 1073 | return -EOPNOTSUPP; |
1021 | } | 1074 | } |
1022 | 1075 | ||
1076 | static void scsi_generic_done(struct scsi_cmnd *cmd) | ||
1077 | { | ||
1078 | BUG_ON(!blk_pc_request(cmd->request)); | ||
1079 | scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0); | ||
1080 | } | ||
1081 | |||
1023 | static int scsi_prep_fn(struct request_queue *q, struct request *req) | 1082 | static int scsi_prep_fn(struct request_queue *q, struct request *req) |
1024 | { | 1083 | { |
1025 | struct scsi_device *sdev = q->queuedata; | 1084 | struct scsi_device *sdev = q->queuedata; |
@@ -1061,7 +1120,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1061 | * these two cases differently. We differentiate by looking | 1120 | * these two cases differently. We differentiate by looking |
1062 | * at request->cmd, as this tells us the real story. | 1121 | * at request->cmd, as this tells us the real story. |
1063 | */ | 1122 | */ |
1064 | if (req->flags & REQ_SPECIAL) { | 1123 | if (req->flags & REQ_SPECIAL && req->special) { |
1065 | struct scsi_request *sreq = req->special; | 1124 | struct scsi_request *sreq = req->special; |
1066 | 1125 | ||
1067 | if (sreq->sr_magic == SCSI_REQ_MAGIC) { | 1126 | if (sreq->sr_magic == SCSI_REQ_MAGIC) { |
@@ -1073,7 +1132,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1073 | cmd = req->special; | 1132 | cmd = req->special; |
1074 | } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { | 1133 | } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { |
1075 | 1134 | ||
1076 | if(unlikely(specials_only)) { | 1135 | if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { |
1077 | if(specials_only == SDEV_QUIESCE || | 1136 | if(specials_only == SDEV_QUIESCE || |
1078 | specials_only == SDEV_BLOCK) | 1137 | specials_only == SDEV_BLOCK) |
1079 | return BLKPREP_DEFER; | 1138 | return BLKPREP_DEFER; |
@@ -1142,11 +1201,26 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1142 | /* | 1201 | /* |
1143 | * Initialize the actual SCSI command for this request. | 1202 | * Initialize the actual SCSI command for this request. |
1144 | */ | 1203 | */ |
1145 | drv = *(struct scsi_driver **)req->rq_disk->private_data; | 1204 | if (req->rq_disk) { |
1146 | if (unlikely(!drv->init_command(cmd))) { | 1205 | drv = *(struct scsi_driver **)req->rq_disk->private_data; |
1147 | scsi_release_buffers(cmd); | 1206 | if (unlikely(!drv->init_command(cmd))) { |
1148 | scsi_put_command(cmd); | 1207 | scsi_release_buffers(cmd); |
1149 | return BLKPREP_KILL; | 1208 | scsi_put_command(cmd); |
1209 | return BLKPREP_KILL; | ||
1210 | } | ||
1211 | } else { | ||
1212 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); | ||
1213 | if (rq_data_dir(req) == WRITE) | ||
1214 | cmd->sc_data_direction = DMA_TO_DEVICE; | ||
1215 | else if (req->data_len) | ||
1216 | cmd->sc_data_direction = DMA_FROM_DEVICE; | ||
1217 | else | ||
1218 | cmd->sc_data_direction = DMA_NONE; | ||
1219 | |||
1220 | cmd->transfersize = req->data_len; | ||
1221 | cmd->allowed = 3; | ||
1222 | cmd->timeout_per_command = req->timeout; | ||
1223 | cmd->done = scsi_generic_done; | ||
1150 | } | 1224 | } |
1151 | } | 1225 | } |
1152 | 1226 | ||