From ce4f75def3999fbe454da9aa733ed322bc671b06 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 31 Mar 2011 13:10:36 -0700 Subject: [PATCH] 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: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c6ce9d0c50c..946caaeb66c 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #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