isci: Manage tag releases differently when aborting tasks.
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>
Fri, 9 Mar 2012 06:42:03 +0000 (22:42 -0800)
committerDan Williams <dan.j.williams@intel.com>
Thu, 17 May 2012 21:33:41 +0000 (14:33 -0700)
When an individual request is being terminated, the request's tag
is managed in the terminate function.

Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/scsi/isci/host.c
drivers/scsi/isci/remote_device.c
drivers/scsi/isci/request.h
drivers/scsi/isci/task.c

index 53c3ad6..ef2790f 100644 (file)
@@ -1141,7 +1141,8 @@ void isci_host_completion_routine(unsigned long data)
                if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &request->flags))
                        wake_up_all(&ihost->eventq);
 
-               isci_free_tag(ihost, request->io_tag);
+               if (!test_bit(IREQ_NO_AUTO_FREE_TAG, &request->flags))
+                       isci_free_tag(ihost, request->io_tag);
        }
        spin_unlock_irq(&ihost->scic_lock);
 
index 21a9800..adeda64 100644 (file)
@@ -104,15 +104,15 @@ static enum sci_status sci_remote_device_terminate_req(
        int check_abort,
        struct isci_request *ireq)
 {
-       dev_dbg(&ihost->pdev->dev,
-               "%s: idev=%p; flags=%lx; req=%p; req target=%p\n",
-               __func__, idev, idev->flags, ireq, ireq->target_device);
-
        if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
            (ireq->target_device != idev) ||
            (check_abort && !test_bit(IREQ_PENDING_ABORT, &ireq->flags)))
                return SCI_SUCCESS;
 
+       dev_dbg(&ihost->pdev->dev,
+               "%s: idev=%p; flags=%lx; req=%p; req target=%p\n",
+               __func__, idev, idev->flags, ireq, ireq->target_device);
+
        set_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);
 
        return sci_controller_terminate_request(ihost, idev, ireq);
@@ -209,11 +209,14 @@ enum sci_status isci_remote_device_terminate_requests(
                        rnc_suspend_count, idev->rnc.suspend_count);
                if (ireq) {
                        /* Terminate a specific TC. */
+                       set_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags);
                        sci_remote_device_terminate_req(ihost, idev, 0, ireq);
                        spin_unlock_irqrestore(&ihost->scic_lock, flags);
                        wait_event(ihost->eventq,
                                   isci_check_reqterm(ihost, idev, ireq,
                                                      rnc_suspend_count));
+                       clear_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags);
+                       isci_free_tag(ihost, ireq->io_tag);
                } else {
                        /* Terminate all TCs. */
                        sci_remote_device_terminate_requests(idev);
index d12e975..1a65157 100644 (file)
@@ -87,6 +87,7 @@ struct isci_request {
        #define IREQ_PENDING_ABORT 4 /* Set == device was not suspended yet */
        #define IREQ_TC_ABORT_POSTED 5
        #define IREQ_ABORT_PATH_ACTIVE 6
+       #define IREQ_NO_AUTO_FREE_TAG 7 /* Set when being explicitly managed */
        unsigned long flags;
        /* XXX kill ttype and ttype_ptr, allocate full sas_task */
        union ttype_ptr_union {
index c1c6dd0..e798c6a 100644 (file)
@@ -719,7 +719,8 @@ isci_task_request_complete(struct isci_host *ihost,
         */
        set_bit(IREQ_TERMINATED, &ireq->flags);
 
-       isci_free_tag(ihost, ireq->io_tag);
+       if (!test_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags))
+               isci_free_tag(ihost, ireq->io_tag);
 
        /* The task management part completes last. */
        if (tmf_complete)