mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-09 12:04:15 +08:00
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>
This commit is contained in:
parent
08f370f0a2
commit
eb6a61bb95
@ -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)
|
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
|
||||||
dsc = 1;
|
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 */
|
/* Command finished - Call the callback function */
|
||||||
uptodate = drive->pc_callback(drive, dsc);
|
uptodate = drive->pc_callback(drive, dsc);
|
||||||
|
|
||||||
@ -417,7 +427,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
|||||||
|
|
||||||
if (blk_special_request(rq)) {
|
if (blk_special_request(rq)) {
|
||||||
rq->errors = 0;
|
rq->errors = 0;
|
||||||
done = blk_rq_bytes(rq);
|
|
||||||
error = 0;
|
error = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -426,11 +435,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
|
|||||||
rq->errors = -EIO;
|
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;
|
error = uptodate ? 0 : -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,14 +134,17 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
|
|||||||
drive->pc = pc;
|
drive->pc = pc;
|
||||||
|
|
||||||
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
|
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
|
||||||
|
unsigned int done = blk_rq_bytes(drive->hwif->rq);
|
||||||
|
|
||||||
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
|
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
|
||||||
ide_floppy_report_error(floppy, pc);
|
ide_floppy_report_error(floppy, pc);
|
||||||
|
|
||||||
/* Giving up */
|
/* Giving up */
|
||||||
pc->error = IDE_DRV_ERROR_GENERAL;
|
pc->error = IDE_DRV_ERROR_GENERAL;
|
||||||
|
|
||||||
drive->failed_pc = NULL;
|
drive->failed_pc = NULL;
|
||||||
drive->pc_callback(drive, 0);
|
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;
|
return ide_stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,6 +622,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
|
|||||||
|
|
||||||
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
|
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
|
||||||
(pc->flags & PC_FLAG_ABORT)) {
|
(pc->flags & PC_FLAG_ABORT)) {
|
||||||
|
unsigned int done = blk_rq_bytes(drive->hwif->rq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We will "abort" retrying a packet command in case legitimate
|
* We will "abort" retrying a packet command in case legitimate
|
||||||
* error code was received (crossing a filemark, or end of the
|
* 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,
|
|||||||
/* Giving up */
|
/* Giving up */
|
||||||
pc->error = IDE_DRV_ERROR_GENERAL;
|
pc->error = IDE_DRV_ERROR_GENERAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drive->failed_pc = NULL;
|
drive->failed_pc = NULL;
|
||||||
drive->pc_callback(drive, 0);
|
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;
|
return ide_stopped;
|
||||||
}
|
}
|
||||||
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
|
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
|
||||||
|
Loading…
Reference in New Issue
Block a user