lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 25 Jul 2014 18:27:08 +0530
From:	Sreekanth Reddy <sreekanth.reddy@...gotech.com>
To:	"Martin K. Petersen" <martin.petersen@...cle.com>
Cc:	jejb@...nel.org, "James E.J. Bottomley" <JBottomley@...allels.com>,
	linux-scsi@...r.kernel.org,
	Sathya Prakash <Sathya.Prakash@...gotech.com>,
	Nagalakshmi Nandigama <Nagalakshmi.Nandigama@...gotech.com>,
	linux-kernel@...r.kernel.org, Christoph Hellwig <hch@...radead.org>
Subject: Re: [RESEND][PATCH 07/10][SCSI]mpt2sas: Added Reply Descriptor Post
 Queue (RDPQ) Array support

Hi Martin,

Following are the changes that I have done in this patch over the
first RDPQ support patch,

1. Reduced the redundancy in the function
_base_release_memory_pools(), _base_allocate_memory_pools().
2. Set pci_set_consistent_dma_mask() to DMA_BIT_MASK(32). still I am
analysing whether this change may affect on any other things or not?

Signed-off-by: Sreekanth Reddy <Sreekanth.Reddy@...gotech.com>

diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c
b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 6b2a79e..cf69e61 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -1186,7 +1186,7 @@ _base_config_dma_addressing(struct
MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
             dma_get_required_mask(&pdev->dev);
         if ((required_mask > DMA_BIT_MASK(32)) && !pci_set_dma_mask(pdev,
             DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev,
-            DMA_BIT_MASK(64))) {
+            DMA_BIT_MASK(32))) {
             ioc->base_add_sg_single = &_base_add_sg_single_64;
             ioc->sge_size = sizeof(Mpi2SGESimple64_t);
             desc = "64";
@@ -1424,6 +1424,9 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
     ioc->reply_queue_count = min_t(int, ioc->cpu_count,
         ioc->msix_vector_count);

+    if (!ioc->rdpq_array_enable && max_msix_vectors == -1)
+        max_msix_vectors = 8;
+
     if (max_msix_vectors > 0) {
         ioc->reply_queue_count = min_t(int, max_msix_vectors,
             ioc->reply_queue_count);
@@ -1477,6 +1480,335 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
 }

 /**
+ * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
+ * a write to the doorbell)
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
+ */
+static int
+_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
+    int sleep_flag)
+{
+    u32 cntdn, count;
+    u32 int_status;
+
+    count = 0;
+    cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+    do {
+        int_status = readl(&ioc->chip->HostInterruptStatus);
+        if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+            dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
+                "%s: successful count(%d), timeout(%d)\n",
+                ioc->name, __func__, count, timeout));
+            return 0;
+        }
+        if (sleep_flag == CAN_SLEEP)
+            msleep(1);
+        else
+            udelay(500);
+        count++;
+    } while (--cntdn);
+
+    printk(MPT2SAS_ERR_FMT
+        "%s: failed due to timeout count(%d), int_status(%x)!\n",
+        ioc->name, __func__, count, int_status);
+    return -EFAULT;
+}
+
+/**
+ * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
+ * doorbell.
+ */
+static int
+_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
+    int sleep_flag)
+{
+    u32 cntdn, count;
+    u32 int_status;
+    u32 doorbell;
+
+    count = 0;
+    cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+    do {
+        int_status = readl(&ioc->chip->HostInterruptStatus);
+        if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
+            dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
+                "%s: successful count(%d), timeout(%d)\n",
+                ioc->name, __func__, count, timeout));
+            return 0;
+        } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+            doorbell = readl(&ioc->chip->Doorbell);
+            if ((doorbell & MPI2_IOC_STATE_MASK) ==
+                MPI2_IOC_STATE_FAULT) {
+                mpt2sas_base_fault_info(ioc , doorbell);
+                return -EFAULT;
+            }
+        } else if (int_status == 0xFFFFFFFF)
+            goto out;
+
+        if (sleep_flag == CAN_SLEEP)
+            msleep(1);
+        else
+            udelay(500);
+        count++;
+    } while (--cntdn);
+
+ out:
+    printk(MPT2SAS_ERR_FMT
+        "%s: failed due to timeout count(%d), int_status(%x)!\n",
+        ioc->name, __func__, count, int_status);
+    return -EFAULT;
+}
+
+/**
+ * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
+    int sleep_flag)
+{
+    u32 cntdn, count;
+    u32 doorbell_reg;
+
+    count = 0;
+    cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+    do {
+        doorbell_reg = readl(&ioc->chip->Doorbell);
+        if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
+            dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
+                "%s: successful count(%d), timeout(%d)\n",
+                ioc->name, __func__, count, timeout));
+            return 0;
+        }
+        if (sleep_flag == CAN_SLEEP)
+            msleep(1);
+        else
+            udelay(500);
+        count++;
+    } while (--cntdn);
+
+    printk(MPT2SAS_ERR_FMT
+        "%s: failed due to timeout count(%d), doorbell_reg(%x)!\n",
+        ioc->name, __func__, count, doorbell_reg);
+    return -EFAULT;
+}
+
+/**
+ * _base_handshake_req_reply_wait - send request thru doorbell interface
+ * @ioc: per adapter object
+ * @request_bytes: request length
+ * @request: pointer having request payload
+ * @reply_bytes: reply length
+ * @reply: pointer to reply payload
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
+    u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
+{
+    MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
+    int i;
+    u8 failed;
+    u16 dummy;
+    __le32 *mfp;
+
+    /* make sure doorbell is not in use */
+    if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
+        printk(MPT2SAS_ERR_FMT "doorbell is in use (line=%d)\n",
+            ioc->name, __LINE__);
+        return -EFAULT;
+    }
+
+    /* clear pending doorbell interrupts from previous state changes */
+    if (readl(&ioc->chip->HostInterruptStatus) &
+        MPI2_HIS_IOC2SYS_DB_STATUS)
+        writel(0, &ioc->chip->HostInterruptStatus);
+
+    /* send message to ioc */
+    writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
+        ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
+        &ioc->chip->Doorbell);
+
+    if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
+        printk(MPT2SAS_ERR_FMT
+           "doorbell handshake int failed (line=%d)\n",
+           ioc->name, __LINE__);
+        return -EFAULT;
+    }
+    writel(0, &ioc->chip->HostInterruptStatus);
+
+    if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
+        printk(MPT2SAS_ERR_FMT
+            "doorbell handshake ack failed (line=%d)\n",
+            ioc->name, __LINE__);
+        return -EFAULT;
+    }
+
+    /* send message 32-bits at a time */
+    for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
+        writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
+        if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
+            failed = 1;
+    }
+
+    if (failed) {
+        printk(MPT2SAS_ERR_FMT
+           "doorbell handshake sending request failed (line=%d)\n",
+           ioc->name, __LINE__);
+        return -EFAULT;
+    }
+
+    /* now wait for the reply */
+    if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
+        printk(MPT2SAS_ERR_FMT
+           "doorbell handshake int failed (line=%d)\n",
+           ioc->name, __LINE__);
+        return -EFAULT;
+    }
+
+    /* read the first two 16-bits, it gives the total length of the reply */
+    reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+        & MPI2_DOORBELL_DATA_MASK);
+    writel(0, &ioc->chip->HostInterruptStatus);
+    if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+        printk(MPT2SAS_ERR_FMT
+           "doorbell handshake int failed (line=%d)\n",
+           ioc->name, __LINE__);
+        return -EFAULT;
+    }
+    reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+        & MPI2_DOORBELL_DATA_MASK);
+    writel(0, &ioc->chip->HostInterruptStatus);
+
+    for (i = 2; i < default_reply->MsgLength * 2; i++)  {
+        if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+            printk(MPT2SAS_ERR_FMT
+                "doorbell handshake int failed (line=%d)\n",
+                ioc->name, __LINE__);
+            return -EFAULT;
+        }
+        if (i >=  reply_bytes/2) /* overflow case */
+            dummy = readl(&ioc->chip->Doorbell);
+        else
+            reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+                & MPI2_DOORBELL_DATA_MASK);
+        writel(0, &ioc->chip->HostInterruptStatus);
+    }
+
+    _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
+    if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
+        dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
+            "doorbell is in use (line=%d)\n", ioc->name, __LINE__));
+    }
+    writel(0, &ioc->chip->HostInterruptStatus);
+
+    if (ioc->logging_level & MPT_DEBUG_INIT) {
+        mfp = (__le32 *)reply;
+        pr_info("\toffset:data\n");
+        for (i = 0; i < reply_bytes/4; i++)
+            pr_info("\t[0x%02x]:%08x\n", i*4,
+                le32_to_cpu(mfp[i]));
+    }
+    return 0;
+}
+
+/**
+ * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
+{
+    Mpi2IOCFactsRequest_t mpi_request;
+    Mpi2IOCFactsReply_t mpi_reply;
+    struct mpt2sas_facts *facts;
+    int mpi_reply_sz, mpi_request_sz, r;
+
+    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+        __func__));
+
+    mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
+    mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
+    memset(&mpi_request, 0, mpi_request_sz);
+    mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
+    r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
+        (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
+
+    if (r != 0) {
+        printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
+            ioc->name, __func__, r);
+        return r;
+    }
+
+    facts = &ioc->facts;
+    memset(facts, 0, sizeof(struct mpt2sas_facts));
+    facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
+    facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
+    facts->VP_ID = mpi_reply.VP_ID;
+    facts->VF_ID = mpi_reply.VF_ID;
+    facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
+    facts->MaxChainDepth = mpi_reply.MaxChainDepth;
+    facts->WhoInit = mpi_reply.WhoInit;
+    facts->NumberOfPorts = mpi_reply.NumberOfPorts;
+    facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
+    facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
+    facts->MaxReplyDescriptorPostQueueDepth =
+        le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
+    facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
+    facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
+    if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
+        ioc->ir_firmware = 1;
+    if ((facts->IOCCapabilities &
+          MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE))
+        ioc->rdpq_array_capable = 1;
+    facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
+    facts->IOCRequestFrameSize =
+        le16_to_cpu(mpi_reply.IOCRequestFrameSize);
+    facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
+    facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
+    ioc->shost->max_id = -1;
+    facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
+    facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
+    facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
+    facts->HighPriorityCredit =
+        le16_to_cpu(mpi_reply.HighPriorityCredit);
+    facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
+    facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
+
+    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
+        "hba queue depth(%d), max chains per io(%d)\n", ioc->name,
+        facts->RequestCredit, facts->MaxChainDepth));
+    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
+        "request frame size(%d), reply frame size(%d)\n", ioc->name,
+        facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
+    return 0;
+}
+
+/**
  * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
  * @ioc: per adapter object
  *
@@ -1552,6 +1884,16 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
     }

     _base_mask_interrupts(ioc);
+
+    r = _base_get_ioc_facts(ioc, CAN_SLEEP);
+    if (r)
+        goto out_fail;
+
+    if (!ioc->rdpq_array_enable_assigned) {
+        ioc->rdpq_array_enable = ioc->rdpq_array_capable;
+        ioc->rdpq_array_enable_assigned = 1;
+    }
+
     r = _base_enable_msix(ioc);
     if (r)
         goto out_fail;
@@ -2349,7 +2691,7 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
 static void
 _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
 {
-    int i;
+    int i = 0;

     dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
         __func__));
@@ -2390,15 +2732,25 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
         ioc->reply_free = NULL;
     }

-    if (ioc->reply_post_free) {
-        pci_pool_free(ioc->reply_post_free_dma_pool,
-            ioc->reply_post_free, ioc->reply_post_free_dma);
+    if (ioc->reply_post) {
+        do {
+            if (ioc->reply_post[i].reply_post_free) {
+                pci_pool_free(
+                  ioc->reply_post_free_dma_pool,
+                  ioc->reply_post[i].reply_post_free,
+                  ioc->reply_post[i].reply_post_free_dma);
+                dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
+                  "reply_post_free_pool(0x%p): free\n",
+                  ioc->name,
+                  ioc->reply_post[i].reply_post_free));
+                ioc->reply_post[i].reply_post_free = NULL;
+            }
+        } while (ioc->rdpq_array_enable &&
+                (++i < ioc->reply_queue_count));
+
         if (ioc->reply_post_free_dma_pool)
             pci_pool_destroy(ioc->reply_post_free_dma_pool);
-        dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
-            "reply_post_free_pool(0x%p): free\n", ioc->name,
-            ioc->reply_post_free));
-        ioc->reply_post_free = NULL;
+        kfree(ioc->reply_post);
     }

     if (ioc->config_page) {
@@ -2429,7 +2781,6 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
     }
 }

-
 /**
  * _base_allocate_memory_pools - allocate start of day memory pools
  * @ioc: per adapter object
@@ -2752,233 +3103,130 @@ chain_done:
         "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
     total_sz += sz;

-    /* reply post queue, 16 byte align */
     reply_post_free_sz = ioc->reply_post_queue_depth *
         sizeof(Mpi2DefaultReplyDescriptor_t);
-    if (_base_is_controller_msix_enabled(ioc))
-        sz = reply_post_free_sz * ioc->reply_queue_count;
-    else
+    if (ioc->rdpq_array_enable)
         sz = reply_post_free_sz;
-    ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
-        ioc->pdev, sz, 16, 0);
-    if (!ioc->reply_post_free_dma_pool) {
-        printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_create "
-            "failed\n", ioc->name);
-        goto out;
+    else {
+        if (_base_is_controller_msix_enabled(ioc))
+            sz = reply_post_free_sz * ioc->reply_queue_count;
+        else
+            sz = reply_post_free_sz;
     }
-    ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
-        GFP_KERNEL, &ioc->reply_post_free_dma);
-    if (!ioc->reply_post_free) {
-        printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_alloc "
-            "failed\n", ioc->name);
+
+    ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ?
+        (ioc->reply_queue_count):1,
+        sizeof(struct reply_post_struct), GFP_KERNEL);
+
+    if (!ioc->reply_post) {
+        printk(MPT2SAS_ERR_FMT "reply_post_free pool: kcalloc failed\n",
+            ioc->name);
         goto out;
     }
-    memset(ioc->reply_post_free, 0, sz);
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply post free pool"
-        "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
-        ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
-        sz/1024));
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_post_free_dma = "
-        "(0x%llx)\n", ioc->name, (unsigned long long)
-        ioc->reply_post_free_dma));
-    total_sz += sz;

-    ioc->config_page_sz = 512;
-    ioc->config_page = pci_alloc_consistent(ioc->pdev,
-        ioc->config_page_sz, &ioc->config_page_dma);
-    if (!ioc->config_page) {
-        printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
-            "failed\n", ioc->name);
+    ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
+        ioc->pdev, sz, 16, 0);
+    if (!ioc->reply_post_free_dma_pool) {
+        printk(MPT2SAS_ERR_FMT
+         "reply_post_free pool: pci_pool_create failed\n",
+         ioc->name);
         goto out;
     }
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
-        "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
-        "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
-    total_sz += ioc->config_page_sz;
-
-    printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
-        ioc->name, total_sz/1024);
-    printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
-        "Max Controller Queue Depth(%d)\n",
-        ioc->name, ioc->shost->can_queue, facts->RequestCredit);
-    printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
-        ioc->name, ioc->shost->sg_tablesize);
-    return 0;
-
- out:
-    return -ENOMEM;
-}
-
-
-/**
- * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
- * @ioc: Pointer to MPT_ADAPTER structure
- * @cooked: Request raw or cooked IOC state
- *
- * Returns all IOC Doorbell register bits if cooked==0, else just the
- * Doorbell bits in MPI_IOC_STATE_MASK.
- */
-u32
-mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
-{
-    u32 s, sc;
-
-    s = readl(&ioc->chip->Doorbell);
-    sc = s & MPI2_IOC_STATE_MASK;
-    return cooked ? sc : s;
-}
-
-/**
- * _base_wait_on_iocstate - waiting on a particular ioc state
- * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
-    int sleep_flag)
-{
-    u32 count, cntdn;
-    u32 current_state;
-
-    count = 0;
-    cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-    do {
-        current_state = mpt2sas_base_get_iocstate(ioc, 1);
-        if (current_state == ioc_state)
-            return 0;
-        if (count && current_state == MPI2_IOC_STATE_FAULT)
-            break;
-        if (sleep_flag == CAN_SLEEP)
-            msleep(1);
-        else
-            udelay(500);
-        count++;
-    } while (--cntdn);
-
-    return current_state;
-}

-/**
- * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
- * a write to the doorbell)
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
- */
-static int
-_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
-    int sleep_flag)
-{
-    u32 cntdn, count;
-    u32 int_status;
-
-    count = 0;
-    cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-    do {
-        int_status = readl(&ioc->chip->HostInterruptStatus);
-        if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
-            dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                "successful count(%d), timeout(%d)\n", ioc->name,
-                __func__, count, timeout));
-            return 0;
-        }
-        if (sleep_flag == CAN_SLEEP)
-            msleep(1);
-        else
-            udelay(500);
-        count++;
-    } while (--cntdn);
-
-    printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
-        "int_status(%x)!\n", ioc->name, __func__, count, int_status);
-    return -EFAULT;
-}
-
-/**
- * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
- * doorbell.
- */
-static int
-_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
-    int sleep_flag)
-{
-    u32 cntdn, count;
-    u32 int_status;
-    u32 doorbell;
-
-    count = 0;
-    cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-    do {
-        int_status = readl(&ioc->chip->HostInterruptStatus);
-        if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
-            dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                "successful count(%d), timeout(%d)\n", ioc->name,
-                __func__, count, timeout));
-            return 0;
-        } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
-            doorbell = readl(&ioc->chip->Doorbell);
-            if ((doorbell & MPI2_IOC_STATE_MASK) ==
-                MPI2_IOC_STATE_FAULT) {
-                mpt2sas_base_fault_info(ioc , doorbell);
-                return -EFAULT;
-            }
-        } else if (int_status == 0xFFFFFFFF)
+    i = 0;
+    do {
+        ioc->reply_post[i].reply_post_free =
+            pci_pool_alloc(ioc->reply_post_free_dma_pool,
+            GFP_KERNEL,
+            &ioc->reply_post[i].reply_post_free_dma);
+        if (!ioc->reply_post[i].reply_post_free) {
+            printk(MPT2SAS_ERR_FMT
+            "reply_post_free pool: pci_pool_alloc failed\n",
+            ioc->name);
             goto out;
+        }
+        memset(ioc->reply_post[i].reply_post_free, 0, sz);
+        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
+            "reply post free pool (0x%p): depth(%d),"
+            "element_size(%d), pool_size(%d kB)\n", ioc->name,
+            ioc->reply_post[i].reply_post_free,
+            ioc->reply_post_queue_depth, 8, sz/1024));
+        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
+            "reply_post_free_dma = (0x%llx)\n", ioc->name,
+            (unsigned long long)
+            ioc->reply_post[i].reply_post_free_dma));
+        total_sz += sz;
+    } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));

-        if (sleep_flag == CAN_SLEEP)
-            msleep(1);
-        else
-            udelay(500);
-        count++;
-    } while (--cntdn);
+    ioc->config_page_sz = 512;
+    ioc->config_page = pci_alloc_consistent(ioc->pdev,
+        ioc->config_page_sz, &ioc->config_page_dma);
+    if (!ioc->config_page) {
+        printk(MPT2SAS_ERR_FMT
+            "config page: pci_pool_alloc failed\n", ioc->name);
+        goto out;
+    }
+    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
+        "config page(0x%p): size(%d)\n",
+        ioc->name, ioc->config_page, ioc->config_page_sz));
+    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma (0x%llx)\n",
+        ioc->name, (unsigned long long)ioc->config_page_dma));
+    total_sz += ioc->config_page_sz;
+
+    printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
+        ioc->name, total_sz/1024);
+    printk(MPT2SAS_INFO_FMT
+    "Current Controller Queue Depth(%d), Max Controller Queue Depth(%d)\n",
+     ioc->name, ioc->shost->can_queue, facts->RequestCredit);
+    printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
+        ioc->name, ioc->shost->sg_tablesize);
+    return 0;

  out:
-    printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
-        "int_status(%x)!\n", ioc->name, __func__, count, int_status);
-    return -EFAULT;
+    return -ENOMEM;
 }

 /**
- * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
- * @ioc: per adapter object
+ * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @cooked: Request raw or cooked IOC state
+ *
+ * Returns all IOC Doorbell register bits if cooked==0, else just the
+ * Doorbell bits in MPI_IOC_STATE_MASK.
+ */
+u32
+mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
+{
+    u32 s, sc;
+
+    s = readl(&ioc->chip->Doorbell);
+    sc = s & MPI2_IOC_STATE_MASK;
+    return cooked ? sc : s;
+}
+
+/**
+ * _base_wait_on_iocstate - waiting on a particular ioc state
+ * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
  * @timeout: timeout in second
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
  *
  * Returns 0 for success, non-zero for failure.
- *
  */
 static int
-_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
+_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
     int sleep_flag)
 {
-    u32 cntdn, count;
-    u32 doorbell_reg;
+    u32 count, cntdn;
+    u32 current_state;

     count = 0;
     cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
     do {
-        doorbell_reg = readl(&ioc->chip->Doorbell);
-        if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
-            dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                "successful count(%d), timeout(%d)\n", ioc->name,
-                __func__, count, timeout));
+        current_state = mpt2sas_base_get_iocstate(ioc, 1);
+        if (current_state == ioc_state)
             return 0;
-        }
+        if (count && current_state == MPI2_IOC_STATE_FAULT)
+            break;
         if (sleep_flag == CAN_SLEEP)
             msleep(1);
         else
@@ -2986,9 +3234,7 @@ _base_wait_for_doorbell_not_used(struct
MPT2SAS_ADAPTER *ioc, int timeout,
         count++;
     } while (--cntdn);

-    printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
-        "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
-    return -EFAULT;
+    return current_state;
 }

 /**
@@ -3040,123 +3286,6 @@ _base_send_ioc_reset(struct MPT2SAS_ADAPTER
*ioc, u8 reset_type, int timeout,
 }

 /**
- * _base_handshake_req_reply_wait - send request thru doorbell interface
- * @ioc: per adapter object
- * @request_bytes: request length
- * @request: pointer having request payload
- * @reply_bytes: reply length
- * @reply: pointer to reply payload
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
-    u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
-{
-    MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
-    int i;
-    u8 failed;
-    u16 dummy;
-    __le32 *mfp;
-
-    /* make sure doorbell is not in use */
-    if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
-        printk(MPT2SAS_ERR_FMT "doorbell is in use "
-            " (line=%d)\n", ioc->name, __LINE__);
-        return -EFAULT;
-    }
-
-    /* clear pending doorbell interrupts from previous state changes */
-    if (readl(&ioc->chip->HostInterruptStatus) &
-        MPI2_HIS_IOC2SYS_DB_STATUS)
-        writel(0, &ioc->chip->HostInterruptStatus);
-
-    /* send message to ioc */
-    writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
-        ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
-        &ioc->chip->Doorbell);
-
-    if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
-        printk(MPT2SAS_ERR_FMT "doorbell handshake "
-           "int failed (line=%d)\n", ioc->name, __LINE__);
-        return -EFAULT;
-    }
-    writel(0, &ioc->chip->HostInterruptStatus);
-
-    if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
-        printk(MPT2SAS_ERR_FMT "doorbell handshake "
-            "ack failed (line=%d)\n", ioc->name, __LINE__);
-        return -EFAULT;
-    }
-
-    /* send message 32-bits at a time */
-    for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
-        writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
-        if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
-            failed = 1;
-    }
-
-    if (failed) {
-        printk(MPT2SAS_ERR_FMT "doorbell handshake "
-            "sending request failed (line=%d)\n", ioc->name, __LINE__);
-        return -EFAULT;
-    }
-
-    /* now wait for the reply */
-    if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
-        printk(MPT2SAS_ERR_FMT "doorbell handshake "
-           "int failed (line=%d)\n", ioc->name, __LINE__);
-        return -EFAULT;
-    }
-
-    /* read the first two 16-bits, it gives the total length of the reply */
-    reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
-        & MPI2_DOORBELL_DATA_MASK);
-    writel(0, &ioc->chip->HostInterruptStatus);
-    if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
-        printk(MPT2SAS_ERR_FMT "doorbell handshake "
-           "int failed (line=%d)\n", ioc->name, __LINE__);
-        return -EFAULT;
-    }
-    reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
-        & MPI2_DOORBELL_DATA_MASK);
-    writel(0, &ioc->chip->HostInterruptStatus);
-
-    for (i = 2; i < default_reply->MsgLength * 2; i++)  {
-        if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
-            printk(MPT2SAS_ERR_FMT "doorbell "
-                "handshake int failed (line=%d)\n", ioc->name,
-                __LINE__);
-            return -EFAULT;
-        }
-        if (i >=  reply_bytes/2) /* overflow case */
-            dummy = readl(&ioc->chip->Doorbell);
-        else
-            reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
-                & MPI2_DOORBELL_DATA_MASK);
-        writel(0, &ioc->chip->HostInterruptStatus);
-    }
-
-    _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
-    if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
-        dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
-            " (line=%d)\n", ioc->name, __LINE__));
-    }
-    writel(0, &ioc->chip->HostInterruptStatus);
-
-    if (ioc->logging_level & MPT_DEBUG_INIT) {
-        mfp = (__le32 *)reply;
-        printk(KERN_INFO "\toffset:data\n");
-        for (i = 0; i < reply_bytes/4; i++)
-            printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
-                le32_to_cpu(mfp[i]));
-    }
-    return 0;
-}
-
-/**
  * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
  * @ioc: per adapter object
  * @mpi_reply: the reply payload from FW
@@ -3406,78 +3535,6 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER
*ioc, int port, int sleep_flag)
 }

 /**
- * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
-    Mpi2IOCFactsRequest_t mpi_request;
-    Mpi2IOCFactsReply_t mpi_reply;
-    struct mpt2sas_facts *facts;
-    int mpi_reply_sz, mpi_request_sz, r;
-
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-        __func__));
-
-    mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
-    mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
-    memset(&mpi_request, 0, mpi_request_sz);
-    mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
-    r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
-        (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
-
-    if (r != 0) {
-        printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
-            ioc->name, __func__, r);
-        return r;
-    }
-
-    facts = &ioc->facts;
-    memset(facts, 0, sizeof(struct mpt2sas_facts));
-    facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
-    facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
-    facts->VP_ID = mpi_reply.VP_ID;
-    facts->VF_ID = mpi_reply.VF_ID;
-    facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
-    facts->MaxChainDepth = mpi_reply.MaxChainDepth;
-    facts->WhoInit = mpi_reply.WhoInit;
-    facts->NumberOfPorts = mpi_reply.NumberOfPorts;
-    facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
-    facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
-    facts->MaxReplyDescriptorPostQueueDepth =
-        le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
-    facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
-    facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
-    if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
-        ioc->ir_firmware = 1;
-    facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
-    facts->IOCRequestFrameSize =
-        le16_to_cpu(mpi_reply.IOCRequestFrameSize);
-    facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
-    facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
-    ioc->shost->max_id = -1;
-    facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
-    facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
-    facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
-    facts->HighPriorityCredit =
-        le16_to_cpu(mpi_reply.HighPriorityCredit);
-    facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
-    facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
-
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
-        "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
-        facts->MaxChainDepth));
-    dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
-        "reply frame size(%d)\n", ioc->name,
-        facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
-    return 0;
-}
-
-/**
  * _base_send_ioc_init - send ioc_init to firmware
  * @ioc: per adapter object
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
@@ -3489,9 +3546,12 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER
*ioc, int sleep_flag)
 {
     Mpi2IOCInitRequest_t mpi_request;
     Mpi2IOCInitReply_t mpi_reply;
-    int r;
+    int i, r = 0;
     struct timeval current_time;
     u16 ioc_status;
+    u32 reply_post_free_array_sz = 0;
+    Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL;
+    dma_addr_t reply_post_free_array_dma;

     dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
         __func__));
@@ -3520,9 +3580,30 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER
*ioc, int sleep_flag)
         cpu_to_le64((u64)ioc->request_dma);
     mpi_request.ReplyFreeQueueAddress =
         cpu_to_le64((u64)ioc->reply_free_dma);
-    mpi_request.ReplyDescriptorPostQueueAddress =
-        cpu_to_le64((u64)ioc->reply_post_free_dma);
-
+    if (ioc->rdpq_array_enable) {
+        reply_post_free_array_sz = ioc->reply_queue_count *
+            sizeof(Mpi2IOCInitRDPQArrayEntry);
+        reply_post_free_array = pci_alloc_consistent(ioc->pdev,
+            reply_post_free_array_sz, &reply_post_free_array_dma);
+        if (!reply_post_free_array) {
+            printk(MPT2SAS_ERR_FMT
+            "reply_post_free_array: pci_alloc_consistent failed\n",
+            ioc->name);
+            r = -ENOMEM;
+            goto out;
+        }
+        memset(reply_post_free_array, 0, reply_post_free_array_sz);
+        for (i = 0; i < ioc->reply_queue_count; i++)
+            reply_post_free_array[i].RDPQBaseAddress =
+                cpu_to_le64(
+                (u64)ioc->reply_post[i].reply_post_free_dma);
+        mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE;
+        mpi_request.ReplyDescriptorPostQueueAddress =
+            cpu_to_le64((u64)reply_post_free_array_dma);
+    } else {
+        mpi_request.ReplyDescriptorPostQueueAddress =
+            cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma);
+    }

     /* This time stamp specifies number of milliseconds
      * since epoch ~ midnight January 1, 1970.
@@ -3550,7 +3631,7 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc,
int sleep_flag)
     if (r != 0) {
         printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
             ioc->name, __func__, r);
-        return r;
+        goto out;
     }

     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
@@ -3560,7 +3641,12 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER
*ioc, int sleep_flag)
         r = -EIO;
     }

-    return 0;
+ out:
+    if (reply_post_free_array)
+        pci_free_consistent(ioc->pdev, reply_post_free_array_sz,
+                    reply_post_free_array,
+                    reply_post_free_array_dma);
+    return r;
 }

 /**
@@ -4093,7 +4179,7 @@ _base_make_ioc_operational(struct
MPT2SAS_ADAPTER *ioc, int sleep_flag)
     u8 hide_flag;
     struct adapter_reply_queue *reply_q;
     long reply_post_free;
-    u32 reply_post_free_sz;
+    unsigned int reply_post_free_sz, index = 0;

     dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
         __func__));
@@ -4164,19 +4250,28 @@ _base_make_ioc_operational(struct
MPT2SAS_ADAPTER *ioc, int sleep_flag)
         _base_assign_reply_queues(ioc);

     /* initialize Reply Post Free Queue */
-    reply_post_free = (long)ioc->reply_post_free;
     reply_post_free_sz = ioc->reply_post_queue_depth *
-        sizeof(Mpi2DefaultReplyDescriptor_t);
+                sizeof(Mpi2DefaultReplyDescriptor_t);
+    reply_post_free = (long)ioc->reply_post[index].reply_post_free;
     list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
         reply_q->reply_post_host_index = 0;
-        reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
-            reply_post_free;
+        reply_q->reply_post_free =
+             (Mpi2ReplyDescriptorsUnion_t *) reply_post_free;
         for (i = 0; i < ioc->reply_post_queue_depth; i++)
             reply_q->reply_post_free[i].Words =
-                            cpu_to_le64(ULLONG_MAX);
+                        cpu_to_le64(ULLONG_MAX);
+
         if (!_base_is_controller_msix_enabled(ioc))
             goto skip_init_reply_post_free_queue;
-        reply_post_free += reply_post_free_sz;
+        /*
+         * If RDPQ is enabled, switch to the next allocation.
+         * Otherwise advance within the contiguous region.
+         */
+        if (ioc->rdpq_array_enable)
+            reply_post_free = (long)
+                ioc->reply_post[++index].reply_post_free;
+        else
+            reply_post_free += reply_post_free_sz;
     }
  skip_init_reply_post_free_queue:

@@ -4304,6 +4399,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
         }
     }

+    ioc->rdpq_array_enable_assigned = 0;
     r = mpt2sas_base_map_resources(ioc);
     if (r)
         goto out_free_resources;
@@ -4664,6 +4760,16 @@ mpt2sas_base_hard_reset_handler(struct
MPT2SAS_ADAPTER *ioc, int sleep_flag,
         r = -EFAULT;
         goto out;
     }
+
+    r = _base_get_ioc_facts(ioc, CAN_SLEEP);
+    if (r)
+        goto out;
+
+    if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable)
+        panic("%s: Issue occurred with flashing controller firmware."
+              "Please reboot the system and ensure that the correct"
+              "firmware version is running\n", ioc->name);
+
     r = _base_make_ioc_operational(ioc, sleep_flag);
     if (!r)
         _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h
b/drivers/scsi/mpt2sas/mpt2sas_base.h
index be2ae90..ec15e0e 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -636,6 +636,11 @@ struct mpt2sas_port_facts {
     u16            MaxPostedCmdBuffers;
 };

+struct reply_post_struct {
+    Mpi2ReplyDescriptorsUnion_t    *reply_post_free;
+    dma_addr_t            reply_post_free_dma;
+};
+
 /**
  * enum mutex_type - task management mutex type
  * @TM_MUTEX_OFF: mutex is not required becuase calling function is
acquiring it
@@ -779,8 +784,11 @@ typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct
MPT2SAS_ADAPTER *ioc);
  * @reply_free_dma_pool:
  * @reply_free_host_index: tail index in pool to insert free replys
  * @reply_post_queue_depth: reply post queue depth
- * @reply_post_free: pool for reply post (64bit descriptor)
- * @reply_post_free_dma:
+ * @reply_post_struct: struct for reply_post_free physical & virt address
+ * @rdpq_array_capable: FW supports multiple reply queue addresses in ioc_init
+ * @rdpq_array_enable: rdpq_array support is enabled in the driver
+ * @rdpq_array_enable_assigned: this ensures that rdpq_array_enable flag
+ *                is assigned only ones
  * @reply_queue_count: number of reply queue's
  * @reply_queue_list: link list contaning the reply queue info
  * @reply_post_host_index: head index in the pool where FW completes IO
@@ -972,11 +980,13 @@ struct MPT2SAS_ADAPTER {

     /* reply post queue */
     u16         reply_post_queue_depth;
-    Mpi2ReplyDescriptorsUnion_t *reply_post_free;
-    dma_addr_t    reply_post_free_dma;
+    struct reply_post_struct *reply_post;
     struct dma_pool *reply_post_free_dma_pool;
     u8        reply_queue_count;
     struct list_head reply_queue_list;
+    u8              rdpq_array_capable;
+    u8              rdpq_array_enable;
+    u8              rdpq_array_enable_assigned;

     struct list_head delayed_tr_list;
     struct list_head delayed_tr_volume_list;

On Thu, Jul 24, 2014 at 1:16 AM, Martin K. Petersen
<martin.petersen@...cle.com> wrote:
>>>>>> "Sreekanth" == Sreekanth Reddy <sreekanth.reddy@...gotech.com> writes:
>
> Sreekanth,
>
> Sreekanth> 2. As per MPI Spec, each set of 8 reply descriptor post
> Sreekanth> queues must have the same value for the upper 32-bits of
> Sreekanth> their memory address. So allocated set of eight queues in a
> Sreekanth> single pool and added a new function is_MSB_are_same() to
> Sreekanth> check whether higher 32 bits of this pool memory address are
> Sreekanth> same or not. If this functions returns zero then we are
> Sreekanth> saving these pools in the bad_reply_post_pool list. then
> Sreekanth> releasing these pools once we get the required memory pools.
>
> Why don't you just set pci_set_consistent_dma_mask() to DMA_BIT_MASK(32)
> before you allocate the queue entries?
>
> --
> Martin K. Petersen      Oracle Linux Engineering
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ