Commit 9b46c836 authored by Mike Anderson's avatar Mike Anderson Committed by James Bottomley

Error handler general clean up

parent 8885e375
...@@ -259,6 +259,48 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j) ...@@ -259,6 +259,48 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
return retval; return retval;
} }
void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy++;
sdev->device_busy++;
spin_unlock_irqrestore(shost->host_lock, flags);
}
void scsi_host_busy_dec_and_test(struct Scsi_Host *shost, Scsi_Device *sdev)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--;
sdev->device_busy--;
if (shost->in_recovery && (shost->host_busy == shost->host_failed)) {
up(shost->eh_wait);
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
"thread (%d)\n",
atomic_read(&shost->eh_wait->count)));
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
void scsi_host_failed_inc_and_test(struct Scsi_Host *shost)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
shost->in_recovery = 1;
shost->host_failed++;
if (shost->host_busy == shost->host_failed) {
up(shost->eh_wait);
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
"thread (%d)\n",
atomic_read(&shost->eh_wait->count)));
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -543,6 +543,13 @@ extern int scsi_unregister_device(struct Scsi_Device_Template *); ...@@ -543,6 +543,13 @@ extern int scsi_unregister_device(struct Scsi_Device_Template *);
extern int scsi_register_host(Scsi_Host_Template *); extern int scsi_register_host(Scsi_Host_Template *);
extern int scsi_unregister_host(Scsi_Host_Template *); extern int scsi_unregister_host(Scsi_Host_Template *);
/*
* host_busy inc/dec/test functions
*/
extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
/* /*
* This is an ugly hack. If we expect to be able to load devices at run time, * This is an ugly hack. If we expect to be able to load devices at run time,
......
...@@ -566,22 +566,6 @@ inline void __scsi_release_command(Scsi_Cmnd * SCpnt) ...@@ -566,22 +566,6 @@ inline void __scsi_release_command(Scsi_Cmnd * SCpnt)
SCpnt->target, SCpnt->target,
atomic_read(&SCpnt->host->host_active), atomic_read(&SCpnt->host->host_active),
SCpnt->host->host_failed)); SCpnt->host->host_failed));
if (SCpnt->host->host_failed != 0) {
SCSI_LOG_ERROR_RECOVERY(5, printk("Error handler thread %d %d\n",
SCpnt->host->in_recovery,
SCpnt->host->eh_active));
}
/*
* If the host is having troubles, then look to see if this was the last
* command that might have failed. If so, wake up the error handler.
*/
if (SCpnt->host->in_recovery
&& !SCpnt->host->eh_active
&& SCpnt->host->host_busy == SCpnt->host->host_failed) {
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
atomic_read(&SCpnt->host->eh_wait->count)));
up(SCpnt->host->eh_wait);
}
spin_unlock_irqrestore(&device_request_lock, flags); spin_unlock_irqrestore(&device_request_lock, flags);
...@@ -1217,28 +1201,11 @@ void scsi_done(Scsi_Cmnd * SCpnt) ...@@ -1217,28 +1201,11 @@ void scsi_done(Scsi_Cmnd * SCpnt)
* etc, etc. * etc, etc.
*/ */
if (!tstatus) { if (!tstatus) {
SCpnt->done_late = 1;
return; return;
} }
/* Set the serial numbers back to zero */ /* Set the serial numbers back to zero */
SCpnt->serial_number = 0; SCpnt->serial_number = 0;
/*
* First, see whether this command already timed out. If so, we ignore
* the response. We treat it as if the command never finished.
*
* Since serial_number is now 0, the error handler cound detect this
* situation and avoid to call the low level driver abort routine.
* (DB)
*
* FIXME(eric) - I believe that this test is now redundant, due to
* the test of the return status of del_timer().
*/
if (SCpnt->state == SCSI_STATE_TIMEOUT) {
SCSI_LOG_MLCOMPLETE(1, printk("Ignoring completion of %p due to timeout status", SCpnt));
return;
}
SCpnt->serial_number_at_timeout = 0; SCpnt->serial_number_at_timeout = 0;
SCpnt->state = SCSI_STATE_BHQUEUE; SCpnt->state = SCSI_STATE_BHQUEUE;
SCpnt->owner = SCSI_OWNER_BH_HANDLER; SCpnt->owner = SCSI_OWNER_BH_HANDLER;
...@@ -1349,21 +1316,11 @@ static void scsi_softirq(struct softirq_action *h) ...@@ -1349,21 +1316,11 @@ static void scsi_softirq(struct softirq_action *h)
SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt)); SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt));
} }
if (SCpnt->host->eh_wait != NULL) { if (SCpnt->host->eh_wait != NULL) {
SCpnt->host->host_failed++; scsi_eh_eflags_set(SCpnt, SCSI_EH_CMD_FAILED | SCSI_EH_CMD_ERR);
SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
SCpnt->state = SCSI_STATE_FAILED; SCpnt->state = SCSI_STATE_FAILED;
SCpnt->host->in_recovery = 1;
/* scsi_host_failed_inc_and_test(SCpnt->host);
* If the host is having troubles, then
* look to see if this was the last
* command that might have failed. If
* so, wake up the error handler.
*/
if (SCpnt->host->host_busy == SCpnt->host->host_failed) {
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
atomic_read(&SCpnt->host->eh_wait->count)));
up(SCpnt->host->eh_wait);
}
} else { } else {
/* /*
* We only get here if the error * We only get here if the error
...@@ -1418,7 +1375,6 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt) ...@@ -1418,7 +1375,6 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
struct Scsi_Host *host; struct Scsi_Host *host;
Scsi_Device *device; Scsi_Device *device;
Scsi_Request * SRpnt; Scsi_Request * SRpnt;
unsigned long flags;
host = SCpnt->host; host = SCpnt->host;
device = SCpnt->device; device = SCpnt->device;
...@@ -1432,10 +1388,7 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt) ...@@ -1432,10 +1388,7 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
* one execution context, but the device and host structures are * one execution context, but the device and host structures are
* shared. * shared.
*/ */
spin_lock_irqsave(host->host_lock, flags); scsi_host_busy_dec_and_test(host, device);
host->host_busy--; /* Indicate that we are free */
device->device_busy--; /* Decrement device usage counter. */
spin_unlock_irqrestore(host->host_lock, flags);
/* /*
* Clear the flags which say that the device/host is no longer * Clear the flags which say that the device/host is no longer
...@@ -1450,7 +1403,7 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt) ...@@ -1450,7 +1403,7 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
* If we have valid sense information, then some kind of recovery * If we have valid sense information, then some kind of recovery
* must have taken place. Make a note of this. * must have taken place. Make a note of this.
*/ */
if (scsi_sense_valid(SCpnt)) { if (SCSI_SENSE_VALID(SCpnt)) {
SCpnt->result |= (DRIVER_SENSE << 24); SCpnt->result |= (DRIVER_SENSE << 24);
} }
SCSI_LOG_MLCOMPLETE(3, printk("Notifying upper driver of completion for device %d %x\n", SCSI_LOG_MLCOMPLETE(3, printk("Notifying upper driver of completion for device %d %x\n",
......
...@@ -428,7 +428,6 @@ extern void scsi_add_timer(Scsi_Cmnd * SCset, int timeout, ...@@ -428,7 +428,6 @@ extern void scsi_add_timer(Scsi_Cmnd * SCset, int timeout,
void (*complete) (Scsi_Cmnd *)); void (*complete) (Scsi_Cmnd *));
extern int scsi_delete_timer(Scsi_Cmnd * SCset); extern int scsi_delete_timer(Scsi_Cmnd * SCset);
extern void scsi_error_handler(void *host); extern void scsi_error_handler(void *host);
extern int scsi_sense_valid(Scsi_Cmnd *);
extern int scsi_decide_disposition(Scsi_Cmnd * SCpnt); extern int scsi_decide_disposition(Scsi_Cmnd * SCpnt);
extern int scsi_block_when_processing_errors(Scsi_Device *); extern int scsi_block_when_processing_errors(Scsi_Device *);
extern void scsi_sleep(int); extern void scsi_sleep(int);
...@@ -701,6 +700,7 @@ struct scsi_cmnd { ...@@ -701,6 +700,7 @@ struct scsi_cmnd {
struct scsi_cmnd *reset_chain; struct scsi_cmnd *reset_chain;
int eh_state; /* Used for state tracking in error handlr */ int eh_state; /* Used for state tracking in error handlr */
int eh_eflags; /* Used by error handlr */
void (*done) (struct scsi_cmnd *); /* Mid-level done function */ void (*done) (struct scsi_cmnd *); /* Mid-level done function */
/* /*
A SCSI Command is assigned a nonzero serial_number when internal_cmnd A SCSI Command is assigned a nonzero serial_number when internal_cmnd
...@@ -940,4 +940,26 @@ static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) { ...@@ -940,4 +940,26 @@ static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) {
return (Scsi_Cmnd *)req->special; return (Scsi_Cmnd *)req->special;
} }
#define scsi_eh_eflags_chk(scp, flags) (scp->eh_eflags & flags)
#define scsi_eh_eflags_set(scp, flags) do { \
scp->eh_eflags |= flags; \
} while(0)
#define scsi_eh_eflags_clr(scp, flags) do { \
scp->eh_eflags &= ~flags; \
} while(0)
#define scsi_eh_eflags_clr_all(scp) (scp->eh_eflags = 0)
/*
* Scsi Error Handler Flags
*/
#define SCSI_EH_CMD_ERR 0x0001 /* Orig cmd error'd */
#define SCSI_EH_CMD_FAILED 0x0002 /* Orig cmd error type failed */
#define SCSI_EH_CMD_TIMEOUT 0x0004 /* Orig cmd error type timeout */
#define SCSI_EH_REC_TIMEOUT 0x0008 /* Recovery cmd timeout */
#define SCSI_SENSE_VALID(scmd) ((scmd->sense_buffer[0] & 0x70) == 0x70)
#endif #endif
This diff is collapsed.
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