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 /drivers/scsi/isci/host.c | |
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>
Diffstat (limited to 'drivers/scsi/isci/host.c')
-rw-r--r-- | drivers/scsi/isci/host.c | 75 |
1 files changed, 61 insertions, 14 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); |