Commit 5c926216 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by Linus Torvalds

[PATCH] ide: no partial completions for PIO (CONFIG_IDE_TASKFILE_IO=y)

Don't do partial completions but instead acknowledge already transferred
sectors with verified good status on error.  This allows us to complete
"good" sectors to block layer even if bio they belong to wasn't finished
and simplifies code.
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a0d1756c
...@@ -532,6 +532,18 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) ...@@ -532,6 +532,18 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
return stat; return stat;
} }
static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
const char *s, u8 stat, unsigned cur_bad)
{
if (rq->bio) {
int sectors = rq->hard_nr_sectors - rq->nr_sectors - cur_bad;
if (sectors > 0)
drive->driver->end_request(drive, 1, sectors);
}
return drive->driver->error(drive, s, stat);
}
/* /*
* Handler for command with PIO data-in phase (Read). * Handler for command with PIO data-in phase (Read).
*/ */
...@@ -542,24 +554,11 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) ...@@ -542,24 +554,11 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT)) if (stat & (ERR_STAT | DRQ_STAT))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, 0);
/* BUSY_STAT: No data yet, so wait for another IRQ. */ /* BUSY_STAT: No data yet, so wait for another IRQ. */
ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
finish_rq:
/*
* Complete previously submitted bios (if any).
* Status was already verifyied.
*/
while (rq->bio != rq->cbio)
if (!DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)))
return ide_stopped;
/* Complete rq->buffer based request (ioctls). */
if (!rq->bio && !rq->nr_sectors) {
DRIVER(drive)->end_request(drive, 1, 0);
return ide_stopped;
}
task_sectors(drive, rq, 1, IDE_PIO_IN); task_sectors(drive, rq, 1, IDE_PIO_IN);
...@@ -567,8 +566,9 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) ...@@ -567,8 +566,9 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
if (!rq->nr_sectors) { if (!rq->nr_sectors) {
stat = wait_drive_not_busy(drive); stat = wait_drive_not_busy(drive);
if (!OK_STAT(stat, 0, BAD_R_STAT)) if (!OK_STAT(stat, 0, BAD_R_STAT))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, 1);
goto finish_rq; drive->driver->end_request(drive, 1, rq->hard_nr_sectors);
return ide_stopped;
} }
/* Still data left to transfer. */ /* Still data left to transfer. */
...@@ -588,24 +588,11 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive) ...@@ -588,24 +588,11 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive)
if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT)) if (stat & (ERR_STAT | DRQ_STAT))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, 0);
/* BUSY_STAT: No data yet, so wait for another IRQ. */ /* BUSY_STAT: No data yet, so wait for another IRQ. */
ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL); ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
finish_rq:
/*
* Complete previously submitted bios (if any).
* Status was already verifyied.
*/
while (rq->bio != rq->cbio)
if (!DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)))
return ide_stopped;
/* Complete rq->buffer based request (ioctls). */
if (!rq->bio && !rq->nr_sectors) {
DRIVER(drive)->end_request(drive, 1, 0);
return ide_stopped;
}
task_multi_sectors(drive, rq, IDE_PIO_IN); task_multi_sectors(drive, rq, IDE_PIO_IN);
...@@ -613,8 +600,9 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive) ...@@ -613,8 +600,9 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive)
if (!rq->nr_sectors) { if (!rq->nr_sectors) {
stat = wait_drive_not_busy(drive); stat = wait_drive_not_busy(drive);
if (!OK_STAT(stat, 0, BAD_R_STAT)) if (!OK_STAT(stat, 0, BAD_R_STAT))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
goto finish_rq; drive->driver->end_request(drive, 1, rq->hard_nr_sectors);
return ide_stopped;
} }
/* Still data left to transfer. */ /* Still data left to transfer. */
...@@ -634,23 +622,15 @@ ide_startstop_t task_out_intr (ide_drive_t *drive) ...@@ -634,23 +622,15 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
stat = HWIF(drive)->INB(IDE_STATUS_REG); stat = HWIF(drive)->INB(IDE_STATUS_REG);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, 1);
/* Deal with unexpected ATA data phase. */ /* Deal with unexpected ATA data phase. */
if ((!(stat & DATA_READY) && rq->nr_sectors) || if ((!(stat & DATA_READY) && rq->nr_sectors) ||
((stat & DATA_READY) && !rq->nr_sectors)) ((stat & DATA_READY) && !rq->nr_sectors))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, 1);
/* if (!rq->nr_sectors) {
* Complete previously submitted bios (if any). drive->driver->end_request(drive, 1, rq->hard_nr_sectors);
* Status was already verifyied.
*/
while (rq->bio != rq->cbio)
if (!DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)))
return ide_stopped;
/* Complete rq->buffer based request (ioctls). */
if (!rq->bio && !rq->nr_sectors) {
DRIVER(drive)->end_request(drive, 1, 0);
return ide_stopped; return ide_stopped;
} }
...@@ -694,23 +674,15 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive) ...@@ -694,23 +674,15 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive)
stat = HWIF(drive)->INB(IDE_STATUS_REG); stat = HWIF(drive)->INB(IDE_STATUS_REG);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
/* Deal with unexpected ATA data phase. */ /* Deal with unexpected ATA data phase. */
if ((!(stat & DATA_READY) && rq->nr_sectors) || if ((!(stat & DATA_READY) && rq->nr_sectors) ||
((stat & DATA_READY) && !rq->nr_sectors)) ((stat & DATA_READY) && !rq->nr_sectors))
return DRIVER(drive)->error(drive, __FUNCTION__, stat); return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
/* if (!rq->nr_sectors) {
* Complete previously submitted bios (if any). drive->driver->end_request(drive, 1, rq->hard_nr_sectors);
* Status was already verifyied.
*/
while (rq->bio != rq->cbio)
if (!DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)))
return ide_stopped;
/* Complete rq->buffer based request (ioctls). */
if (!rq->bio && !rq->nr_sectors) {
DRIVER(drive)->end_request(drive, 1, 0);
return ide_stopped; return ide_stopped;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment