diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2007-01-30 02:48:19 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-02-03 09:15:55 -0500 |
commit | a9344e68ac0a656475006737dbc258d69fe4f7b0 (patch) | |
tree | 09735ffa77d9d5c1b88de5c4118b90501e623527 | |
parent | 423f7cf467045eab616f97309aed87a54b5e351d (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>
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 40 | ||||
-rw-r--r-- | 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 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 */ |
425 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | 425 | int 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 */ | ||
446 | int 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) | |||
443 | static int try_to_reset_cmd_device(struct Scsi_Host *shost, | 464 | static 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); | 476 | try_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 | ||
452 | static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, | 483 | static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, |
@@ -976,3 +1007,4 @@ EXPORT_SYMBOL_GPL(sas_task_abort); | |||
976 | EXPORT_SYMBOL_GPL(sas_phy_reset); | 1007 | EXPORT_SYMBOL_GPL(sas_phy_reset); |
977 | EXPORT_SYMBOL_GPL(sas_phy_enable); | 1008 | EXPORT_SYMBOL_GPL(sas_phy_enable); |
978 | EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); | 1009 | EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); |
1010 | EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); | ||
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index b200233cc6f4..8516ba68cc95 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -661,5 +661,6 @@ void sas_init_dev(struct domain_device *); | |||
661 | void sas_task_abort(struct sas_task *); | 661 | void sas_task_abort(struct sas_task *); |
662 | int __sas_task_abort(struct sas_task *); | 662 | int __sas_task_abort(struct sas_task *); |
663 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); | 663 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); |
664 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); | ||
664 | 665 | ||
665 | #endif /* _SASLIB_H_ */ | 666 | #endif /* _SASLIB_H_ */ |