diff options
author | Tejun Heo <tj@kernel.org> | 2009-04-18 19:46:02 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2009-04-18 19:46:02 -0400 |
commit | b3071d190d6757b14af002a9d79832f12de61bce (patch) | |
tree | b31e5d2ca6c9a86110b64811faf817bbb49d0d9c | |
parent | ea7066afcd590e4663e6dc010f93704164050f48 (diff) |
ide-atapi,tape,floppy: allow ->pc_callback() to change rq->data_len
Impact: allow residual count implementation in ->pc_callback()
rq->data_len has two duties - carrying the number of input bytes on
issue and carrying residual count back to the issuer on completion.
ide-atapi completion callback ->pc_callback() is the right place to do
this but currently ide-atapi depends on rq->data_len carrying the
original request size after calling ->pc_callback() to complete the pc
request.
This patch makes ide_pc_intr(), ide_tape_issue_pc() and
ide_floppy_issue_pc() cache length to complete before calling
->pc_callback() so that it can modify rq->data_len as necessary.
Note: As using rq->data_len for two purposes can make cases like this
incorrect in subtle ways, future changes will introduce separate
field for residual count.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | drivers/ide/ide-atapi.c | 16 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 5 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 5 |
3 files changed, 18 insertions, 8 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 5cefe12f5622..3df5442de710 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -409,6 +409,16 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
409 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) | 409 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) |
410 | dsc = 1; | 410 | dsc = 1; |
411 | 411 | ||
412 | /* | ||
413 | * ->pc_callback() might change rq->data_len for | ||
414 | * residual count, cache total length. | ||
415 | */ | ||
416 | if (!blk_special_request(rq) && | ||
417 | (drive->media == ide_tape && !rq->bio)) | ||
418 | done = ide_rq_bytes(rq); /* FIXME */ | ||
419 | else | ||
420 | done = blk_rq_bytes(rq); | ||
421 | |||
412 | /* Command finished - Call the callback function */ | 422 | /* Command finished - Call the callback function */ |
413 | uptodate = drive->pc_callback(drive, dsc); | 423 | uptodate = drive->pc_callback(drive, dsc); |
414 | 424 | ||
@@ -417,7 +427,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
417 | 427 | ||
418 | if (blk_special_request(rq)) { | 428 | if (blk_special_request(rq)) { |
419 | rq->errors = 0; | 429 | rq->errors = 0; |
420 | done = blk_rq_bytes(rq); | ||
421 | error = 0; | 430 | error = 0; |
422 | } else { | 431 | } else { |
423 | 432 | ||
@@ -426,11 +435,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
426 | rq->errors = -EIO; | 435 | rq->errors = -EIO; |
427 | } | 436 | } |
428 | 437 | ||
429 | if (drive->media == ide_tape && !rq->bio) | ||
430 | done = ide_rq_bytes(rq); /* FIXME */ | ||
431 | else | ||
432 | done = blk_rq_bytes(rq); | ||
433 | |||
434 | error = uptodate ? 0 : -EIO; | 438 | error = uptodate ? 0 : -EIO; |
435 | } | 439 | } |
436 | 440 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index d20704ac3183..537b7c558033 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -134,14 +134,17 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive, | |||
134 | drive->pc = pc; | 134 | drive->pc = pc; |
135 | 135 | ||
136 | if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { | 136 | if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { |
137 | unsigned int done = blk_rq_bytes(drive->hwif->rq); | ||
138 | |||
137 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) | 139 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) |
138 | ide_floppy_report_error(floppy, pc); | 140 | ide_floppy_report_error(floppy, pc); |
141 | |||
139 | /* Giving up */ | 142 | /* Giving up */ |
140 | pc->error = IDE_DRV_ERROR_GENERAL; | 143 | pc->error = IDE_DRV_ERROR_GENERAL; |
141 | 144 | ||
142 | drive->failed_pc = NULL; | 145 | drive->failed_pc = NULL; |
143 | drive->pc_callback(drive, 0); | 146 | drive->pc_callback(drive, 0); |
144 | ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq)); | 147 | ide_complete_rq(drive, -EIO, done); |
145 | return ide_stopped; | 148 | return ide_stopped; |
146 | } | 149 | } |
147 | 150 | ||
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 2b9a13671c5f..8226d52504d0 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -622,6 +622,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, | |||
622 | 622 | ||
623 | if (pc->retries > IDETAPE_MAX_PC_RETRIES || | 623 | if (pc->retries > IDETAPE_MAX_PC_RETRIES || |
624 | (pc->flags & PC_FLAG_ABORT)) { | 624 | (pc->flags & PC_FLAG_ABORT)) { |
625 | unsigned int done = blk_rq_bytes(drive->hwif->rq); | ||
626 | |||
625 | /* | 627 | /* |
626 | * We will "abort" retrying a packet command in case legitimate | 628 | * We will "abort" retrying a packet command in case legitimate |
627 | * error code was received (crossing a filemark, or end of the | 629 | * error code was received (crossing a filemark, or end of the |
@@ -641,9 +643,10 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, | |||
641 | /* Giving up */ | 643 | /* Giving up */ |
642 | pc->error = IDE_DRV_ERROR_GENERAL; | 644 | pc->error = IDE_DRV_ERROR_GENERAL; |
643 | } | 645 | } |
646 | |||
644 | drive->failed_pc = NULL; | 647 | drive->failed_pc = NULL; |
645 | drive->pc_callback(drive, 0); | 648 | drive->pc_callback(drive, 0); |
646 | ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq)); | 649 | ide_complete_rq(drive, -EIO, done); |
647 | return ide_stopped; | 650 | return ide_stopped; |
648 | } | 651 | } |
649 | debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); | 652 | debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); |