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

Commit ce4f75de authored by Jeff Skirvin's avatar Jeff Skirvin Committed by Dan Williams
Browse files

isci: Free host lock for SATA/STP abort escalation at submission time.



In the case of I/O requests that fail at submit time because of a
pending reset condition, the host lock for SATA/STP devices must be
managed for any SCSI-initiated I/O before sas_task_abort is called.

Signed-off-by: default avatarJeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent f219f010
Loading
Loading
Loading
Loading
+30 −30
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <scsi/sas_ata.h>
#include "isci.h"
#include "scic_remote_device.h"
#include "scic_io_request.h"
@@ -355,33 +356,6 @@ int isci_request_alloc_tmf(
	return retval;
}

/**
 * isci_request_signal_device_reset() - This function will set the "device
 *    needs target reset" flag in the given sas_tasks' task_state_flags, and
 *    then cause the task to be added into the SCSI error handler queue which
 *    will eventually be escalated to a target reset.
 *
 *
 */
static void isci_request_signal_device_reset(
	struct isci_request *isci_request)
{
	unsigned long flags;
	struct sas_task *task = isci_request_access_task(isci_request);

	dev_dbg(&isci_request->isci_host->pdev->dev,
		"%s: request=%p, task=%p\n", __func__, isci_request, task);

	spin_lock_irqsave(&task->task_state_lock, flags);
	task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	/* Cause this task to be scheduled in the SCSI error handler
	 * thread.
	 */
	sas_task_abort(task);
}

/**
 * isci_request_execute() - This function allocates the isci_request object,
 *    all fills in some common fields.
@@ -453,11 +427,18 @@ int isci_request_execute(
				/* Save the tag for possible task mgmt later. */
				request->io_tag = scic_io_request_get_io_tag(
						     request->sci_request_handle);
			} else {
				/* The request did not really start in the
				 * hardware, so clear the request handle
				 * here so no terminations will be done.
				 */
				request->sci_request_handle = NULL;
			}

		} else
			dev_warn(&isci_host->pdev->dev,
				 "%s: failed request start\n",
				 __func__);
				 "%s: failed request start (0x%x)\n",
				 __func__, status);

		spin_unlock_irqrestore(&isci_host->scic_lock, flags);

@@ -467,7 +448,26 @@ int isci_request_execute(
			* handler thread to work on this I/O and that
			* we want a device reset.
			*/
			isci_request_signal_device_reset(request);
			spin_lock_irqsave(&task->task_state_lock, flags);
			task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
			spin_unlock_irqrestore(&task->task_state_lock, flags);

			/* Cause this task to be scheduled in the SCSI error handler
			* thread.
			*/
			if (dev_is_sata(task->dev)) {
				/* Since we are still in the submit path, and since
				* libsas takes the host lock on behalf of SATA
				* devices before I/O starts, we need to unlock
				* before we can put the task in the error path.
				*/
				raw_local_irq_save(flags);
				spin_unlock(isci_host->shost->host_lock);
				sas_task_abort(task);
				spin_lock(isci_host->shost->host_lock);
				raw_local_irq_restore(flags);
			} else
				sas_task_abort(task);

			/* Change the status, since we are holding
			* the I/O until it is managed by the SCSI