diff options
-rw-r--r-- | drivers/scsi/isci/task.c | 141 |
1 files changed, 71 insertions, 70 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index e9bfc22d91d0..3dc9ef3f305b 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
@@ -83,21 +83,10 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
83 | unsigned long flags; | 83 | unsigned long flags; |
84 | int ret; | 84 | int ret; |
85 | enum sci_status status; | 85 | enum sci_status status; |
86 | 86 | enum isci_status device_status; | |
87 | 87 | ||
88 | dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num); | 88 | dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num); |
89 | 89 | ||
90 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | ||
91 | |||
92 | isci_task_complete_for_upper_layer( | ||
93 | task, | ||
94 | SAS_TASK_UNDELIVERED, | ||
95 | SAM_STAT_TASK_ABORTED, | ||
96 | isci_perform_normal_io_completion | ||
97 | ); | ||
98 | |||
99 | return 0; /* The I/O was accepted (and failed). */ | ||
100 | } | ||
101 | if ((task->dev == NULL) || (task->dev->port == NULL)) { | 90 | if ((task->dev == NULL) || (task->dev->port == NULL)) { |
102 | 91 | ||
103 | /* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer | 92 | /* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer |
@@ -143,93 +132,105 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
143 | /* We don't have a valid host reference, so we | 132 | /* We don't have a valid host reference, so we |
144 | * can't control the host queueing condition. | 133 | * can't control the host queueing condition. |
145 | */ | 134 | */ |
146 | continue; | 135 | goto next_task; |
147 | } | 136 | } |
148 | 137 | ||
149 | device = isci_dev_from_domain_dev(task->dev); | 138 | device = isci_dev_from_domain_dev(task->dev); |
150 | 139 | ||
151 | isci_host = isci_host_from_sas_ha(task->dev->port->ha); | 140 | isci_host = isci_host_from_sas_ha(task->dev->port->ha); |
152 | 141 | ||
153 | if (device && device->status == isci_ready) { | 142 | if (device) |
143 | device_status = device->status; | ||
144 | else | ||
145 | device_status = isci_freed; | ||
146 | |||
147 | /* From this point onward, any process that needs to guarantee | ||
148 | * that there is no kernel I/O being started will have to wait | ||
149 | * for the quiesce spinlock. | ||
150 | */ | ||
151 | |||
152 | if (device_status != isci_ready_for_io) { | ||
154 | 153 | ||
155 | /* Forces a retry from scsi mid layer. */ | 154 | /* Forces a retry from scsi mid layer. */ |
156 | dev_warn(task->dev->port->ha->dev, | 155 | dev_warn(task->dev->port->ha->dev, |
157 | "%s: task %p: isci_host->status = %d, " | 156 | "%s: task %p: isci_host->status = %d, " |
158 | "device = %p\n", | 157 | "device = %p; device_status = 0x%x\n\n", |
159 | __func__, | 158 | __func__, |
160 | task, | 159 | task, |
161 | isci_host_get_state(isci_host), | 160 | isci_host_get_state(isci_host), |
162 | device); | 161 | device, device_status); |
163 | |||
164 | if (device) | ||
165 | dev_dbg(task->dev->port->ha->dev, | ||
166 | "%s: device->status = 0x%x\n", | ||
167 | __func__, device->status); | ||
168 | 162 | ||
169 | /* Indicate QUEUE_FULL so that the scsi midlayer | 163 | if (device_status == isci_ready) { |
170 | * retries. | 164 | /* Indicate QUEUE_FULL so that the scsi midlayer |
171 | */ | 165 | * retries. |
172 | isci_task_complete_for_upper_layer( | 166 | */ |
173 | task, | 167 | isci_task_complete_for_upper_layer( |
174 | SAS_TASK_COMPLETE, | 168 | task, |
175 | SAS_QUEUE_FULL, | 169 | SAS_TASK_COMPLETE, |
176 | isci_perform_normal_io_completion | 170 | SAS_QUEUE_FULL, |
177 | ); | 171 | isci_perform_normal_io_completion |
172 | ); | ||
173 | } else { | ||
174 | /* Else, the device is going down. */ | ||
175 | isci_task_complete_for_upper_layer( | ||
176 | task, | ||
177 | SAS_TASK_UNDELIVERED, | ||
178 | SAS_DEVICE_UNKNOWN, | ||
179 | isci_perform_normal_io_completion | ||
180 | ); | ||
181 | } | ||
178 | isci_host_can_dequeue(isci_host, 1); | 182 | isci_host_can_dequeue(isci_host, 1); |
179 | } | 183 | } else { |
180 | /* the device is going down... */ | 184 | /* There is a device and it's ready for I/O. */ |
181 | else if (!device || device->status != isci_ready_for_io) { | 185 | spin_lock_irqsave(&task->task_state_lock, flags); |
182 | 186 | ||
183 | dev_dbg(task->dev->port->ha->dev, | 187 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { |
184 | "%s: task %p: isci_host->status = %d, " | ||
185 | "device = %p\n", | ||
186 | __func__, | ||
187 | task, | ||
188 | isci_host_get_state(isci_host), | ||
189 | device); | ||
190 | 188 | ||
191 | if (device) | 189 | spin_unlock_irqrestore(&task->task_state_lock, |
192 | dev_dbg(task->dev->port->ha->dev, | 190 | flags); |
193 | "%s: device->status = 0x%x\n", | ||
194 | __func__, device->status); | ||
195 | 191 | ||
196 | /* Indicate SAS_TASK_UNDELIVERED, so that the scsi | 192 | isci_task_complete_for_upper_layer( |
197 | * midlayer removes the target. | 193 | task, |
198 | */ | 194 | SAS_TASK_UNDELIVERED, |
199 | isci_task_complete_for_upper_layer( | 195 | SAM_STAT_TASK_ABORTED, |
200 | task, | 196 | isci_perform_normal_io_completion |
201 | SAS_TASK_UNDELIVERED, | 197 | ); |
202 | SAS_DEVICE_UNKNOWN, | ||
203 | isci_perform_normal_io_completion | ||
204 | ); | ||
205 | isci_host_can_dequeue(isci_host, 1); | ||
206 | 198 | ||
207 | } else { | 199 | /* The I/O was aborted. */ |
208 | /* build and send the request. */ | ||
209 | status = isci_request_execute(isci_host, task, &request, | ||
210 | gfp_flags); | ||
211 | 200 | ||
212 | if (status == SCI_SUCCESS) { | 201 | } else { |
213 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
214 | task->task_state_flags |= SAS_TASK_AT_INITIATOR; | 202 | task->task_state_flags |= SAS_TASK_AT_INITIATOR; |
215 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 203 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
216 | } else { | 204 | |
217 | /* Indicate QUEUE_FULL so that the scsi | 205 | /* build and send the request. */ |
218 | * midlayer retries. if the request | 206 | status = isci_request_execute(isci_host, task, &request, |
219 | * failed for remote device reasons, | 207 | gfp_flags); |
220 | * it gets returned as | 208 | |
221 | * SAS_TASK_UNDELIVERED next time | 209 | if (status != SCI_SUCCESS) { |
222 | * through. | 210 | |
223 | */ | 211 | spin_lock_irqsave(&task->task_state_lock, flags); |
224 | isci_task_complete_for_upper_layer( | 212 | /* Did not really start this command. */ |
213 | task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
214 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
215 | |||
216 | /* Indicate QUEUE_FULL so that the scsi | ||
217 | * midlayer retries. if the request | ||
218 | * failed for remote device reasons, | ||
219 | * it gets returned as | ||
220 | * SAS_TASK_UNDELIVERED next time | ||
221 | * through. | ||
222 | */ | ||
223 | isci_task_complete_for_upper_layer( | ||
225 | task, | 224 | task, |
226 | SAS_TASK_COMPLETE, | 225 | SAS_TASK_COMPLETE, |
227 | SAS_QUEUE_FULL, | 226 | SAS_QUEUE_FULL, |
228 | isci_perform_normal_io_completion | 227 | isci_perform_normal_io_completion |
229 | ); | 228 | ); |
230 | isci_host_can_dequeue(isci_host, 1); | 229 | isci_host_can_dequeue(isci_host, 1); |
230 | } | ||
231 | } | 231 | } |
232 | } | 232 | } |
233 | next_task: | ||
233 | task = list_entry(task->list.next, struct sas_task, list); | 234 | task = list_entry(task->list.next, struct sas_task, list); |
234 | } while (--num > 0); | 235 | } while (--num > 0); |
235 | return 0; | 236 | return 0; |