Skip to content

Commit

Permalink
ide-atapi,tape,floppy: allow ->pc_callback() to change rq->data_len
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tejun Heo committed Apr 18, 2009
1 parent ea7066a commit b3071d1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 8 deletions.
16 changes: 10 additions & 6 deletions drivers/ide/ide-atapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,16 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
dsc = 1;

/*
* ->pc_callback() might change rq->data_len for
* residual count, cache total length.
*/
if (!blk_special_request(rq) &&
(drive->media == ide_tape && !rq->bio))
done = ide_rq_bytes(rq); /* FIXME */
else
done = blk_rq_bytes(rq);

/* Command finished - Call the callback function */
uptodate = drive->pc_callback(drive, dsc);

Expand All @@ -417,7 +427,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)

if (blk_special_request(rq)) {
rq->errors = 0;
done = blk_rq_bytes(rq);
error = 0;
} else {

Expand All @@ -426,11 +435,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
rq->errors = -EIO;
}

if (drive->media == ide_tape && !rq->bio)
done = ide_rq_bytes(rq); /* FIXME */
else
done = blk_rq_bytes(rq);

error = uptodate ? 0 : -EIO;
}

Expand Down
5 changes: 4 additions & 1 deletion drivers/ide/ide-floppy.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,17 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
drive->pc = pc;

if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
unsigned int done = blk_rq_bytes(drive->hwif->rq);

if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
ide_floppy_report_error(floppy, pc);

/* Giving up */
pc->error = IDE_DRV_ERROR_GENERAL;

drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq));
ide_complete_rq(drive, -EIO, done);
return ide_stopped;
}

Expand Down
5 changes: 4 additions & 1 deletion drivers/ide/ide-tape.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,

if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
(pc->flags & PC_FLAG_ABORT)) {
unsigned int done = blk_rq_bytes(drive->hwif->rq);

/*
* We will "abort" retrying a packet command in case legitimate
* error code was received (crossing a filemark, or end of the
Expand All @@ -641,9 +643,10 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
/* Giving up */
pc->error = IDE_DRV_ERROR_GENERAL;
}

drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq));
ide_complete_rq(drive, -EIO, done);
return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
Expand Down

0 comments on commit b3071d1

Please sign in to comment.