diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 58 |
1 files changed, 8 insertions, 50 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index e40c8b66da40..ce9d73a292e2 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -254,55 +254,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd, | |||
254 | } | 254 | } |
255 | EXPORT_SYMBOL(scsi_do_req); | 255 | EXPORT_SYMBOL(scsi_do_req); |
256 | 256 | ||
257 | /* This is the end routine we get to if a command was never attached | ||
258 | * to the request. Simply complete the request without changing | ||
259 | * rq_status; this will cause a DRIVER_ERROR. */ | ||
260 | static void scsi_wait_req_end_io(struct request *req) | ||
261 | { | ||
262 | BUG_ON(!req->waiting); | ||
263 | |||
264 | complete(req->waiting); | ||
265 | } | ||
266 | |||
267 | void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, | ||
268 | unsigned bufflen, int timeout, int retries) | ||
269 | { | ||
270 | DECLARE_COMPLETION(wait); | ||
271 | int write = (sreq->sr_data_direction == DMA_TO_DEVICE); | ||
272 | struct request *req; | ||
273 | |||
274 | req = blk_get_request(sreq->sr_device->request_queue, write, | ||
275 | __GFP_WAIT); | ||
276 | if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req, | ||
277 | buffer, bufflen, __GFP_WAIT)) { | ||
278 | sreq->sr_result = DRIVER_ERROR << 24; | ||
279 | blk_put_request(req); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | req->flags |= REQ_NOMERGE; | ||
284 | req->waiting = &wait; | ||
285 | req->end_io = scsi_wait_req_end_io; | ||
286 | req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]); | ||
287 | req->sense = sreq->sr_sense_buffer; | ||
288 | req->sense_len = 0; | ||
289 | memcpy(req->cmd, cmnd, req->cmd_len); | ||
290 | req->timeout = timeout; | ||
291 | req->flags |= REQ_BLOCK_PC; | ||
292 | req->rq_disk = NULL; | ||
293 | blk_insert_request(sreq->sr_device->request_queue, req, | ||
294 | sreq->sr_data_direction == DMA_TO_DEVICE, NULL); | ||
295 | wait_for_completion(&wait); | ||
296 | sreq->sr_request->waiting = NULL; | ||
297 | sreq->sr_result = req->errors; | ||
298 | if (req->errors) | ||
299 | sreq->sr_result |= (DRIVER_ERROR << 24); | ||
300 | |||
301 | blk_put_request(req); | ||
302 | } | ||
303 | |||
304 | EXPORT_SYMBOL(scsi_wait_req); | ||
305 | |||
306 | /** | 257 | /** |
307 | * scsi_execute - insert request and wait for the result | 258 | * scsi_execute - insert request and wait for the result |
308 | * @sdev: scsi device | 259 | * @sdev: scsi device |
@@ -591,10 +542,17 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) | |||
591 | 542 | ||
592 | void scsi_next_command(struct scsi_cmnd *cmd) | 543 | void scsi_next_command(struct scsi_cmnd *cmd) |
593 | { | 544 | { |
594 | struct request_queue *q = cmd->device->request_queue; | 545 | struct scsi_device *sdev = cmd->device; |
546 | struct request_queue *q = sdev->request_queue; | ||
547 | |||
548 | /* need to hold a reference on the device before we let go of the cmd */ | ||
549 | get_device(&sdev->sdev_gendev); | ||
595 | 550 | ||
596 | scsi_put_command(cmd); | 551 | scsi_put_command(cmd); |
597 | scsi_run_queue(q); | 552 | scsi_run_queue(q); |
553 | |||
554 | /* ok to remove device now */ | ||
555 | put_device(&sdev->sdev_gendev); | ||
598 | } | 556 | } |
599 | 557 | ||
600 | void scsi_run_host_queues(struct Scsi_Host *shost) | 558 | void scsi_run_host_queues(struct Scsi_Host *shost) |