aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c148
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}
233EXPORT_SYMBOL(scsi_do_req); 233EXPORT_SYMBOL(scsi_do_req);
234 234
235static 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
279EXPORT_SYMBOL(scsi_wait_req); 282EXPORT_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 **/
298int 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
331EXPORT_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
1076static 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
1023static int scsi_prep_fn(struct request_queue *q, struct request *req) 1082static 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