Skip to content

Commit

Permalink
[SCSI] libsas: Enable the EH strategy handler to reset a phy after a …
Browse files Browse the repository at this point in the history
…command

When a SAS LLDD needs to request a device port reset, it needs to have all
commands aborted before it can reset the port.  Since commands are put on
the EH's list in the order that they were queued, the LLDD can set a "need
reset" flag in the last task to be aborted so that the EH can reset the
port after all commands are aborted.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Darrick J. Wong authored and James Bottomley committed Jan 13, 2007
1 parent 37958fb commit 3ebf692
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
37 changes: 36 additions & 1 deletion drivers/scsi/libsas/sas_scsi_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,15 +389,29 @@ static int sas_recover_I_T(struct domain_device *dev)
return res;
}

static int eh_reset_phy_helper(struct sas_phy *phy)
{
int tmf_resp;

tmf_resp = sas_phy_reset(phy, 1);
if (tmf_resp)
SAS_DPRINTK("Hard reset of phy %d failed 0x%x\n",
phy->identify.phy_identifier,
tmf_resp);

return tmf_resp;
}

void sas_scsi_recover_host(struct Scsi_Host *shost)
{
struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
unsigned long flags;
LIST_HEAD(error_q);
struct scsi_cmnd *cmd, *n;
enum task_disposition res = TASK_IS_DONE;
int tmf_resp;
int tmf_resp, need_reset;
struct sas_internal *i = to_sas_internal(shost->transportt);
struct sas_phy *task_sas_phy = NULL;

spin_lock_irqsave(shost->host_lock, flags);
list_splice_init(&shost->eh_cmd_q, &error_q);
Expand All @@ -418,6 +432,13 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
continue;
}

spin_lock_irqsave(&task->task_state_lock, flags);
need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
if (need_reset)
task_sas_phy = task->dev->port->phy;
spin_unlock_irqrestore(&task->task_state_lock, flags);

SAS_DPRINTK("trying to find task 0x%p\n", task);
res = sas_scsi_find_task(task);

Expand All @@ -428,11 +449,15 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
task);
task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
continue;
case TASK_IS_ABORTED:
SAS_DPRINTK("%s: task 0x%p is aborted\n",
__FUNCTION__, task);
task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
continue;
case TASK_IS_AT_LU:
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
Expand All @@ -443,6 +468,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_ADDR(task->dev),
cmd->device->lun);
task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
sas_scsi_clear_queue_lu(&error_q, cmd);
goto Again;
}
Expand All @@ -455,6 +482,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("I_T %016llx recovered\n",
SAS_ADDR(task->dev->sas_addr));
task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
sas_scsi_clear_queue_I_T(&error_q, task->dev);
goto Again;
}
Expand All @@ -468,6 +497,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("clear nexus port:%d "
"succeeded\n", port->id);
task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
sas_scsi_clear_queue_port(&error_q,
port);
goto Again;
Expand All @@ -480,6 +511,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("clear nexus ha "
"succeeded\n");
task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
goto out;
}
}
Expand All @@ -493,6 +526,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
cmd->device->lun);

task->task_done(task);
if (need_reset)
eh_reset_phy_helper(task_sas_phy);
goto clear_q;
}
}
Expand Down
1 change: 1 addition & 0 deletions include/scsi/libsas.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ struct sas_task {
#define SAS_TASK_STATE_PENDING 1
#define SAS_TASK_STATE_DONE 2
#define SAS_TASK_STATE_ABORTED 4
#define SAS_TASK_NEED_DEV_RESET 8
#define SAS_TASK_AT_INITIATOR 16

static inline struct sas_task *sas_alloc_task(gfp_t flags)
Expand Down

0 comments on commit 3ebf692

Please sign in to comment.