diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 262 |
1 files changed, 223 insertions, 39 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index dc249cb970ea..a7f3f0c84db7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -63,39 +63,6 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = { | |||
63 | }; | 63 | }; |
64 | #undef SP | 64 | #undef SP |
65 | 65 | ||
66 | |||
67 | /* | ||
68 | * Function: scsi_insert_special_req() | ||
69 | * | ||
70 | * Purpose: Insert pre-formed request into request queue. | ||
71 | * | ||
72 | * Arguments: sreq - request that is ready to be queued. | ||
73 | * at_head - boolean. True if we should insert at head | ||
74 | * of queue, false if we should insert at tail. | ||
75 | * | ||
76 | * Lock status: Assumed that lock is not held upon entry. | ||
77 | * | ||
78 | * Returns: Nothing | ||
79 | * | ||
80 | * Notes: This function is called from character device and from | ||
81 | * ioctl types of functions where the caller knows exactly | ||
82 | * what SCSI command needs to be issued. The idea is that | ||
83 | * we merely inject the command into the queue (at the head | ||
84 | * for now), and then call the queue request function to actually | ||
85 | * process it. | ||
86 | */ | ||
87 | int scsi_insert_special_req(struct scsi_request *sreq, int at_head) | ||
88 | { | ||
89 | /* | ||
90 | * Because users of this function are apt to reuse requests with no | ||
91 | * modification, we have to sanitise the request flags here | ||
92 | */ | ||
93 | sreq->sr_request->flags &= ~REQ_DONTPREP; | ||
94 | blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request, | ||
95 | at_head, sreq); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static void scsi_run_queue(struct request_queue *q); | 66 | static void scsi_run_queue(struct request_queue *q); |
100 | 67 | ||
101 | /* | 68 | /* |
@@ -249,8 +216,13 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd, | |||
249 | 216 | ||
250 | /* | 217 | /* |
251 | * head injection *required* here otherwise quiesce won't work | 218 | * head injection *required* here otherwise quiesce won't work |
219 | * | ||
220 | * Because users of this function are apt to reuse requests with no | ||
221 | * modification, we have to sanitise the request flags here | ||
252 | */ | 222 | */ |
253 | scsi_insert_special_req(sreq, 1); | 223 | sreq->sr_request->flags &= ~REQ_DONTPREP; |
224 | blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request, | ||
225 | 1, sreq); | ||
254 | } | 226 | } |
255 | EXPORT_SYMBOL(scsi_do_req); | 227 | EXPORT_SYMBOL(scsi_do_req); |
256 | 228 | ||
@@ -287,6 +259,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
287 | memcpy(req->cmd, cmd, req->cmd_len); | 259 | memcpy(req->cmd, cmd, req->cmd_len); |
288 | req->sense = sense; | 260 | req->sense = sense; |
289 | req->sense_len = 0; | 261 | req->sense_len = 0; |
262 | req->retries = retries; | ||
290 | req->timeout = timeout; | 263 | req->timeout = timeout; |
291 | req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET; | 264 | req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET; |
292 | 265 | ||
@@ -327,6 +300,200 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | |||
327 | } | 300 | } |
328 | EXPORT_SYMBOL(scsi_execute_req); | 301 | EXPORT_SYMBOL(scsi_execute_req); |
329 | 302 | ||
303 | struct scsi_io_context { | ||
304 | void *data; | ||
305 | void (*done)(void *data, char *sense, int result, int resid); | ||
306 | char sense[SCSI_SENSE_BUFFERSIZE]; | ||
307 | }; | ||
308 | |||
309 | static kmem_cache_t *scsi_io_context_cache; | ||
310 | |||
311 | static void scsi_end_async(struct request *req) | ||
312 | { | ||
313 | struct scsi_io_context *sioc = req->end_io_data; | ||
314 | |||
315 | if (sioc->done) | ||
316 | sioc->done(sioc->data, sioc->sense, req->errors, req->data_len); | ||
317 | |||
318 | kmem_cache_free(scsi_io_context_cache, sioc); | ||
319 | __blk_put_request(req->q, req); | ||
320 | } | ||
321 | |||
322 | static int scsi_merge_bio(struct request *rq, struct bio *bio) | ||
323 | { | ||
324 | struct request_queue *q = rq->q; | ||
325 | |||
326 | bio->bi_flags &= ~(1 << BIO_SEG_VALID); | ||
327 | if (rq_data_dir(rq) == WRITE) | ||
328 | bio->bi_rw |= (1 << BIO_RW); | ||
329 | blk_queue_bounce(q, &bio); | ||
330 | |||
331 | if (!rq->bio) | ||
332 | blk_rq_bio_prep(q, rq, bio); | ||
333 | else if (!q->back_merge_fn(q, rq, bio)) | ||
334 | return -EINVAL; | ||
335 | else { | ||
336 | rq->biotail->bi_next = bio; | ||
337 | rq->biotail = bio; | ||
338 | rq->hard_nr_sectors += bio_sectors(bio); | ||
339 | rq->nr_sectors = rq->hard_nr_sectors; | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) | ||
346 | { | ||
347 | if (bio->bi_size) | ||
348 | return 1; | ||
349 | |||
350 | bio_put(bio); | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * scsi_req_map_sg - map a scatterlist into a request | ||
356 | * @rq: request to fill | ||
357 | * @sg: scatterlist | ||
358 | * @nsegs: number of elements | ||
359 | * @bufflen: len of buffer | ||
360 | * @gfp: memory allocation flags | ||
361 | * | ||
362 | * scsi_req_map_sg maps a scatterlist into a request so that the | ||
363 | * request can be sent to the block layer. We do not trust the scatterlist | ||
364 | * sent to use, as some ULDs use that struct to only organize the pages. | ||
365 | */ | ||
366 | static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, | ||
367 | int nsegs, unsigned bufflen, gfp_t gfp) | ||
368 | { | ||
369 | struct request_queue *q = rq->q; | ||
370 | int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
371 | unsigned int data_len = 0, len, bytes, off; | ||
372 | struct page *page; | ||
373 | struct bio *bio = NULL; | ||
374 | int i, err, nr_vecs = 0; | ||
375 | |||
376 | for (i = 0; i < nsegs; i++) { | ||
377 | page = sgl[i].page; | ||
378 | off = sgl[i].offset; | ||
379 | len = sgl[i].length; | ||
380 | data_len += len; | ||
381 | |||
382 | while (len > 0) { | ||
383 | bytes = min_t(unsigned int, len, PAGE_SIZE - off); | ||
384 | |||
385 | if (!bio) { | ||
386 | nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages); | ||
387 | nr_pages -= nr_vecs; | ||
388 | |||
389 | bio = bio_alloc(gfp, nr_vecs); | ||
390 | if (!bio) { | ||
391 | err = -ENOMEM; | ||
392 | goto free_bios; | ||
393 | } | ||
394 | bio->bi_end_io = scsi_bi_endio; | ||
395 | } | ||
396 | |||
397 | if (bio_add_pc_page(q, bio, page, bytes, off) != | ||
398 | bytes) { | ||
399 | bio_put(bio); | ||
400 | err = -EINVAL; | ||
401 | goto free_bios; | ||
402 | } | ||
403 | |||
404 | if (bio->bi_vcnt >= nr_vecs) { | ||
405 | err = scsi_merge_bio(rq, bio); | ||
406 | if (err) { | ||
407 | bio_endio(bio, bio->bi_size, 0); | ||
408 | goto free_bios; | ||
409 | } | ||
410 | bio = NULL; | ||
411 | } | ||
412 | |||
413 | page++; | ||
414 | len -= bytes; | ||
415 | off = 0; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | rq->buffer = rq->data = NULL; | ||
420 | rq->data_len = data_len; | ||
421 | return 0; | ||
422 | |||
423 | free_bios: | ||
424 | while ((bio = rq->bio) != NULL) { | ||
425 | rq->bio = bio->bi_next; | ||
426 | /* | ||
427 | * call endio instead of bio_put incase it was bounced | ||
428 | */ | ||
429 | bio_endio(bio, bio->bi_size, 0); | ||
430 | } | ||
431 | |||
432 | return err; | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * scsi_execute_async - insert request | ||
437 | * @sdev: scsi device | ||
438 | * @cmd: scsi command | ||
439 | * @data_direction: data direction | ||
440 | * @buffer: data buffer (this can be a kernel buffer or scatterlist) | ||
441 | * @bufflen: len of buffer | ||
442 | * @use_sg: if buffer is a scatterlist this is the number of elements | ||
443 | * @timeout: request timeout in seconds | ||
444 | * @retries: number of times to retry request | ||
445 | * @flags: or into request flags | ||
446 | **/ | ||
447 | int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, | ||
448 | int data_direction, void *buffer, unsigned bufflen, | ||
449 | int use_sg, int timeout, int retries, void *privdata, | ||
450 | void (*done)(void *, char *, int, int), gfp_t gfp) | ||
451 | { | ||
452 | struct request *req; | ||
453 | struct scsi_io_context *sioc; | ||
454 | int err = 0; | ||
455 | int write = (data_direction == DMA_TO_DEVICE); | ||
456 | |||
457 | sioc = kmem_cache_alloc(scsi_io_context_cache, gfp); | ||
458 | if (!sioc) | ||
459 | return DRIVER_ERROR << 24; | ||
460 | memset(sioc, 0, sizeof(*sioc)); | ||
461 | |||
462 | req = blk_get_request(sdev->request_queue, write, gfp); | ||
463 | if (!req) | ||
464 | goto free_sense; | ||
465 | req->flags |= REQ_BLOCK_PC | REQ_QUIET; | ||
466 | |||
467 | if (use_sg) | ||
468 | err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp); | ||
469 | else if (bufflen) | ||
470 | err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp); | ||
471 | |||
472 | if (err) | ||
473 | goto free_req; | ||
474 | |||
475 | req->cmd_len = COMMAND_SIZE(cmd[0]); | ||
476 | memcpy(req->cmd, cmd, req->cmd_len); | ||
477 | req->sense = sioc->sense; | ||
478 | req->sense_len = 0; | ||
479 | req->timeout = timeout; | ||
480 | req->retries = retries; | ||
481 | req->end_io_data = sioc; | ||
482 | |||
483 | sioc->data = privdata; | ||
484 | sioc->done = done; | ||
485 | |||
486 | blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async); | ||
487 | return 0; | ||
488 | |||
489 | free_req: | ||
490 | blk_put_request(req); | ||
491 | free_sense: | ||
492 | kfree(sioc); | ||
493 | return DRIVER_ERROR << 24; | ||
494 | } | ||
495 | EXPORT_SYMBOL_GPL(scsi_execute_async); | ||
496 | |||
330 | /* | 497 | /* |
331 | * Function: scsi_init_cmd_errh() | 498 | * Function: scsi_init_cmd_errh() |
332 | * | 499 | * |
@@ -884,7 +1051,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
884 | * system where READ CAPACITY failed, we may have read | 1051 | * system where READ CAPACITY failed, we may have read |
885 | * past the end of the disk. | 1052 | * past the end of the disk. |
886 | */ | 1053 | */ |
887 | if (cmd->device->use_10_for_rw && | 1054 | if ((cmd->device->use_10_for_rw && |
1055 | sshdr.asc == 0x20 && sshdr.ascq == 0x00) && | ||
888 | (cmd->cmnd[0] == READ_10 || | 1056 | (cmd->cmnd[0] == READ_10 || |
889 | cmd->cmnd[0] == WRITE_10)) { | 1057 | cmd->cmnd[0] == WRITE_10)) { |
890 | cmd->device->use_10_for_rw = 0; | 1058 | cmd->device->use_10_for_rw = 0; |
@@ -1082,10 +1250,16 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, | |||
1082 | static void scsi_generic_done(struct scsi_cmnd *cmd) | 1250 | static void scsi_generic_done(struct scsi_cmnd *cmd) |
1083 | { | 1251 | { |
1084 | BUG_ON(!blk_pc_request(cmd->request)); | 1252 | BUG_ON(!blk_pc_request(cmd->request)); |
1085 | scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0); | 1253 | /* |
1254 | * This will complete the whole command with uptodate=1 so | ||
1255 | * as far as the block layer is concerned the command completed | ||
1256 | * successfully. Since this is a REQ_BLOCK_PC command the | ||
1257 | * caller should check the request's errors value | ||
1258 | */ | ||
1259 | scsi_io_completion(cmd, cmd->bufflen, 0); | ||
1086 | } | 1260 | } |
1087 | 1261 | ||
1088 | void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries) | 1262 | void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) |
1089 | { | 1263 | { |
1090 | struct request *req = cmd->request; | 1264 | struct request *req = cmd->request; |
1091 | 1265 | ||
@@ -1100,7 +1274,7 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries) | |||
1100 | cmd->sc_data_direction = DMA_FROM_DEVICE; | 1274 | cmd->sc_data_direction = DMA_FROM_DEVICE; |
1101 | 1275 | ||
1102 | cmd->transfersize = req->data_len; | 1276 | cmd->transfersize = req->data_len; |
1103 | cmd->allowed = retries; | 1277 | cmd->allowed = req->retries; |
1104 | cmd->timeout_per_command = req->timeout; | 1278 | cmd->timeout_per_command = req->timeout; |
1105 | } | 1279 | } |
1106 | EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd); | 1280 | EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd); |
@@ -1240,7 +1414,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1240 | goto kill; | 1414 | goto kill; |
1241 | } | 1415 | } |
1242 | } else { | 1416 | } else { |
1243 | scsi_setup_blk_pc_cmnd(cmd, 3); | 1417 | scsi_setup_blk_pc_cmnd(cmd); |
1244 | cmd->done = scsi_generic_done; | 1418 | cmd->done = scsi_generic_done; |
1245 | } | 1419 | } |
1246 | } | 1420 | } |
@@ -1603,6 +1777,14 @@ int __init scsi_init_queue(void) | |||
1603 | { | 1777 | { |
1604 | int i; | 1778 | int i; |
1605 | 1779 | ||
1780 | scsi_io_context_cache = kmem_cache_create("scsi_io_context", | ||
1781 | sizeof(struct scsi_io_context), | ||
1782 | 0, 0, NULL, NULL); | ||
1783 | if (!scsi_io_context_cache) { | ||
1784 | printk(KERN_ERR "SCSI: can't init scsi io context cache\n"); | ||
1785 | return -ENOMEM; | ||
1786 | } | ||
1787 | |||
1606 | for (i = 0; i < SG_MEMPOOL_NR; i++) { | 1788 | for (i = 0; i < SG_MEMPOOL_NR; i++) { |
1607 | struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; | 1789 | struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; |
1608 | int size = sgp->size * sizeof(struct scatterlist); | 1790 | int size = sgp->size * sizeof(struct scatterlist); |
@@ -1630,6 +1812,8 @@ void scsi_exit_queue(void) | |||
1630 | { | 1812 | { |
1631 | int i; | 1813 | int i; |
1632 | 1814 | ||
1815 | kmem_cache_destroy(scsi_io_context_cache); | ||
1816 | |||
1633 | for (i = 0; i < SG_MEMPOOL_NR; i++) { | 1817 | for (i = 0; i < SG_MEMPOOL_NR; i++) { |
1634 | struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; | 1818 | struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; |
1635 | mempool_destroy(sgp->pool); | 1819 | mempool_destroy(sgp->pool); |