diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2011-03-04 17:06:40 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 06:55:29 -0400 |
commit | 11b00c194cfbd0eb0d90f32c096508b2bb8be6ec (patch) | |
tree | 81e258a7715742d97eaa8675f45fac97a2118e20 | |
parent | 18d3d72a42a846d46b71131982c51d63eba2b7b3 (diff) |
isci: Changes in isci_host_completion_routine
Changes to move management of the reqs_in_process entry for the request here.
Made changes to note when the task is already in the abort path and
cannot be completed through callbacks.
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Jacek Danecki <Jacek.Danecki@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/scsi/isci/host.c | 75 | ||||
-rw-r--r-- | drivers/scsi/isci/host.h | 2 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 12 |
3 files changed, 64 insertions, 25 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index ae5d46022073..153f419f1618 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -270,27 +270,40 @@ static int isci_host_mdl_allocate_coherent( | |||
270 | static void isci_host_completion_routine(unsigned long data) | 270 | static void isci_host_completion_routine(unsigned long data) |
271 | { | 271 | { |
272 | struct isci_host *isci_host = (struct isci_host *)data; | 272 | struct isci_host *isci_host = (struct isci_host *)data; |
273 | struct list_head completed_request_list; | 273 | struct list_head completed_request_list; |
274 | struct list_head aborted_request_list; | 274 | struct list_head errored_request_list; |
275 | struct list_head *current_position; | 275 | struct list_head *current_position; |
276 | struct list_head *next_position; | 276 | struct list_head *next_position; |
277 | struct isci_request *request; | 277 | struct isci_request *request; |
278 | struct isci_request *next_request; | 278 | struct isci_request *next_request; |
279 | struct sas_task *task; | 279 | struct sas_task *task; |
280 | 280 | ||
281 | INIT_LIST_HEAD(&completed_request_list); | 281 | INIT_LIST_HEAD(&completed_request_list); |
282 | INIT_LIST_HEAD(&aborted_request_list); | 282 | INIT_LIST_HEAD(&errored_request_list); |
283 | 283 | ||
284 | spin_lock_irq(&isci_host->scic_lock); | 284 | spin_lock_irq(&isci_host->scic_lock); |
285 | 285 | ||
286 | scic_sds_controller_completion_handler(isci_host->core_controller); | 286 | scic_sds_controller_completion_handler(isci_host->core_controller); |
287 | 287 | ||
288 | /* Take the lists of completed I/Os from the host. */ | 288 | /* Take the lists of completed I/Os from the host. */ |
289 | |||
289 | list_splice_init(&isci_host->requests_to_complete, | 290 | list_splice_init(&isci_host->requests_to_complete, |
290 | &completed_request_list); | 291 | &completed_request_list); |
291 | 292 | ||
292 | list_splice_init(&isci_host->requests_to_abort, | 293 | /* While holding the scic_lock take all of the normally completed |
293 | &aborted_request_list); | 294 | * I/Os off of the device's pending lists. |
295 | */ | ||
296 | list_for_each_entry(request, &completed_request_list, completed_node) { | ||
297 | |||
298 | /* Remove the request from the remote device's list | ||
299 | * of pending requests. | ||
300 | */ | ||
301 | list_del_init(&request->dev_node); | ||
302 | } | ||
303 | |||
304 | /* Take the list of errored I/Os from the host. */ | ||
305 | list_splice_init(&isci_host->requests_to_errorback, | ||
306 | &errored_request_list); | ||
294 | 307 | ||
295 | spin_unlock_irq(&isci_host->scic_lock); | 308 | spin_unlock_irq(&isci_host->scic_lock); |
296 | 309 | ||
@@ -309,13 +322,22 @@ static void isci_host_completion_routine(unsigned long data) | |||
309 | request, | 322 | request, |
310 | task); | 323 | task); |
311 | 324 | ||
312 | task->task_done(task); | 325 | /* Return the task to libsas */ |
313 | task->lldd_task = NULL; | 326 | if (task != NULL) { |
327 | |||
328 | task->lldd_task = NULL; | ||
329 | if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | ||
314 | 330 | ||
331 | /* If the task is already in the abort path, | ||
332 | * the task_done callback cannot be called. | ||
333 | */ | ||
334 | task->task_done(task); | ||
335 | } | ||
336 | } | ||
315 | /* Free the request object. */ | 337 | /* Free the request object. */ |
316 | isci_request_free(isci_host, request); | 338 | isci_request_free(isci_host, request); |
317 | } | 339 | } |
318 | list_for_each_entry_safe(request, next_request, &aborted_request_list, | 340 | list_for_each_entry_safe(request, next_request, &errored_request_list, |
319 | completed_node) { | 341 | completed_node) { |
320 | 342 | ||
321 | task = isci_request_access_task(request); | 343 | task = isci_request_access_task(request); |
@@ -327,8 +349,33 @@ static void isci_host_completion_routine(unsigned long data) | |||
327 | request, | 349 | request, |
328 | task); | 350 | task); |
329 | 351 | ||
330 | /* Put the task into the abort path. */ | 352 | if (task != NULL) { |
331 | sas_task_abort(task); | 353 | |
354 | /* Put the task into the abort path if it's not there | ||
355 | * already. | ||
356 | */ | ||
357 | if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) | ||
358 | sas_task_abort(task); | ||
359 | |||
360 | } else { | ||
361 | /* This is a case where the request has completed with a | ||
362 | * status such that it needed further target servicing, | ||
363 | * but the sas_task reference has already been removed | ||
364 | * from the request. Since it was errored, it was not | ||
365 | * being aborted, so there is nothing to do except free | ||
366 | * it. | ||
367 | */ | ||
368 | |||
369 | spin_lock_irq(&isci_host->scic_lock); | ||
370 | /* Remove the request from the remote device's list | ||
371 | * of pending requests. | ||
372 | */ | ||
373 | list_del_init(&request->dev_node); | ||
374 | spin_unlock_irq(&isci_host->scic_lock); | ||
375 | |||
376 | /* Free the request object. */ | ||
377 | isci_request_free(isci_host, request); | ||
378 | } | ||
332 | } | 379 | } |
333 | 380 | ||
334 | } | 381 | } |
@@ -477,7 +524,7 @@ int isci_host_init(struct isci_host *isci_host) | |||
477 | INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); | 524 | INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); |
478 | 525 | ||
479 | INIT_LIST_HEAD(&isci_host->requests_to_complete); | 526 | INIT_LIST_HEAD(&isci_host->requests_to_complete); |
480 | INIT_LIST_HEAD(&isci_host->requests_to_abort); | 527 | INIT_LIST_HEAD(&isci_host->requests_to_errorback); |
481 | 528 | ||
482 | spin_lock_irq(&isci_host->scic_lock); | 529 | spin_lock_irq(&isci_host->scic_lock); |
483 | status = scic_controller_initialize(isci_host->core_controller); | 530 | status = scic_controller_initialize(isci_host->core_controller); |
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 3c69f1ffb1c3..889a7850255a 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h | |||
@@ -116,7 +116,7 @@ struct isci_host { | |||
116 | struct tasklet_struct completion_tasklet; | 116 | struct tasklet_struct completion_tasklet; |
117 | struct list_head mdl_struct_list; | 117 | struct list_head mdl_struct_list; |
118 | struct list_head requests_to_complete; | 118 | struct list_head requests_to_complete; |
119 | struct list_head requests_to_abort; | 119 | struct list_head requests_to_errorback; |
120 | spinlock_t scic_lock; | 120 | spinlock_t scic_lock; |
121 | 121 | ||
122 | /* careful only access this via idev_by_id */ | 122 | /* careful only access this via idev_by_id */ |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 6b0863e73f22..8039f1c72f72 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -836,7 +836,7 @@ static void isci_task_save_for_upper_layer_completion( | |||
836 | status); | 836 | status); |
837 | /* Add to the aborted list. */ | 837 | /* Add to the aborted list. */ |
838 | list_add(&request->completed_node, | 838 | list_add(&request->completed_node, |
839 | &host->requests_to_abort); | 839 | &host->requests_to_errorback); |
840 | break; | 840 | break; |
841 | 841 | ||
842 | default: | 842 | default: |
@@ -849,7 +849,7 @@ static void isci_task_save_for_upper_layer_completion( | |||
849 | 849 | ||
850 | /* Add to the aborted list. */ | 850 | /* Add to the aborted list. */ |
851 | list_add(&request->completed_node, | 851 | list_add(&request->completed_node, |
852 | &host->requests_to_abort); | 852 | &host->requests_to_errorback); |
853 | break; | 853 | break; |
854 | } | 854 | } |
855 | } | 855 | } |
@@ -1185,14 +1185,6 @@ void isci_request_io_request_complete( | |||
1185 | */ | 1185 | */ |
1186 | request->sci_request_handle = NULL; | 1186 | request->sci_request_handle = NULL; |
1187 | 1187 | ||
1188 | /* Only remove the request from the remote device list | ||
1189 | * of pending requests if we have not requested error | ||
1190 | * handling on this request. | ||
1191 | */ | ||
1192 | if (complete_to_host != isci_perform_error_io_completion) | ||
1193 | list_del_init(&request->dev_node); | ||
1194 | |||
1195 | |||
1196 | /* Save possible completion ptr. */ | 1188 | /* Save possible completion ptr. */ |
1197 | io_request_completion = request->io_request_completion; | 1189 | io_request_completion = request->io_request_completion; |
1198 | 1190 | ||