Commit f456393e authored by Darrick J. Wong's avatar Darrick J. Wong Committed by James Bottomley

[SCSI] libsas: modify error handler to use scsi_eh_* functions

This patch adds an EH done queue to sas_ha, converts the error handling
strategy function and the sas_scsi_task_done functions in libsas to use
the scsi_eh_* commands for error'd commands, and adds checks for the
INITIATOR_ABORTED flag so that we do the right thing if a sas_task has
been aborted by the initiator.
Signed-off-by: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent b4d38e38
...@@ -112,6 +112,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) ...@@ -112,6 +112,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
} }
} }
INIT_LIST_HEAD(&sas_ha->eh_done_q);
return 0; return 0;
Undo_ports: Undo_ports:
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h> #include <scsi/scsi_transport_sas.h>
#include "../scsi_sas_internal.h" #include "../scsi_sas_internal.h"
...@@ -46,6 +47,7 @@ static void sas_scsi_task_done(struct sas_task *task) ...@@ -46,6 +47,7 @@ static void sas_scsi_task_done(struct sas_task *task)
{ {
struct task_status_struct *ts = &task->task_status; struct task_status_struct *ts = &task->task_status;
struct scsi_cmnd *sc = task->uldd_task; struct scsi_cmnd *sc = task->uldd_task;
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host);
unsigned ts_flags = task->task_state_flags; unsigned ts_flags = task->task_state_flags;
int hs = 0, stat = 0; int hs = 0, stat = 0;
...@@ -116,7 +118,7 @@ static void sas_scsi_task_done(struct sas_task *task) ...@@ -116,7 +118,7 @@ static void sas_scsi_task_done(struct sas_task *task)
sas_free_task(task); sas_free_task(task);
/* This is very ugly but this is how SCSI Core works. */ /* This is very ugly but this is how SCSI Core works. */
if (ts_flags & SAS_TASK_STATE_ABORTED) if (ts_flags & SAS_TASK_STATE_ABORTED)
scsi_finish_command(sc); scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q);
else else
sc->scsi_done(sc); sc->scsi_done(sc);
} }
...@@ -307,6 +309,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) ...@@ -307,6 +309,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
spin_unlock_irqrestore(&core->task_queue_lock, flags); spin_unlock_irqrestore(&core->task_queue_lock, flags);
} }
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("%s: task 0x%p already aborted\n",
__FUNCTION__, task);
return TASK_IS_ABORTED;
}
spin_unlock_irqrestore(&task->task_state_lock, flags);
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
res = si->dft->lldd_abort_task(task); res = si->dft->lldd_abort_task(task);
...@@ -409,13 +420,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) ...@@ -409,13 +420,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("going over list...\n"); SAS_DPRINTK("going over list...\n");
list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
struct sas_task *task = TO_SAS_TASK(cmd); struct sas_task *task = TO_SAS_TASK(cmd);
list_del_init(&cmd->eh_entry);
if (!task) {
SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
continue;
}
SAS_DPRINTK("trying to find task 0x%p\n", task); SAS_DPRINTK("trying to find task 0x%p\n", task);
list_del_init(&cmd->eh_entry);
res = sas_scsi_find_task(task); res = sas_scsi_find_task(task);
cmd->eh_eflags = 0; cmd->eh_eflags = 0;
shost->host_failed--;
switch (res) { switch (res) {
case TASK_IS_DONE: case TASK_IS_DONE:
...@@ -491,6 +505,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) ...@@ -491,6 +505,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
} }
} }
out: out:
scsi_eh_flush_done_q(&ha->eh_done_q);
SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
return; return;
clear_q: clear_q:
...@@ -508,12 +523,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) ...@@ -508,12 +523,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
unsigned long flags; unsigned long flags;
if (!task) { if (!task) {
SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
cmd, task); cmd, task);
return EH_HANDLED; return EH_HANDLED;
} }
spin_lock_irqsave(&task->task_state_lock, flags); spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
"EH_NOT_HANDLED\n", cmd, task);
return EH_NOT_HANDLED;
}
if (task->task_state_flags & SAS_TASK_STATE_DONE) { if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags); spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
......
...@@ -338,6 +338,8 @@ struct sas_ha_struct { ...@@ -338,6 +338,8 @@ struct sas_ha_struct {
void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event);
void *lldd_ha; /* not touched by sas class code */ void *lldd_ha; /* not touched by sas class code */
struct list_head eh_done_q;
}; };
#define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata)
...@@ -530,9 +532,10 @@ struct sas_task { ...@@ -530,9 +532,10 @@ struct sas_task {
#define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_PENDING 1
#define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_DONE 2
#define SAS_TASK_STATE_ABORTED 4 #define SAS_TASK_STATE_ABORTED 4
#define SAS_TASK_INITIATOR_ABORTED 8
static inline struct sas_task *sas_alloc_task(gfp_t flags) static inline struct sas_task *sas_alloc_task(gfp_t flags)
{ {
......
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