|
@@ -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
|