Commit 4e9fbe87 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ide-scsi error handling fixes

From: Willem Riede <wrlk@riede.org>

The patch revises the error handling in ide-scsi, fixing the scheduling
while locked issues, and make it work properly, at least for me...

Specific changes in this patch:

- introduce idescsi_expiry, a timeout routine for the ide subsystem,
  which simply flags the fact that the command timed out, but postpones
  any other action until either the command still finishes on its own
  (unlikely?) or the scsi error handler kicks in;

- introduce idescsi_atapi_error and idescsi_atapi_abort, error routines
  for the ide subsystem, which are modeled after those of ide-cd, but
  take only minimal effort to recover, leaving the heavy lifting for
  the scsi error handler;

- rewrite (and rename for clarity) idescsi_eh_abort and idescsi_eh_error,
  the abort/error routines to be called by the scsi error handler --
  this redesign should not have the scheduling while atomic problems
  of the old implementation.

- move ide_cdrom_dump_status() from ide-cd.c to ide-lib.c as
  ide_dump_atapi_status() and both ide-cd and ide-scsi call it.

- replaces BUG() by WARN_ON()/printk in the error handling code.

- sets TASK_UNINTERRUPTIBLE before schedule_timeout() and moves the host
  unlock/lock around the while loop inside the loop in idescsi_eh_reset().
parent e5c539b8
...@@ -554,53 +554,6 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, ...@@ -554,53 +554,6 @@ static void cdrom_queue_request_sense(ide_drive_t *drive,
(void) ide_do_drive_cmd(drive, rq, ide_preempt); (void) ide_do_drive_cmd(drive, rq, ide_preempt);
} }
/*
* Error reporting, in human readable form (luxurious, but a memory hog).
*/
byte ide_cdrom_dump_status (ide_drive_t *drive, const char *msg, byte stat)
{
unsigned long flags;
atapi_status_t status;
atapi_error_t error;
status.all = stat;
local_irq_set(flags);
printk("%s: %s: status=0x%02x", drive->name, msg, stat);
#if FANCY_STATUS_DUMPS
printk(" { ");
if (status.b.bsy)
printk("Busy ");
else {
if (status.b.drdy) printk("DriveReady ");
if (status.b.df) printk("DeviceFault ");
if (status.b.dsc) printk("SeekComplete ");
if (status.b.drq) printk("DataRequest ");
if (status.b.corr) printk("CorrectedError ");
if (status.b.idx) printk("Index ");
if (status.b.check) printk("Error ");
}
printk("}");
#endif /* FANCY_STATUS_DUMPS */
printk("\n");
if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) {
error.all = HWIF(drive)->INB(IDE_ERROR_REG);
printk("%s: %s: error=0x%02x", drive->name, msg, error.all);
#if FANCY_STATUS_DUMPS
if (error.b.ili) printk("IllegalLengthIndication ");
if (error.b.eom) printk("EndOfMedia ");
if (error.b.abrt) printk("Aborted Command ");
if (error.b.mcr) printk("MediaChangeRequested ");
if (error.b.sense_key) printk("LastFailedSense 0x%02x ",
error.b.sense_key);
#endif /* FANCY_STATUS_DUMPS */
printk("\n");
}
local_irq_restore(flags);
return error.all;
}
/* /*
* ide_error() takes action based on the error returned by the drive. * ide_error() takes action based on the error returned by the drive.
*/ */
...@@ -609,7 +562,7 @@ ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) ...@@ -609,7 +562,7 @@ ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat)
struct request *rq; struct request *rq;
byte err; byte err;
err = ide_cdrom_dump_status(drive, msg, stat); err = ide_dump_atapi_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped; return ide_stopped;
/* retry only "normal" I/O: */ /* retry only "normal" I/O: */
...@@ -3412,7 +3365,7 @@ static ide_driver_t ide_cdrom_driver = { ...@@ -3412,7 +3365,7 @@ static ide_driver_t ide_cdrom_driver = {
.supports_dsc_overlap = 1, .supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup, .cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom, .do_request = ide_do_rw_cdrom,
.sense = ide_cdrom_dump_status, .sense = ide_dump_atapi_status,
.error = ide_cdrom_error, .error = ide_cdrom_error,
.abort = ide_cdrom_abort, .abort = ide_cdrom_abort,
.capacity = ide_cdrom_capacity, .capacity = ide_cdrom_capacity,
......
...@@ -447,3 +447,55 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) ...@@ -447,3 +447,55 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
EXPORT_SYMBOL_GPL(ide_set_xfer_rate); EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
/**
* ide_dump_atapi_status - print human readable atapi status
* @drive: drive that status applies to
* @msg: text message to print
* @stat: status byte to decode
*
* Error reporting, in human readable form (luxurious, but a memory hog).
*/
byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
{
unsigned long flags;
atapi_status_t status;
atapi_error_t error;
status.all = stat;
local_irq_set(flags);
printk("%s: %s: status=0x%02x", drive->name, msg, stat);
#if FANCY_STATUS_DUMPS
printk(" { ");
if (status.b.bsy)
printk("Busy ");
else {
if (status.b.drdy) printk("DriveReady ");
if (status.b.df) printk("DeviceFault ");
if (status.b.dsc) printk("SeekComplete ");
if (status.b.drq) printk("DataRequest ");
if (status.b.corr) printk("CorrectedError ");
if (status.b.idx) printk("Index ");
if (status.b.check) printk("Error ");
}
printk("}");
#endif /* FANCY_STATUS_DUMPS */
printk("\n");
if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) {
error.all = HWIF(drive)->INB(IDE_ERROR_REG);
printk("%s: %s: error=0x%02x", drive->name, msg, error.all);
#if FANCY_STATUS_DUMPS
if (error.b.ili) printk("IllegalLengthIndication ");
if (error.b.eom) printk("EndOfMedia ");
if (error.b.abrt) printk("Aborted Command ");
if (error.b.mcr) printk("MediaChangeRequested ");
if (error.b.sense_key) printk("LastFailedSense 0x%02x ",
error.b.sense_key);
#endif /* FANCY_STATUS_DUMPS */
printk("\n");
}
local_irq_restore(flags);
return error.all;
}
EXPORT_SYMBOL(ide_dump_atapi_status);
This diff is collapsed.
...@@ -1612,6 +1612,7 @@ extern int ide_dma_enable(ide_drive_t *drive); ...@@ -1612,6 +1612,7 @@ extern int ide_dma_enable(ide_drive_t *drive);
extern char *ide_xfer_verbose(u8 xfer_rate); extern char *ide_xfer_verbose(u8 xfer_rate);
extern void ide_toggle_bounce(ide_drive_t *drive, int on); extern void ide_toggle_bounce(ide_drive_t *drive, int on);
extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
extern byte ide_dump_atapi_status(ide_drive_t *drive, const char *msg, byte stat);
typedef struct ide_pio_timings_s { typedef struct ide_pio_timings_s {
int setup_time; /* Address setup (ns) minimum */ int setup_time; /* Address setup (ns) minimum */
......
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