Commit b62eaa5d authored by James Bottomley's avatar James Bottomley

Merge raven.il.steeleye.com:/home/jejb/BK/scsi-error-2.5

into raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5
parents f02dc7b9 9e119469
...@@ -397,6 +397,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes) ...@@ -397,6 +397,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
spin_lock_init(&shost->default_lock); spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock); scsi_assign_lock(shost, &shost->default_lock);
INIT_LIST_HEAD(&shost->my_devices); INIT_LIST_HEAD(&shost->my_devices);
INIT_LIST_HEAD(&shost->eh_cmd_q);
init_waitqueue_head(&shost->host_wait); init_waitqueue_head(&shost->host_wait);
shost->dma_channel = 0xff; shost->dma_channel = 0xff;
...@@ -634,22 +635,9 @@ void scsi_host_busy_dec_and_test(struct Scsi_Host *shost, Scsi_Device *sdev) ...@@ -634,22 +635,9 @@ void scsi_host_busy_dec_and_test(struct Scsi_Host *shost, Scsi_Device *sdev)
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--; shost->host_busy--;
sdev->device_busy--; sdev->device_busy--;
if (shost->in_recovery && (shost->host_busy == shost->host_failed)) { if (shost->in_recovery && shost->host_failed &&
up(shost->eh_wait); (shost->host_busy == shost->host_failed))
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler" {
" thread\n"));
}
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); up(shost->eh_wait);
SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler" SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler"
" thread\n")); " thread\n"));
......
...@@ -384,6 +384,7 @@ struct Scsi_Host ...@@ -384,6 +384,7 @@ struct Scsi_Host
spinlock_t default_lock; spinlock_t default_lock;
spinlock_t *host_lock; spinlock_t *host_lock;
struct list_head eh_cmd_q;
struct task_struct * ehandler; /* Error recovery thread. */ struct task_struct * ehandler; /* Error recovery thread. */
struct semaphore * eh_wait; /* The error recovery thread waits on struct semaphore * eh_wait; /* The error recovery thread waits on
this. */ this. */
...@@ -587,7 +588,6 @@ extern void scsi_host_init(void); ...@@ -587,7 +588,6 @@ extern void scsi_host_init(void);
*/ */
extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *); 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_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
/** /**
* scsi_find_device - find a device given the host * scsi_find_device - find a device given the host
......
...@@ -790,13 +790,9 @@ static void scsi_softirq(struct softirq_action *h) ...@@ -790,13 +790,9 @@ static void scsi_softirq(struct softirq_action *h)
if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) { if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) {
SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt)); SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt));
} }
if (SCpnt->device->host->eh_wait != NULL) {
scsi_eh_eflags_set(SCpnt, SCSI_EH_CMD_FAILED | SCSI_EH_CMD_ERR);
SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
SCpnt->state = SCSI_STATE_FAILED;
scsi_host_failed_inc_and_test(SCpnt->device->host); if (!scsi_eh_scmd_add(SCpnt, 0))
} else { {
/* /*
* We only get here if the error * We only get here if the error
* recovery thread has died. * recovery thread has died.
...@@ -1306,6 +1302,44 @@ void scsi_device_put(struct scsi_device *sdev) ...@@ -1306,6 +1302,44 @@ void scsi_device_put(struct scsi_device *sdev)
module_put(sdev->host->hostt->module); module_put(sdev->host->hostt->module);
} }
/**
* scsi_set_device_offline - set scsi_device offline
* @sdev: pointer to struct scsi_device to offline.
*
* Locks: host_lock held on entry.
**/
void scsi_set_device_offline(struct scsi_device *sdev)
{
struct scsi_cmnd *scmd;
int cmds_active = 0;
unsigned long flags;
sdev->online = FALSE;
spin_lock_irqsave(&sdev->list_lock, flags);
list_for_each_entry(scmd, &sdev->cmd_list, list) {
if (scmd->request && scmd->request->rq_status != RQ_INACTIVE) {
/*
* If we are unable to remove the timer, it means
* that the command has already timed out or
* finished.
*/
if (!scsi_delete_timer(scmd)) {
continue;
}
++cmds_active;
scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD);
}
}
spin_unlock_irqrestore(&sdev->list_lock, flags);
if (!cmds_active) {
/* FIXME: Send online state change hotplug event */
}
}
/* /*
* Function: scsi_slave_attach() * Function: scsi_slave_attach()
* *
......
...@@ -455,6 +455,7 @@ extern int scsi_slave_attach(struct scsi_device *); ...@@ -455,6 +455,7 @@ extern int scsi_slave_attach(struct scsi_device *);
extern void scsi_slave_detach(struct scsi_device *); extern void scsi_slave_detach(struct scsi_device *);
extern int scsi_device_get(struct scsi_device *); extern int scsi_device_get(struct scsi_device *);
extern void scsi_device_put(struct scsi_device *); extern void scsi_device_put(struct scsi_device *);
extern void scsi_set_device_offline(struct scsi_device *);
extern void scsi_done(Scsi_Cmnd * SCpnt); extern void scsi_done(Scsi_Cmnd * SCpnt);
extern void scsi_finish_command(Scsi_Cmnd *); extern void scsi_finish_command(Scsi_Cmnd *);
extern int scsi_retry_command(Scsi_Cmnd *); extern int scsi_retry_command(Scsi_Cmnd *);
...@@ -726,6 +727,7 @@ struct scsi_cmnd { ...@@ -726,6 +727,7 @@ struct scsi_cmnd {
struct list_head list; /* scsi_cmnd participates in queue lists */ struct list_head list; /* scsi_cmnd participates in queue lists */
struct list_head eh_entry; /* entry for the host eh_cmd_q */
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 */ 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 */
...@@ -850,6 +852,7 @@ struct scsi_cmnd { ...@@ -850,6 +852,7 @@ struct scsi_cmnd {
*/ */
#define SCSI_MLQUEUE_HOST_BUSY 0x1055 #define SCSI_MLQUEUE_HOST_BUSY 0x1055
#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056 #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
#define SCSI_MLQUEUE_EH_RETRY 0x1057
/* /*
* old style reset request from external source * old style reset request from external source
...@@ -960,13 +963,13 @@ static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) { ...@@ -960,13 +963,13 @@ static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) {
/* /*
* Scsi Error Handler Flags * Scsi Error Handler Flags
*/ */
#define SCSI_EH_CMD_ERR 0x0001 /* Orig cmd error'd */ #define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */
#define SCSI_EH_CMD_FAILED 0x0002 /* Orig cmd error type failed */ #define SCSI_EH_REC_TIMEOUT 0x0002 /* EH retry timed out */
#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) #define SCSI_SENSE_VALID(scmd) ((scmd->sense_buffer[0] & 0x70) == 0x70)
extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
int scsi_set_medium_removal(Scsi_Device *dev, char state); int scsi_set_medium_removal(Scsi_Device *dev, char state);
extern int scsi_device_register(struct scsi_device *); extern int scsi_device_register(struct scsi_device *);
......
This diff is collapsed.
...@@ -117,7 +117,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) ...@@ -117,7 +117,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
*/ */
if (reason == SCSI_MLQUEUE_HOST_BUSY) if (reason == SCSI_MLQUEUE_HOST_BUSY)
host->host_blocked = host->max_host_blocked; host->host_blocked = host->max_host_blocked;
else else if (reason == SCSI_MLQUEUE_DEVICE_BUSY)
device->device_blocked = device->max_device_blocked; device->device_blocked = device->max_device_blocked;
/* /*
......
...@@ -80,6 +80,7 @@ EXPORT_SYMBOL(scsi_slave_attach); ...@@ -80,6 +80,7 @@ EXPORT_SYMBOL(scsi_slave_attach);
EXPORT_SYMBOL(scsi_slave_detach); EXPORT_SYMBOL(scsi_slave_detach);
EXPORT_SYMBOL(scsi_device_get); EXPORT_SYMBOL(scsi_device_get);
EXPORT_SYMBOL(scsi_device_put); EXPORT_SYMBOL(scsi_device_put);
EXPORT_SYMBOL(scsi_set_device_offline);
/* /*
* This symbol is for the highlevel drivers (e.g. sg) only. * This symbol is for the highlevel drivers (e.g. sg) only.
......
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