diff options
author | Eric Moore <eric.moore@lsi.com> | 2009-05-18 15:00:45 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-05-23 16:44:17 -0400 |
commit | 993e0da7b767c0a7c1fd0079b16f3d28e6f25a48 (patch) | |
tree | 1e64897334fdeb48b71778c0eddbb929c04eb4c1 /drivers | |
parent | 3c621b3ee1432e7a2aca4a3b670b1d05f19ecf9c (diff) |
[SCSI] mpt2sas: LUN Reset Support
Adding new eh_target_reset_handler for target reset. Change the
eh_device_reset_handler so its sending
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, instead of
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET. Add new function
_scsih_scsi_lookup_find_by_lun as a sanity check to insure I_T_L commands are
completed upon completing lun reset.
Signed-off-by: Eric Moore <eric.moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 111 |
1 files changed, 109 insertions, 2 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 5394f6196416..f45837630b24 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -884,6 +884,41 @@ _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id, | |||
884 | } | 884 | } |
885 | 885 | ||
886 | /** | 886 | /** |
887 | * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun | ||
888 | * @ioc: per adapter object | ||
889 | * @id: target id | ||
890 | * @lun: lun number | ||
891 | * @channel: channel | ||
892 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
893 | * | ||
894 | * This will search for a matching channel:id:lun in the scsi_lookup array, | ||
895 | * returning 1 if found. | ||
896 | */ | ||
897 | static u8 | ||
898 | _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id, | ||
899 | unsigned int lun, int channel) | ||
900 | { | ||
901 | u8 found; | ||
902 | unsigned long flags; | ||
903 | int i; | ||
904 | |||
905 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
906 | found = 0; | ||
907 | for (i = 0 ; i < ioc->request_depth; i++) { | ||
908 | if (ioc->scsi_lookup[i].scmd && | ||
909 | (ioc->scsi_lookup[i].scmd->device->id == id && | ||
910 | ioc->scsi_lookup[i].scmd->device->channel == channel && | ||
911 | ioc->scsi_lookup[i].scmd->device->lun == lun)) { | ||
912 | found = 1; | ||
913 | goto out; | ||
914 | } | ||
915 | } | ||
916 | out: | ||
917 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
918 | return found; | ||
919 | } | ||
920 | |||
921 | /** | ||
887 | * _scsih_get_chain_buffer_dma - obtain block of chains (dma address) | 922 | * _scsih_get_chain_buffer_dma - obtain block of chains (dma address) |
888 | * @ioc: per adapter object | 923 | * @ioc: per adapter object |
889 | * @smid: system request message index | 924 | * @smid: system request message index |
@@ -1889,7 +1924,6 @@ scsih_abort(struct scsi_cmnd *scmd) | |||
1889 | return r; | 1924 | return r; |
1890 | } | 1925 | } |
1891 | 1926 | ||
1892 | |||
1893 | /** | 1927 | /** |
1894 | * scsih_dev_reset - eh threads main device reset routine | 1928 | * scsih_dev_reset - eh threads main device reset routine |
1895 | * @sdev: scsi device struct | 1929 | * @sdev: scsi device struct |
@@ -1906,7 +1940,7 @@ scsih_dev_reset(struct scsi_cmnd *scmd) | |||
1906 | u16 handle; | 1940 | u16 handle; |
1907 | int r; | 1941 | int r; |
1908 | 1942 | ||
1909 | printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n", | 1943 | printk(MPT2SAS_INFO_FMT "attempting device reset! scmd(%p)\n", |
1910 | ioc->name, scmd); | 1944 | ioc->name, scmd); |
1911 | scsi_print_command(scmd); | 1945 | scsi_print_command(scmd); |
1912 | 1946 | ||
@@ -1941,6 +1975,78 @@ scsih_dev_reset(struct scsi_cmnd *scmd) | |||
1941 | 1975 | ||
1942 | mutex_lock(&ioc->tm_cmds.mutex); | 1976 | mutex_lock(&ioc->tm_cmds.mutex); |
1943 | mpt2sas_scsih_issue_tm(ioc, handle, 0, | 1977 | mpt2sas_scsih_issue_tm(ioc, handle, 0, |
1978 | MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, scmd->device->lun, | ||
1979 | 30); | ||
1980 | |||
1981 | /* | ||
1982 | * sanity check see whether all commands to this device been | ||
1983 | * completed | ||
1984 | */ | ||
1985 | if (_scsih_scsi_lookup_find_by_lun(ioc, scmd->device->id, | ||
1986 | scmd->device->lun, scmd->device->channel)) | ||
1987 | r = FAILED; | ||
1988 | else | ||
1989 | r = SUCCESS; | ||
1990 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | ||
1991 | mutex_unlock(&ioc->tm_cmds.mutex); | ||
1992 | |||
1993 | out: | ||
1994 | printk(MPT2SAS_INFO_FMT "device reset: %s scmd(%p)\n", | ||
1995 | ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | ||
1996 | return r; | ||
1997 | } | ||
1998 | |||
1999 | /** | ||
2000 | * scsih_target_reset - eh threads main target reset routine | ||
2001 | * @sdev: scsi device struct | ||
2002 | * | ||
2003 | * Returns SUCCESS if command aborted else FAILED | ||
2004 | */ | ||
2005 | static int | ||
2006 | scsih_target_reset(struct scsi_cmnd *scmd) | ||
2007 | { | ||
2008 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | ||
2009 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
2010 | struct _sas_device *sas_device; | ||
2011 | unsigned long flags; | ||
2012 | u16 handle; | ||
2013 | int r; | ||
2014 | |||
2015 | printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n", | ||
2016 | ioc->name, scmd); | ||
2017 | scsi_print_command(scmd); | ||
2018 | |||
2019 | sas_device_priv_data = scmd->device->hostdata; | ||
2020 | if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { | ||
2021 | printk(MPT2SAS_INFO_FMT "target been deleted! scmd(%p)\n", | ||
2022 | ioc->name, scmd); | ||
2023 | scmd->result = DID_NO_CONNECT << 16; | ||
2024 | scmd->scsi_done(scmd); | ||
2025 | r = SUCCESS; | ||
2026 | goto out; | ||
2027 | } | ||
2028 | |||
2029 | /* for hidden raid components obtain the volume_handle */ | ||
2030 | handle = 0; | ||
2031 | if (sas_device_priv_data->sas_target->flags & | ||
2032 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
2033 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2034 | sas_device = _scsih_sas_device_find_by_handle(ioc, | ||
2035 | sas_device_priv_data->sas_target->handle); | ||
2036 | if (sas_device) | ||
2037 | handle = sas_device->volume_handle; | ||
2038 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2039 | } else | ||
2040 | handle = sas_device_priv_data->sas_target->handle; | ||
2041 | |||
2042 | if (!handle) { | ||
2043 | scmd->result = DID_RESET << 16; | ||
2044 | r = FAILED; | ||
2045 | goto out; | ||
2046 | } | ||
2047 | |||
2048 | mutex_lock(&ioc->tm_cmds.mutex); | ||
2049 | mpt2sas_scsih_issue_tm(ioc, handle, 0, | ||
1944 | MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30); | 2050 | MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30); |
1945 | 2051 | ||
1946 | /* | 2052 | /* |
@@ -5255,6 +5361,7 @@ static struct scsi_host_template scsih_driver_template = { | |||
5255 | .change_queue_type = scsih_change_queue_type, | 5361 | .change_queue_type = scsih_change_queue_type, |
5256 | .eh_abort_handler = scsih_abort, | 5362 | .eh_abort_handler = scsih_abort, |
5257 | .eh_device_reset_handler = scsih_dev_reset, | 5363 | .eh_device_reset_handler = scsih_dev_reset, |
5364 | .eh_target_reset_handler = scsih_target_reset, | ||
5258 | .eh_host_reset_handler = scsih_host_reset, | 5365 | .eh_host_reset_handler = scsih_host_reset, |
5259 | .bios_param = scsih_bios_param, | 5366 | .bios_param = scsih_bios_param, |
5260 | .can_queue = 1, | 5367 | .can_queue = 1, |