diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index aff1b0cfd4b2..2ecb6ff42444 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -453,9 +453,18 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) | |||
453 | } | 453 | } |
454 | 454 | ||
455 | /** | 455 | /** |
456 | * scsi_send_eh_cmnd - send a cmd to a device as part of error recovery. | 456 | * scsi_send_eh_cmnd - submit a scsi command as part of error recory |
457 | * @scmd: SCSI Cmd to send. | 457 | * @scmd: SCSI command structure to hijack |
458 | * @timeout: Timeout for cmd. | 458 | * @cmnd: CDB to send |
459 | * @cmnd_size: size in bytes of @cmnd | ||
460 | * @timeout: timeout for this request | ||
461 | * @copy_sense: request sense data if set to 1 | ||
462 | * | ||
463 | * This function is used to send a scsi command down to a target device | ||
464 | * as part of the error recovery process. If @copy_sense is 0 the command | ||
465 | * sent must be one that does not transfer any data. If @copy_sense is 1 | ||
466 | * the command must be REQUEST_SENSE and this functions copies out the | ||
467 | * sense buffer it got into @scmd->sense_buffer. | ||
459 | * | 468 | * |
460 | * Return value: | 469 | * Return value: |
461 | * SUCCESS or FAILED or NEEDS_RETRY | 470 | * SUCCESS or FAILED or NEEDS_RETRY |
@@ -469,6 +478,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
469 | DECLARE_COMPLETION_ONSTACK(done); | 478 | DECLARE_COMPLETION_ONSTACK(done); |
470 | unsigned long timeleft; | 479 | unsigned long timeleft; |
471 | unsigned long flags; | 480 | unsigned long flags; |
481 | struct scatterlist sgl; | ||
472 | unsigned char old_cmnd[MAX_COMMAND_SIZE]; | 482 | unsigned char old_cmnd[MAX_COMMAND_SIZE]; |
473 | enum dma_data_direction old_data_direction; | 483 | enum dma_data_direction old_data_direction; |
474 | unsigned short old_use_sg; | 484 | unsigned short old_use_sg; |
@@ -500,19 +510,24 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
500 | if (shost->hostt->unchecked_isa_dma) | 510 | if (shost->hostt->unchecked_isa_dma) |
501 | gfp_mask |= __GFP_DMA; | 511 | gfp_mask |= __GFP_DMA; |
502 | 512 | ||
503 | scmd->sc_data_direction = DMA_FROM_DEVICE; | 513 | sgl.page = alloc_page(gfp_mask); |
504 | scmd->request_bufflen = 252; | 514 | if (!sgl.page) |
505 | scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask); | ||
506 | if (!scmd->request_buffer) | ||
507 | return FAILED; | 515 | return FAILED; |
516 | sgl.offset = 0; | ||
517 | sgl.length = 252; | ||
518 | |||
519 | scmd->sc_data_direction = DMA_FROM_DEVICE; | ||
520 | scmd->request_bufflen = sgl.length; | ||
521 | scmd->request_buffer = &sgl; | ||
522 | scmd->use_sg = 1; | ||
508 | } else { | 523 | } else { |
509 | scmd->request_buffer = NULL; | 524 | scmd->request_buffer = NULL; |
510 | scmd->request_bufflen = 0; | 525 | scmd->request_bufflen = 0; |
511 | scmd->sc_data_direction = DMA_NONE; | 526 | scmd->sc_data_direction = DMA_NONE; |
527 | scmd->use_sg = 0; | ||
512 | } | 528 | } |
513 | 529 | ||
514 | scmd->underflow = 0; | 530 | scmd->underflow = 0; |
515 | scmd->use_sg = 0; | ||
516 | scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); | 531 | scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); |
517 | 532 | ||
518 | if (sdev->scsi_level <= SCSI_2) | 533 | if (sdev->scsi_level <= SCSI_2) |
@@ -583,7 +598,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
583 | memcpy(scmd->sense_buffer, scmd->request_buffer, | 598 | memcpy(scmd->sense_buffer, scmd->request_buffer, |
584 | sizeof(scmd->sense_buffer)); | 599 | sizeof(scmd->sense_buffer)); |
585 | } | 600 | } |
586 | kfree(scmd->request_buffer); | 601 | __free_page(sgl.page); |
587 | } | 602 | } |
588 | 603 | ||
589 | 604 | ||