diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/scsi_error.c | 34 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 203 |
2 files changed, 25 insertions, 212 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ad6a1370761e..0c2c73be1974 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -1441,6 +1441,11 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
1441 | } | 1441 | } |
1442 | } | 1442 | } |
1443 | 1443 | ||
1444 | static void eh_lock_door_done(struct request *req, int uptodate) | ||
1445 | { | ||
1446 | __blk_put_request(req->q, req); | ||
1447 | } | ||
1448 | |||
1444 | /** | 1449 | /** |
1445 | * scsi_eh_lock_door - Prevent medium removal for the specified device | 1450 | * scsi_eh_lock_door - Prevent medium removal for the specified device |
1446 | * @sdev: SCSI device to prevent medium removal | 1451 | * @sdev: SCSI device to prevent medium removal |
@@ -1463,19 +1468,28 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
1463 | */ | 1468 | */ |
1464 | static void scsi_eh_lock_door(struct scsi_device *sdev) | 1469 | static void scsi_eh_lock_door(struct scsi_device *sdev) |
1465 | { | 1470 | { |
1466 | unsigned char cmnd[MAX_COMMAND_SIZE]; | 1471 | struct request *req; |
1467 | 1472 | ||
1468 | cmnd[0] = ALLOW_MEDIUM_REMOVAL; | 1473 | req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL); |
1469 | cmnd[1] = 0; | 1474 | if (!req) |
1470 | cmnd[2] = 0; | 1475 | return; |
1471 | cmnd[3] = 0; | ||
1472 | cmnd[4] = SCSI_REMOVAL_PREVENT; | ||
1473 | cmnd[5] = 0; | ||
1474 | 1476 | ||
1475 | scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ, | 1477 | req->cmd[0] = ALLOW_MEDIUM_REMOVAL; |
1476 | 5, NULL, NULL, GFP_KERNEL); | 1478 | req->cmd[1] = 0; |
1477 | } | 1479 | req->cmd[2] = 0; |
1480 | req->cmd[3] = 0; | ||
1481 | req->cmd[4] = SCSI_REMOVAL_PREVENT; | ||
1482 | req->cmd[5] = 0; | ||
1478 | 1483 | ||
1484 | req->cmd_len = COMMAND_SIZE(req->cmd[0]); | ||
1485 | |||
1486 | req->cmd_type = REQ_TYPE_BLOCK_PC; | ||
1487 | req->cmd_flags |= REQ_QUIET; | ||
1488 | req->timeout = 10 * HZ; | ||
1489 | req->retries = 5; | ||
1490 | |||
1491 | blk_execute_rq_nowait(req->q, NULL, req, 1, eh_lock_door_done); | ||
1492 | } | ||
1479 | 1493 | ||
1480 | /** | 1494 | /** |
1481 | * scsi_restart_operations - restart io operations to the specified host. | 1495 | * scsi_restart_operations - restart io operations to the specified host. |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b82ffd90632e..4b13e36d3aa0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -277,196 +277,6 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | |||
277 | } | 277 | } |
278 | EXPORT_SYMBOL(scsi_execute_req); | 278 | EXPORT_SYMBOL(scsi_execute_req); |
279 | 279 | ||
280 | struct scsi_io_context { | ||
281 | void *data; | ||
282 | void (*done)(void *data, char *sense, int result, int resid); | ||
283 | char sense[SCSI_SENSE_BUFFERSIZE]; | ||
284 | }; | ||
285 | |||
286 | static struct kmem_cache *scsi_io_context_cache; | ||
287 | |||
288 | static void scsi_end_async(struct request *req, int uptodate) | ||
289 | { | ||
290 | struct scsi_io_context *sioc = req->end_io_data; | ||
291 | |||
292 | if (sioc->done) | ||
293 | sioc->done(sioc->data, sioc->sense, req->errors, req->data_len); | ||
294 | |||
295 | kmem_cache_free(scsi_io_context_cache, sioc); | ||
296 | __blk_put_request(req->q, req); | ||
297 | } | ||
298 | |||
299 | static int scsi_merge_bio(struct request *rq, struct bio *bio) | ||
300 | { | ||
301 | struct request_queue *q = rq->q; | ||
302 | |||
303 | bio->bi_flags &= ~(1 << BIO_SEG_VALID); | ||
304 | if (rq_data_dir(rq) == WRITE) | ||
305 | bio->bi_rw |= (1 << BIO_RW); | ||
306 | blk_queue_bounce(q, &bio); | ||
307 | |||
308 | return blk_rq_append_bio(q, rq, bio); | ||
309 | } | ||
310 | |||
311 | static void scsi_bi_endio(struct bio *bio, int error) | ||
312 | { | ||
313 | bio_put(bio); | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * scsi_req_map_sg - map a scatterlist into a request | ||
318 | * @rq: request to fill | ||
319 | * @sgl: scatterlist | ||
320 | * @nsegs: number of elements | ||
321 | * @bufflen: len of buffer | ||
322 | * @gfp: memory allocation flags | ||
323 | * | ||
324 | * scsi_req_map_sg maps a scatterlist into a request so that the | ||
325 | * request can be sent to the block layer. We do not trust the scatterlist | ||
326 | * sent to use, as some ULDs use that struct to only organize the pages. | ||
327 | */ | ||
328 | static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, | ||
329 | int nsegs, unsigned bufflen, gfp_t gfp) | ||
330 | { | ||
331 | struct request_queue *q = rq->q; | ||
332 | int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
333 | unsigned int data_len = bufflen, len, bytes, off; | ||
334 | struct scatterlist *sg; | ||
335 | struct page *page; | ||
336 | struct bio *bio = NULL; | ||
337 | int i, err, nr_vecs = 0; | ||
338 | |||
339 | for_each_sg(sgl, sg, nsegs, i) { | ||
340 | page = sg_page(sg); | ||
341 | off = sg->offset; | ||
342 | len = sg->length; | ||
343 | |||
344 | while (len > 0 && data_len > 0) { | ||
345 | /* | ||
346 | * sg sends a scatterlist that is larger than | ||
347 | * the data_len it wants transferred for certain | ||
348 | * IO sizes | ||
349 | */ | ||
350 | bytes = min_t(unsigned int, len, PAGE_SIZE - off); | ||
351 | bytes = min(bytes, data_len); | ||
352 | |||
353 | if (!bio) { | ||
354 | nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages); | ||
355 | nr_pages -= nr_vecs; | ||
356 | |||
357 | bio = bio_alloc(gfp, nr_vecs); | ||
358 | if (!bio) { | ||
359 | err = -ENOMEM; | ||
360 | goto free_bios; | ||
361 | } | ||
362 | bio->bi_end_io = scsi_bi_endio; | ||
363 | } | ||
364 | |||
365 | if (bio_add_pc_page(q, bio, page, bytes, off) != | ||
366 | bytes) { | ||
367 | bio_put(bio); | ||
368 | err = -EINVAL; | ||
369 | goto free_bios; | ||
370 | } | ||
371 | |||
372 | if (bio->bi_vcnt >= nr_vecs) { | ||
373 | err = scsi_merge_bio(rq, bio); | ||
374 | if (err) { | ||
375 | bio_endio(bio, 0); | ||
376 | goto free_bios; | ||
377 | } | ||
378 | bio = NULL; | ||
379 | } | ||
380 | |||
381 | page++; | ||
382 | len -= bytes; | ||
383 | data_len -=bytes; | ||
384 | off = 0; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | rq->buffer = rq->data = NULL; | ||
389 | rq->data_len = bufflen; | ||
390 | return 0; | ||
391 | |||
392 | free_bios: | ||
393 | while ((bio = rq->bio) != NULL) { | ||
394 | rq->bio = bio->bi_next; | ||
395 | /* | ||
396 | * call endio instead of bio_put incase it was bounced | ||
397 | */ | ||
398 | bio_endio(bio, 0); | ||
399 | } | ||
400 | |||
401 | return err; | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * scsi_execute_async - insert request | ||
406 | * @sdev: scsi device | ||
407 | * @cmd: scsi command | ||
408 | * @cmd_len: length of scsi cdb | ||
409 | * @data_direction: DMA_TO_DEVICE, DMA_FROM_DEVICE, or DMA_NONE | ||
410 | * @buffer: data buffer (this can be a kernel buffer or scatterlist) | ||
411 | * @bufflen: len of buffer | ||
412 | * @use_sg: if buffer is a scatterlist this is the number of elements | ||
413 | * @timeout: request timeout in seconds | ||
414 | * @retries: number of times to retry request | ||
415 | * @privdata: data passed to done() | ||
416 | * @done: callback function when done | ||
417 | * @gfp: memory allocation flags | ||
418 | */ | ||
419 | int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, | ||
420 | int cmd_len, int data_direction, void *buffer, unsigned bufflen, | ||
421 | int use_sg, int timeout, int retries, void *privdata, | ||
422 | void (*done)(void *, char *, int, int), gfp_t gfp) | ||
423 | { | ||
424 | struct request *req; | ||
425 | struct scsi_io_context *sioc; | ||
426 | int err = 0; | ||
427 | int write = (data_direction == DMA_TO_DEVICE); | ||
428 | |||
429 | sioc = kmem_cache_zalloc(scsi_io_context_cache, gfp); | ||
430 | if (!sioc) | ||
431 | return DRIVER_ERROR << 24; | ||
432 | |||
433 | req = blk_get_request(sdev->request_queue, write, gfp); | ||
434 | if (!req) | ||
435 | goto free_sense; | ||
436 | req->cmd_type = REQ_TYPE_BLOCK_PC; | ||
437 | req->cmd_flags |= REQ_QUIET; | ||
438 | |||
439 | if (use_sg) | ||
440 | err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp); | ||
441 | else if (bufflen) | ||
442 | err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp); | ||
443 | |||
444 | if (err) | ||
445 | goto free_req; | ||
446 | |||
447 | req->cmd_len = cmd_len; | ||
448 | memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ | ||
449 | memcpy(req->cmd, cmd, req->cmd_len); | ||
450 | req->sense = sioc->sense; | ||
451 | req->sense_len = 0; | ||
452 | req->timeout = timeout; | ||
453 | req->retries = retries; | ||
454 | req->end_io_data = sioc; | ||
455 | |||
456 | sioc->data = privdata; | ||
457 | sioc->done = done; | ||
458 | |||
459 | blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async); | ||
460 | return 0; | ||
461 | |||
462 | free_req: | ||
463 | blk_put_request(req); | ||
464 | free_sense: | ||
465 | kmem_cache_free(scsi_io_context_cache, sioc); | ||
466 | return DRIVER_ERROR << 24; | ||
467 | } | ||
468 | EXPORT_SYMBOL_GPL(scsi_execute_async); | ||
469 | |||
470 | /* | 280 | /* |
471 | * Function: scsi_init_cmd_errh() | 281 | * Function: scsi_init_cmd_errh() |
472 | * | 282 | * |
@@ -1920,20 +1730,12 @@ int __init scsi_init_queue(void) | |||
1920 | { | 1730 | { |
1921 | int i; | 1731 | int i; |
1922 | 1732 | ||
1923 | scsi_io_context_cache = kmem_cache_create("scsi_io_context", | ||
1924 | sizeof(struct scsi_io_context), | ||
1925 | 0, 0, NULL); | ||
1926 | if (!scsi_io_context_cache) { | ||
1927 | printk(KERN_ERR "SCSI: can't init scsi io context cache\n"); | ||
1928 | return -ENOMEM; | ||
1929 | } | ||
1930 | |||
1931 | scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", | 1733 | scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", |
1932 | sizeof(struct scsi_data_buffer), | 1734 | sizeof(struct scsi_data_buffer), |
1933 | 0, 0, NULL); | 1735 | 0, 0, NULL); |
1934 | if (!scsi_sdb_cache) { | 1736 | if (!scsi_sdb_cache) { |
1935 | printk(KERN_ERR "SCSI: can't init scsi sdb cache\n"); | 1737 | printk(KERN_ERR "SCSI: can't init scsi sdb cache\n"); |
1936 | goto cleanup_io_context; | 1738 | return -ENOMEM; |
1937 | } | 1739 | } |
1938 | 1740 | ||
1939 | for (i = 0; i < SG_MEMPOOL_NR; i++) { | 1741 | for (i = 0; i < SG_MEMPOOL_NR; i++) { |
@@ -1968,8 +1770,6 @@ cleanup_sdb: | |||
1968 | kmem_cache_destroy(sgp->slab); | 1770 | kmem_cache_destroy(sgp->slab); |
1969 | } | 1771 | } |
1970 | kmem_cache_destroy(scsi_sdb_cache); | 1772 | kmem_cache_destroy(scsi_sdb_cache); |
1971 | cleanup_io_context: | ||
1972 | kmem_cache_destroy(scsi_io_context_cache); | ||
1973 | 1773 | ||
1974 | return -ENOMEM; | 1774 | return -ENOMEM; |
1975 | } | 1775 | } |
@@ -1978,7 +1778,6 @@ void scsi_exit_queue(void) | |||
1978 | { | 1778 | { |
1979 | int i; | 1779 | int i; |
1980 | 1780 | ||
1981 | kmem_cache_destroy(scsi_io_context_cache); | ||
1982 | kmem_cache_destroy(scsi_sdb_cache); | 1781 | kmem_cache_destroy(scsi_sdb_cache); |
1983 | 1782 | ||
1984 | for (i = 0; i < SG_MEMPOOL_NR; i++) { | 1783 | for (i = 0; i < SG_MEMPOOL_NR; i++) { |