module_param(disable_discovery, int, 0);
 MODULE_PARM_DESC(disable_discovery, " disable discovery ");
 
+static int
+_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
+
 /**
  * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
  *
 _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
 {
        struct sysinfo s;
-       char *desc = NULL;
+       u64 consistent_dma_mask;
+
+       if (ioc->dma_mask)
+               consistent_dma_mask = DMA_BIT_MASK(64);
+       else
+               consistent_dma_mask = DMA_BIT_MASK(32);
 
        if (sizeof(dma_addr_t) > 4) {
                const uint64_t required_mask =
                    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))) {
+               if ((required_mask > DMA_BIT_MASK(32)) &&
+                   !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
+                   !pci_set_consistent_dma_mask(pdev, consistent_dma_mask)) {
                        ioc->base_add_sg_single = &_base_add_sg_single_64;
                        ioc->sge_size = sizeof(Mpi2SGESimple64_t);
-                       desc = "64";
+                       ioc->dma_mask = 64;
                        goto out;
                }
        }
            && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
                ioc->base_add_sg_single = &_base_add_sg_single_32;
                ioc->sge_size = sizeof(Mpi2SGESimple32_t);
-               desc = "32";
+               ioc->dma_mask = 32;
        } else
                return -ENODEV;
 
  out:
        si_meminfo(&s);
-       printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
-           "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));
+       printk(MPT2SAS_INFO_FMT
+           "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n",
+           ioc->name, ioc->dma_mask, convert_to_kb(s.totalram));
 
        return 0;
 }
 
+static int
+_base_change_consistent_dma_mask(struct MPT2SAS_ADAPTER *ioc,
+                                 struct pci_dev *pdev)
+{
+       if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
+                       return -ENODEV;
+       }
+       return 0;
+}
 /**
  * _base_check_enable_msix - checks MSIX capabable.
  * @ioc: per adapter object
        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);
                ioc->msix_vector_count = ioc->reply_queue_count;
-       }
+       } else if (max_msix_vectors == 0)
+               goto try_ioapic;
 
        printk(MPT2SAS_INFO_FMT
        "MSI-X vectors supported: %d, no of cores: %d, max_msix_vectors: %d\n",
 /* failback to io_apic interrupt routing */
  try_ioapic:
 
+       ioc->reply_queue_count = 1;
        r = _base_request_irq(ioc, 0, ioc->pdev->irq);
 
        return r;
        }
 
        _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;
 static void
 _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
 {
-       int i;
+       int i = 0;
+       struct reply_post_struct *rps;
 
        dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
                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 {
+                       rps = &ioc->reply_post[i];
+                       if (rps->reply_post_free) {
+                               pci_pool_free(
+                                   ioc->reply_post_free_dma_pool,
+                                   rps->reply_post_free,
+                                   rps->reply_post_free_dma);
+                               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
+                                   "reply_post_free_pool(0x%p): free\n",
+                                   ioc->name, rps->reply_post_free));
+                               rps->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) {
            ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
            ioc->chains_needed_per_io));
 
+       /* reply post queue, 16 byte align */
+       reply_post_free_sz = ioc->reply_post_queue_depth *
+           sizeof(Mpi2DefaultReplyDescriptor_t);
+
+       sz = reply_post_free_sz;
+       if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable)
+               sz *= ioc->reply_queue_count;
+
+       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;
+       }
+       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;
+       }
+       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 (ioc->dma_mask == 64) {
+               if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
+                       printk(MPT2SAS_WARN_FMT
+                           "no suitable consistent DMA mask for %s\n",
+                           ioc->name, pci_name(ioc->pdev));
+                       goto out;
+               }
+       }
+
        ioc->scsiio_depth = ioc->hba_queue_depth -
            ioc->hi_priority_depth - ioc->internal_depth;
 
            "(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
-               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;
-       }
-       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);
-               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);
        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);
 {
        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__));
            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.
        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;
                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;
 }
 
 /**
        u8 hide_flag;
        struct adapter_reply_queue *reply_q;
        long reply_post_free;
-       u32 reply_post_free_sz;
+       u32 reply_post_free_sz, index = 0;
 
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
                _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);
+       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;
                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:
 
                }
        }
 
+       ioc->rdpq_array_enable_assigned = 0;
+       ioc->dma_mask = 0;
        r = mpt2sas_base_map_resources(ioc);
        if (r)
                goto out_free_resources;
                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);