aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-10-27 18:05:01 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-10-31 05:16:04 -0400
commitd6891682220c18c01bf6838f30e37342c38fde44 (patch)
treead0c61215cbc9de6c82e95825923f95ebc2532a1 /drivers/scsi
parentc2cb8a5fd7d5d8729a4fc25937c4d6564f9a7aa3 (diff)
[SCSI] isci: Fix tag leak in tasks and terminated requests.
Make sure terminated requests and completed task tags are freed. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/isci/task.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index e8cf17b024a4..7180b048c34b 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -552,11 +552,27 @@ static void isci_request_cleanup_completed_loiterer(
552 552
553 if (isci_request != NULL) { 553 if (isci_request != NULL) {
554 spin_lock_irqsave(&isci_host->scic_lock, flags); 554 spin_lock_irqsave(&isci_host->scic_lock, flags);
555 isci_free_tag(isci_host, isci_request->io_tag);
556 isci_request_change_state(isci_request, unallocated);
555 list_del_init(&isci_request->dev_node); 557 list_del_init(&isci_request->dev_node);
556 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 558 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
557 } 559 }
558} 560}
559 561
562static int isci_request_is_dealloc_managed(enum isci_request_status stat)
563{
564 switch (stat) {
565 case aborted:
566 case aborting:
567 case terminating:
568 case completed:
569 case dead:
570 return true;
571 default:
572 return false;
573 }
574}
575
560/** 576/**
561 * isci_terminate_request_core() - This function will terminate the given 577 * isci_terminate_request_core() - This function will terminate the given
562 * request, and wait for it to complete. This function must only be called 578 * request, and wait for it to complete. This function must only be called
@@ -574,7 +590,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
574 enum sci_status status = SCI_SUCCESS; 590 enum sci_status status = SCI_SUCCESS;
575 bool was_terminated = false; 591 bool was_terminated = false;
576 bool needs_cleanup_handling = false; 592 bool needs_cleanup_handling = false;
577 enum isci_request_status request_status;
578 unsigned long flags; 593 unsigned long flags;
579 unsigned long termination_completed = 1; 594 unsigned long termination_completed = 1;
580 struct completion *io_request_completion; 595 struct completion *io_request_completion;
@@ -702,23 +717,11 @@ static void isci_terminate_request_core(struct isci_host *ihost,
702 * needs to be detached and freed here. 717 * needs to be detached and freed here.
703 */ 718 */
704 spin_lock_irqsave(&isci_request->state_lock, flags); 719 spin_lock_irqsave(&isci_request->state_lock, flags);
705 request_status = isci_request->status; 720
706 721 needs_cleanup_handling
707 if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ 722 = isci_request_is_dealloc_managed(
708 && ((request_status == aborted) 723 isci_request->status);
709 || (request_status == aborting) 724
710 || (request_status == terminating)
711 || (request_status == completed)
712 || (request_status == dead)
713 )
714 ) {
715
716 /* The completion routine won't free a request in
717 * the aborted/aborting/etc. states, so we do
718 * it here.
719 */
720 needs_cleanup_handling = true;
721 }
722 spin_unlock_irqrestore(&isci_request->state_lock, flags); 725 spin_unlock_irqrestore(&isci_request->state_lock, flags);
723 726
724 } 727 }
@@ -1329,8 +1332,16 @@ isci_task_request_complete(struct isci_host *ihost,
1329 */ 1332 */
1330 set_bit(IREQ_TERMINATED, &ireq->flags); 1333 set_bit(IREQ_TERMINATED, &ireq->flags);
1331 1334
1332 isci_request_change_state(ireq, unallocated); 1335 /* As soon as something is in the terminate path, deallocation is
1333 list_del_init(&ireq->dev_node); 1336 * managed there. Note that the final non-managed state of a task
1337 * request is "completed".
1338 */
1339 if ((ireq->status == completed) ||
1340 !isci_request_is_dealloc_managed(ireq->status)) {
1341 isci_request_change_state(ireq, unallocated);
1342 isci_free_tag(ihost, ireq->io_tag);
1343 list_del_init(&ireq->dev_node);
1344 }
1334 1345
1335 /* The task management part completes last. */ 1346 /* The task management part completes last. */
1336 complete(tmf_complete); 1347 complete(tmf_complete);