Commit 993e0da7 authored by Eric Moore's avatar Eric Moore Committed by James Bottomley

[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: default avatarEric Moore <eric.moore@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 3c621b3e
...@@ -883,6 +883,41 @@ _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id, ...@@ -883,6 +883,41 @@ _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
return found; return found;
} }
/**
* _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
* @ioc: per adapter object
* @id: target id
* @lun: lun number
* @channel: channel
* Context: This function will acquire ioc->scsi_lookup_lock.
*
* This will search for a matching channel:id:lun in the scsi_lookup array,
* returning 1 if found.
*/
static u8
_scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
unsigned int lun, int channel)
{
u8 found;
unsigned long flags;
int i;
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
found = 0;
for (i = 0 ; i < ioc->request_depth; i++) {
if (ioc->scsi_lookup[i].scmd &&
(ioc->scsi_lookup[i].scmd->device->id == id &&
ioc->scsi_lookup[i].scmd->device->channel == channel &&
ioc->scsi_lookup[i].scmd->device->lun == lun)) {
found = 1;
goto out;
}
}
out:
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
return found;
}
/** /**
* _scsih_get_chain_buffer_dma - obtain block of chains (dma address) * _scsih_get_chain_buffer_dma - obtain block of chains (dma address)
* @ioc: per adapter object * @ioc: per adapter object
...@@ -1889,7 +1924,6 @@ scsih_abort(struct scsi_cmnd *scmd) ...@@ -1889,7 +1924,6 @@ scsih_abort(struct scsi_cmnd *scmd)
return r; return r;
} }
/** /**
* scsih_dev_reset - eh threads main device reset routine * scsih_dev_reset - eh threads main device reset routine
* @sdev: scsi device struct * @sdev: scsi device struct
...@@ -1906,7 +1940,7 @@ scsih_dev_reset(struct scsi_cmnd *scmd) ...@@ -1906,7 +1940,7 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
u16 handle; u16 handle;
int r; int r;
printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n", printk(MPT2SAS_INFO_FMT "attempting device reset! scmd(%p)\n",
ioc->name, scmd); ioc->name, scmd);
scsi_print_command(scmd); scsi_print_command(scmd);
...@@ -1939,6 +1973,78 @@ scsih_dev_reset(struct scsi_cmnd *scmd) ...@@ -1939,6 +1973,78 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
goto out; goto out;
} }
mutex_lock(&ioc->tm_cmds.mutex);
mpt2sas_scsih_issue_tm(ioc, handle, 0,
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, scmd->device->lun,
30);
/*
* sanity check see whether all commands to this device been
* completed
*/
if (_scsih_scsi_lookup_find_by_lun(ioc, scmd->device->id,
scmd->device->lun, scmd->device->channel))
r = FAILED;
else
r = SUCCESS;
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->tm_cmds.mutex);
out:
printk(MPT2SAS_INFO_FMT "device reset: %s scmd(%p)\n",
ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
return r;
}
/**
* scsih_target_reset - eh threads main target reset routine
* @sdev: scsi device struct
*
* Returns SUCCESS if command aborted else FAILED
*/
static int
scsih_target_reset(struct scsi_cmnd *scmd)
{
struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT2SAS_DEVICE *sas_device_priv_data;
struct _sas_device *sas_device;
unsigned long flags;
u16 handle;
int r;
printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n",
ioc->name, scmd);
scsi_print_command(scmd);
sas_device_priv_data = scmd->device->hostdata;
if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
printk(MPT2SAS_INFO_FMT "target been deleted! scmd(%p)\n",
ioc->name, scmd);
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
r = SUCCESS;
goto out;
}
/* for hidden raid components obtain the volume_handle */
handle = 0;
if (sas_device_priv_data->sas_target->flags &
MPT_TARGET_FLAGS_RAID_COMPONENT) {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc,
sas_device_priv_data->sas_target->handle);
if (sas_device)
handle = sas_device->volume_handle;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
} else
handle = sas_device_priv_data->sas_target->handle;
if (!handle) {
scmd->result = DID_RESET << 16;
r = FAILED;
goto out;
}
mutex_lock(&ioc->tm_cmds.mutex); mutex_lock(&ioc->tm_cmds.mutex);
mpt2sas_scsih_issue_tm(ioc, handle, 0, mpt2sas_scsih_issue_tm(ioc, handle, 0,
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30); MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30);
...@@ -5255,6 +5361,7 @@ static struct scsi_host_template scsih_driver_template = { ...@@ -5255,6 +5361,7 @@ static struct scsi_host_template scsih_driver_template = {
.change_queue_type = scsih_change_queue_type, .change_queue_type = scsih_change_queue_type,
.eh_abort_handler = scsih_abort, .eh_abort_handler = scsih_abort,
.eh_device_reset_handler = scsih_dev_reset, .eh_device_reset_handler = scsih_dev_reset,
.eh_target_reset_handler = scsih_target_reset,
.eh_host_reset_handler = scsih_host_reset, .eh_host_reset_handler = scsih_host_reset,
.bios_param = scsih_bios_param, .bios_param = scsih_bios_param,
.can_queue = 1, .can_queue = 1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment