On 08/05/2014 06:41 PM, Sreekanth Reddy wrote: > Hi Tomas, > > Can you please review this updated patch,
Hi Sreekanth, the patch is mangled so a resend is needed anyway and I think you will probably also want implement the changes you were asked for in the mpt2sas sibling of this patch. Thanks, Tomas > > Up to now, Driver allocates a single contiguous block of memory > pool for all reply queues and passes down a single address in the > ReplyDescriptorPostQueueAddress field of the IOC Init Request > Message to the firmware. > > When firmware receives this address, it will program each of the > Reply Descriptor Post Queue registers, as each reply queue has its > own register. Thus the firmware, starting from a base address it > determines the starting address of the subsequent reply queues > through some simple arithmetic calculations. > > The size of this contiguous block of memory pool is directly proportional > to number of MSI-X vectors and the HBA queue depth. For example higher > MSIX vectors requires larger contiguous block of memory pool. > > But some of the OS kernels are unable to allocate this larger > contiguous block of memory pool. > > So, the proposal is to allocate memory independently for each > Reply Queue and pass down all of the addresses to the firmware. > Then the firmware will just take each address and program the value > into the correct register. > > When HBAs with older firmware(i.e. without RDPQ capability) is used > with this new driver then the max_msix_vectors value would be set > to 8 by default. > > Change set in v2: > > 1. Declared the following functions at the beginning of the mpt3sas_base.c > file instead of moving all these functions before > mpt3sas_base_map_resources() function > a. _base_wait_for_doorbell_int() > b. _base_wait_for_doorbell_ack() > c. _base_wait_for_doorbell_not_used() > d. _base_handshake_req_reply_wait() > e. _base_get_ioc_facts() > > 2. Initially set the consistent DMA mask to 32 bit and then change it to 64 > bit mask after allocating RDPQ pools by calling the function > _base_change_consistent_dma_mask. This is to ensure that all the upper 32 > bits of RDPQ entries's base address to be same. > > 3. Reduced the redundancy between the RDPQ and non-RDPQ support in these > following functions > a. _base_release_memory_pools() > b. _base_allocate_memory_pools() > c. _base_send_ioc_init() > d. _base_make_ioc_operational() > > Signed-off-by: Sreekanth Reddy <sreekanth.re...@avagotech.com> > --- > drivers/scsi/mpt3sas/mpt3sas_base.c | 246 > ++++++++++++++++++++++++++++-------- > drivers/scsi/mpt3sas/mpt3sas_base.h | 18 ++- > 2 files changed, 204 insertions(+), 60 deletions(-) > > diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c > b/drivers/scsi/mpt3sas/mpt3sas_base.c > index 153b2c1..20c2c7b 100644 > --- a/drivers/scsi/mpt3sas/mpt3sas_base.c > +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c > @@ -92,6 +92,22 @@ MODULE_PARM_DESC(mpt3sas_fwfault_debug, > " enable detection of firmware fault and halt firmware - (default=0)"); > > > +static int dma_mask; > + > +static int > +_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, > + int sleep_flag); > +static int > +_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, > + int sleep_flag); > +static int > +_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, > + int sleep_flag); > +static int > +_base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int > request_bytes, > + u32 *request, int reply_bytes, u16 *reply, int timeout, int > sleep_flag); > +static int > +_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); > /** > * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. > * > @@ -1482,17 +1498,23 @@ static int > _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev > *pdev) > { > struct sysinfo s; > - char *desc = NULL; > + u64 consistent_dma_mask; > + > + if (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))) { > + !pci_set_consistent_dma_mask(pdev, > + DMA_BIT_MASK(consistent_dma_mask))) { > ioc->base_add_sg_single = &_base_add_sg_single_64; > ioc->sge_size = sizeof(Mpi2SGESimple64_t); > - desc = "64"; > + dma_mask = 64; > goto out; > } > } > @@ -1501,19 +1523,30 @@ _base_config_dma_addressing(struct MPT3SAS_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"; > + dma_mask = 32; > } else > return -ENODEV; > > out: > si_meminfo(&s); > pr_info(MPT3SAS_FMT > - "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", > - ioc->name, desc, convert_to_kb(s.totalram)); > + "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", > + ioc->name, dma_mask, convert_to_kb(s.totalram)); > > return 0; > } > > +static int > +_base_change_consistent_dma_mask(struct MPT3SAS_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 > @@ -1729,6 +1762,9 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) > ": %d, max_msix_vectors: %d\n", ioc->name, ioc->msix_vector_count, > ioc->cpu_count, max_msix_vectors); > > + 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); > @@ -1852,6 +1888,16 @@ mpt3sas_base_map_resources(struct MPT3SAS_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; > @@ -2527,7 +2573,8 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) > static void > _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) > { > - int i; > + int i = 0; > + struct reply_post_struct *rps; > > dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, > __func__)); > @@ -2572,15 +2619,25 @@ _base_release_memory_pools(struct MPT3SAS_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, pr_info(MPT3SAS_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, pr_info(MPT3SAS_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) { > @@ -2727,6 +2784,69 @@ _base_allocate_memory_pools(struct MPT3SAS_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); > + if (ioc->rdpq_array_enable) > + sz = reply_post_free_sz; > + 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 = kcalloc((ioc->rdpq_array_enable) ? > + (ioc->reply_queue_count):1, > + sizeof(struct reply_post_struct), GFP_KERNEL); > + > + if (!ioc->reply_post) { > + pr_err(MPT3SAS_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) { > + pr_err(MPT3SAS_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) { > + pr_err(MPT3SAS_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, pr_info(MPT3SAS_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, pr_info(MPT3SAS_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 (dma_mask == 64) { > + if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) { > + pr_warn(MPT3SAS_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; > > @@ -2941,40 +3061,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER > *ioc, int sleep_flag) > 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) { > - pr_err(MPT3SAS_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) { > - pr_err(MPT3SAS_FMT > - "reply_post_free pool: pci_pool_alloc failed\n", > - ioc->name); > - goto out; > - } > - memset(ioc->reply_post_free, 0, sz); > - dinitprintk(ioc, pr_info(MPT3SAS_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, pr_info(MPT3SAS_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); > @@ -3657,6 +3743,9 @@ _base_get_ioc_facts(struct MPT3SAS_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); > @@ -3693,9 +3782,12 @@ _base_send_ioc_init(struct MPT3SAS_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, pr_info(MPT3SAS_FMT "%s\n", ioc->name, > __func__)); > @@ -3724,9 +3816,31 @@ _base_send_ioc_init(struct MPT3SAS_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) { > + pr_err(MPT3SAS_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. > @@ -3754,7 +3868,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int > sleep_flag) > if (r != 0) { > pr_err(MPT3SAS_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; > @@ -3764,7 +3878,12 @@ _base_send_ioc_init(struct MPT3SAS_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; > } > > /** > @@ -4314,7 +4433,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER > *ioc, int sleep_flag) > struct _tr_list *delayed_tr, *delayed_tr_next; > struct adapter_reply_queue *reply_q; > long reply_post_free; > - u32 reply_post_free_sz; > + u32 reply_post_free_sz, index = 0; > > dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, > __func__)); > @@ -4385,9 +4504,9 @@ _base_make_ioc_operational(struct MPT3SAS_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 *) > @@ -4397,7 +4516,15 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER > *ioc, int sleep_flag) > 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: > > @@ -4508,6 +4635,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) > goto out_free_resources; > } > > + ioc->rdpq_array_enable_assigned = 0; > r = mpt3sas_base_map_resources(ioc); > if (r) > goto out_free_resources; > @@ -4884,6 +5012,12 @@ mpt3sas_base_hard_reset_handler(struct > MPT3SAS_ADAPTER *ioc, int sleep_flag, > 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, MPT3_IOC_DONE_RESET); > diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h > b/drivers/scsi/mpt3sas/mpt3sas_base.h > index ae97f46..fd5d505 100644 > --- a/drivers/scsi/mpt3sas/mpt3sas_base.h > +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h > @@ -569,6 +569,11 @@ struct mpt3sas_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 > @@ -712,8 +717,11 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct > MPT3SAS_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 > @@ -914,8 +922,10 @@ struct MPT3SAS_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; > + u8 rdpq_array_capable; > + u8 rdpq_array_enable; > + u8 rdpq_array_enable_assigned; > struct dma_pool *reply_post_free_dma_pool; > u8 reply_queue_count; > struct list_head reply_queue_list; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html