From a9344e68ac0a656475006737dbc258d69fe4f7b0 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 29 Jan 2007 23:48:19 -0800 Subject: [SCSI] libsas: Add an LU reset mechanism to the error handler After discussion with andmike and dougg, it seems that the purpose of eh_device_reset_handler is to issue LU resets, and that eh_bus_reset_handler would be a more appropriate place for a phy reset. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 40 +++++++++++++++++++++++++++++++++---- include/scsi/libsas.h | 1 + 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index cd23780..897a5e2 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -421,16 +421,37 @@ struct sas_phy *find_local_sas_phy(struct domain_device *dev) return exphy->phy; } -/* Attempt to send a target reset message to a device */ +/* Attempt to send a LUN reset message to a device */ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) { struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_internal *i = + to_sas_internal(dev->port->ha->core.shost->transportt); + struct scsi_lun lun; + int res; + + int_to_scsilun(cmd->device->lun, &lun); + + if (!i->dft->lldd_lu_reset) + return FAILED; + + res = i->dft->lldd_lu_reset(dev, lun.scsi_lun); + if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) + return SUCCESS; + + return FAILED; +} + +/* Attempt to send a phy (bus) reset */ +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) +{ + struct domain_device *dev = cmd_to_domain_dev(cmd); struct sas_phy *phy = find_local_sas_phy(dev); int res; res = sas_phy_reset(phy, 1); if (res) - SAS_DPRINTK("Device reset of %s failed 0x%x\n", + SAS_DPRINTK("Bus reset of %s failed 0x%x\n", phy->dev.kobj.k_name, res); if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) @@ -443,10 +464,20 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) static int try_to_reset_cmd_device(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { + int res; + if (!shost->hostt->eh_device_reset_handler) - return FAILED; + goto try_bus_reset; + + res = shost->hostt->eh_device_reset_handler(cmd); + if (res == SUCCESS) + return res; - return shost->hostt->eh_device_reset_handler(cmd); +try_bus_reset: + if (shost->hostt->eh_bus_reset_handler) + return shost->hostt->eh_bus_reset_handler(cmd); + + return FAILED; } static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, @@ -976,3 +1007,4 @@ EXPORT_SYMBOL_GPL(sas_task_abort); EXPORT_SYMBOL_GPL(sas_phy_reset); EXPORT_SYMBOL_GPL(sas_phy_enable); EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); +EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index b200233..8516ba6 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -661,5 +661,6 @@ void sas_init_dev(struct domain_device *); void sas_task_abort(struct sas_task *); int __sas_task_abort(struct sas_task *); int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); #endif /* _SASLIB_H_ */ -- cgit v1.1