|
@@ -92,6 +92,9 @@ static int disable_discovery = -1;
|
|
|
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.
|
|
|
*
|
|
@@ -1179,17 +1182,22 @@ static int
|
|
|
_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;
|
|
|
}
|
|
|
}
|
|
@@ -1198,18 +1206,29 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
|
|
|
&& !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
|
|
@@ -1406,11 +1425,15 @@ _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);
|
|
|
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",
|
|
@@ -1453,6 +1476,7 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
|
|
|
/* failback to io_apic interrupt routing */
|
|
|
try_ioapic:
|
|
|
|
|
|
+ ioc->reply_queue_count = 1;
|
|
|
r = _base_request_irq(ioc, 0, ioc->pdev->irq);
|
|
|
|
|
|
return r;
|
|
@@ -1534,6 +1558,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;
|
|
@@ -2331,7 +2365,8 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
|
|
|
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__));
|
|
@@ -2372,15 +2407,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 {
|
|
|
+ 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) {
|
|
@@ -2523,6 +2568,65 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
|
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;
|
|
|
|
|
@@ -2734,37 +2838,6 @@ 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
|
|
|
- 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);
|
|
@@ -3436,6 +3509,9 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
|
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);
|
|
@@ -3471,9 +3547,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__));
|
|
@@ -3502,9 +3581,31 @@ _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.
|
|
@@ -3532,7 +3633,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;
|
|
@@ -3542,7 +3643,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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -4075,7 +4181,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;
|
|
|
+ u32 reply_post_free_sz, index = 0;
|
|
|
|
|
|
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
|
|
__func__));
|
|
@@ -4146,19 +4252,27 @@ _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);
|
|
|
+ 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:
|
|
|
|
|
@@ -4286,6 +4400,8 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ ioc->rdpq_array_enable_assigned = 0;
|
|
|
+ ioc->dma_mask = 0;
|
|
|
r = mpt2sas_base_map_resources(ioc);
|
|
|
if (r)
|
|
|
goto out_free_resources;
|
|
@@ -4647,6 +4763,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);
|