diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-03-10 00:27:46 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 06:55:30 -0400 |
commit | 50e7f9b5a9ae4a763b2c27500807cf237faca9b0 (patch) | |
tree | 2275230176a12f2f0a5f7a395100b5a4f2c3e134 | |
parent | 70957a94d70cb82459bd3aea171c54d0a5cd6dbb (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.c | 87 | ||||
-rw-r--r-- | drivers/scsi/isci/task.h | 59 |
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 | */ | ||
81 | static 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 | */ | ||
355 | static 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_) */ |