ide: move error handling code to ide-eh.c (v2)
Do some CodingStyle fixups in <linux/ide.h> while at it. v2: Add missing <linux/delay.h> include (reported by Stephen Rothwell). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
This commit is contained in:
@@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
|
||||
}
|
||||
EXPORT_SYMBOL(ide_end_drive_cmd);
|
||||
|
||||
static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
|
||||
void ide_kill_rq(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
if (rq->rq_disk) {
|
||||
struct ide_driver *drv;
|
||||
@@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
|
||||
ide_end_request(drive, 0, 0);
|
||||
}
|
||||
|
||||
static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
if ((stat & ATA_BUSY) ||
|
||||
((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
|
||||
/* other bits are useless when BUSY */
|
||||
rq->errors |= ERROR_RESET;
|
||||
} else if (stat & ATA_ERR) {
|
||||
/* err has different meaning on cdrom and tape */
|
||||
if (err == ATA_ABORTED) {
|
||||
if ((drive->dev_flags & IDE_DFLAG_LBA) &&
|
||||
/* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
|
||||
hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
|
||||
return ide_stopped;
|
||||
} else if ((err & BAD_CRC) == BAD_CRC) {
|
||||
/* UDMA crc error, just retry the operation */
|
||||
drive->crc_count++;
|
||||
} else if (err & (ATA_BBK | ATA_UNC)) {
|
||||
/* retries won't help these */
|
||||
rq->errors = ERROR_MAX;
|
||||
} else if (err & ATA_TRK0NF) {
|
||||
/* help it find track zero */
|
||||
rq->errors |= ERROR_RECAL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
|
||||
(hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
|
||||
int nsect = drive->mult_count ? drive->mult_count : 1;
|
||||
|
||||
ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
|
||||
ide_kill_rq(drive, rq);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
|
||||
rq->errors |= ERROR_RESET;
|
||||
|
||||
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
|
||||
++rq->errors;
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
|
||||
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
|
||||
drive->special.b.recalibrate = 1;
|
||||
|
||||
++rq->errors;
|
||||
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
if ((stat & ATA_BUSY) ||
|
||||
((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
|
||||
/* other bits are useless when BUSY */
|
||||
rq->errors |= ERROR_RESET;
|
||||
} else {
|
||||
/* add decoding error stuff */
|
||||
}
|
||||
|
||||
if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
|
||||
/* force an abort */
|
||||
hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
|
||||
|
||||
if (rq->errors >= ERROR_MAX) {
|
||||
ide_kill_rq(drive, rq);
|
||||
} else {
|
||||
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
|
||||
++rq->errors;
|
||||
return ide_do_reset(drive);
|
||||
}
|
||||
++rq->errors;
|
||||
}
|
||||
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
static ide_startstop_t
|
||||
__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
|
||||
{
|
||||
if (drive->media == ide_disk)
|
||||
return ide_ata_error(drive, rq, stat, err);
|
||||
return ide_atapi_error(drive, rq, stat, err);
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_error - handle an error on the IDE
|
||||
* @drive: drive the error occurred on
|
||||
* @msg: message to report
|
||||
* @stat: status bits
|
||||
*
|
||||
* ide_error() takes action based on the error returned by the drive.
|
||||
* For normal I/O that may well include retries. We deal with
|
||||
* both new-style (taskfile) and old style command handling here.
|
||||
* In the case of taskfile command handling there is work left to
|
||||
* do
|
||||
*/
|
||||
|
||||
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
|
||||
{
|
||||
struct request *rq;
|
||||
u8 err;
|
||||
|
||||
err = ide_dump_status(drive, msg, stat);
|
||||
|
||||
rq = drive->hwif->rq;
|
||||
if (rq == NULL)
|
||||
return ide_stopped;
|
||||
|
||||
/* retry only "normal" I/O: */
|
||||
if (!blk_fs_request(rq)) {
|
||||
rq->errors = 1;
|
||||
ide_end_drive_cmd(drive, stat, err);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
return __ide_error(drive, rq, stat, err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_error);
|
||||
|
||||
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
|
||||
{
|
||||
tf->nsect = drive->sect;
|
||||
|
Reference in New Issue
Block a user