aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2007-01-30 02:48:19 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-02-03 09:15:55 -0500
commita9344e68ac0a656475006737dbc258d69fe4f7b0 (patch)
tree09735ffa77d9d5c1b88de5c4118b90501e623527 /drivers/scsi/libsas
parent423f7cf467045eab616f97309aed87a54b5e351d (diff)
[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 <djwong@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index cd2378010c7e..897a5e2c55e4 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)
421 return exphy->phy; 421 return exphy->phy;
422} 422}
423 423
424/* Attempt to send a target reset message to a device */ 424/* Attempt to send a LUN reset message to a device */
425int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) 425int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
426{ 426{
427 struct domain_device *dev = cmd_to_domain_dev(cmd); 427 struct domain_device *dev = cmd_to_domain_dev(cmd);
428 struct sas_internal *i =
429 to_sas_internal(dev->port->ha->core.shost->transportt);
430 struct scsi_lun lun;
431 int res;
432
433 int_to_scsilun(cmd->device->lun, &lun);
434
435 if (!i->dft->lldd_lu_reset)
436 return FAILED;
437
438 res = i->dft->lldd_lu_reset(dev, lun.scsi_lun);
439 if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
440 return SUCCESS;
441
442 return FAILED;
443}
444
445/* Attempt to send a phy (bus) reset */
446int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
447{
448 struct domain_device *dev = cmd_to_domain_dev(cmd);
428 struct sas_phy *phy = find_local_sas_phy(dev); 449 struct sas_phy *phy = find_local_sas_phy(dev);
429 int res; 450 int res;
430 451
431 res = sas_phy_reset(phy, 1); 452 res = sas_phy_reset(phy, 1);
432 if (res) 453 if (res)
433 SAS_DPRINTK("Device reset of %s failed 0x%x\n", 454 SAS_DPRINTK("Bus reset of %s failed 0x%x\n",
434 phy->dev.kobj.k_name, 455 phy->dev.kobj.k_name,
435 res); 456 res);
436 if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) 457 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)
443static int try_to_reset_cmd_device(struct Scsi_Host *shost, 464static int try_to_reset_cmd_device(struct Scsi_Host *shost,
444 struct scsi_cmnd *cmd) 465 struct scsi_cmnd *cmd)
445{ 466{
467 int res;
468
446 if (!shost->hostt->eh_device_reset_handler) 469 if (!shost->hostt->eh_device_reset_handler)
447 return FAILED; 470 goto try_bus_reset;
471
472 res = shost->hostt->eh_device_reset_handler(cmd);
473 if (res == SUCCESS)
474 return res;
448 475
449 return shost->hostt->eh_device_reset_handler(cmd); 476try_bus_reset:
477 if (shost->hostt->eh_bus_reset_handler)
478 return shost->hostt->eh_bus_reset_handler(cmd);
479
480 return FAILED;
450} 481}
451 482
452static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, 483static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
@@ -976,3 +1007,4 @@ EXPORT_SYMBOL_GPL(sas_task_abort);
976EXPORT_SYMBOL_GPL(sas_phy_reset); 1007EXPORT_SYMBOL_GPL(sas_phy_reset);
977EXPORT_SYMBOL_GPL(sas_phy_enable); 1008EXPORT_SYMBOL_GPL(sas_phy_enable);
978EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); 1009EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
1010EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);