Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+109 −2
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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)
		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 = {
	.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,