aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-03-10 00:27:46 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:30 -0400
commit50e7f9b5a9ae4a763b2c27500807cf237faca9b0 (patch)
tree2275230176a12f2f0a5f7a395100b5a4f2c3e134
parent70957a94d70cb82459bd3aea171c54d0a5cd6dbb (diff)
isci: Errors in the submit path for SATA devices manage the ap lock.
Since libsas takes the domain device sata_dev.ap->lock before submitting a task, error completions in the submit path for SATA devices must unlock/relock when completing the sas_task back to libsas. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/scsi/isci/task.c87
-rw-r--r--drivers/scsi/isci/task.h59
2 files changed, 87 insertions, 59 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index a1234e42937e..d00b4c97b85b 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -54,6 +54,8 @@
54 */ 54 */
55 55
56#include <linux/completion.h> 56#include <linux/completion.h>
57#include <linux/irqflags.h>
58#include <scsi/sas_ata.h>
57#include "scic_task_request.h" 59#include "scic_task_request.h"
58#include "scic_remote_device.h" 60#include "scic_remote_device.h"
59#include "scic_io_request.h" 61#include "scic_io_request.h"
@@ -64,6 +66,91 @@
64#include "sata.h" 66#include "sata.h"
65#include "task.h" 67#include "task.h"
66 68
69/**
70* isci_task_complete_for_upper_layer() - This function completes the request
71* to the upper layer driver in the case where an I/O needs to be completed
72* back in the submit path.
73* @host: This parameter is a pointer to the host on which the the request
74* should be queued (either as an error or success).
75* @task: This parameter is the completed request.
76* @response: This parameter is the response code for the completed task.
77* @status: This parameter is the status code for the completed task.
78*
79* none.
80*/
81static void isci_task_complete_for_upper_layer(struct sas_task *task,
82 enum service_response response,
83 enum exec_status status,
84 enum isci_completion_selection task_notification_selection)
85{
86 unsigned long flags = 0;
87 struct Scsi_Host *host = NULL;
88
89 task_notification_selection
90 = isci_task_set_completion_status(task, response, status,
91 task_notification_selection);
92
93 /* Tasks aborted specifically by a call to the lldd_abort_task
94 * function should not be completed to the host in the regular path.
95 */
96 switch (task_notification_selection) {
97 case isci_perform_normal_io_completion:
98 /* Normal notification (task_done) */
99 dev_dbg(task->dev->port->ha->dev,
100 "%s: Normal - task = %p, response=%d, status=%d\n",
101 __func__, task, response, status);
102
103 if (dev_is_sata(task->dev)) {
104 /* Since we are still in the submit path, and since
105 * libsas takes the host lock on behalf of SATA
106 * devices before I/O starts, we need to unlock
107 * before we can call back and report the I/O
108 * submission error.
109 */
110 if (task->dev
111 && task->dev->port
112 && task->dev->port->ha) {
113
114 host = task->dev->port->ha->core.shost;
115 raw_local_irq_save(flags);
116 spin_unlock(host->host_lock);
117 }
118 task->task_done(task);
119 if (host) {
120 spin_lock(host->host_lock);
121 raw_local_irq_restore(flags);
122 }
123 } else
124 task->task_done(task);
125
126 task->lldd_task = NULL;
127 break;
128
129 case isci_perform_aborted_io_completion:
130 /* No notification because this request is already in the
131 * abort path.
132 */
133 dev_warn(task->dev->port->ha->dev,
134 "%s: Aborted - task = %p, response=%d, status=%d\n",
135 __func__, task, response, status);
136 break;
137
138 case isci_perform_error_io_completion:
139 /* Use sas_task_abort */
140 dev_warn(task->dev->port->ha->dev,
141 "%s: Error - task = %p, response=%d, status=%d\n",
142 __func__, task, response, status);
143 sas_task_abort(task);
144 break;
145
146 default:
147 dev_warn(task->dev->port->ha->dev,
148 "%s: isci task notification default case!",
149 __func__);
150 sas_task_abort(task);
151 break;
152 }
153}
67 154
68/** 155/**
69 * isci_task_execute_task() - This function is one of the SAS Domain Template 156 * isci_task_execute_task() - This function is one of the SAS Domain Template
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index 4c2a27eede49..e1c9c8f04050 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -341,64 +341,5 @@ isci_task_set_completion_status(
341 return task_notification_selection; 341 return task_notification_selection;
342 342
343} 343}
344/**
345 * isci_task_complete_for_upper_layer() - This function completes the request
346 * to the upper layer driver.
347 * @host: This parameter is a pointer to the host on which the the request
348 * should be queued (either as an error or success).
349 * @request: This parameter is the completed request.
350 * @response: This parameter is the response code for the completed task.
351 * @status: This parameter is the status code for the completed task.
352 *
353 * none.
354 */
355static inline void isci_task_complete_for_upper_layer(
356 struct sas_task *task,
357 enum service_response response,
358 enum exec_status status,
359 enum isci_completion_selection task_notification_selection)
360{
361 task_notification_selection
362 = isci_task_set_completion_status(task, response, status,
363 task_notification_selection);
364
365 /* Tasks aborted specifically by a call to the lldd_abort_task
366 * function should not be completed to the host in the regular path.
367 */
368 switch (task_notification_selection) {
369 case isci_perform_normal_io_completion:
370 /* Normal notification (task_done) */
371 dev_dbg(task->dev->port->ha->dev,
372 "%s: Normal - task = %p, response=%d, status=%d\n",
373 __func__, task, response, status);
374 task->task_done(task);
375 task->lldd_task = NULL;
376 break;
377
378 case isci_perform_aborted_io_completion:
379 /* No notification because this request is already in the
380 * abort path.
381 */
382 dev_warn(task->dev->port->ha->dev,
383 "%s: Aborted - task = %p, response=%d, status=%d\n",
384 __func__, task, response, status);
385 break;
386
387 case isci_perform_error_io_completion:
388 /* Use sas_task_abort */
389 dev_warn(task->dev->port->ha->dev,
390 "%s: Error - task = %p, response=%d, status=%d\n",
391 __func__, task, response, status);
392 sas_task_abort(task);
393 break;
394
395 default:
396 dev_warn(task->dev->port->ha->dev,
397 "%s: isci task notification default case!",
398 __func__);
399 sas_task_abort(task);
400 break;
401 }
402}
403 344
404#endif /* !defined(_SCI_TASK_H_) */ 345#endif /* !defined(_SCI_TASK_H_) */