diff options
author | James Smart <jsmart2021@gmail.com> | 2017-11-21 03:00:29 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-12-05 04:32:53 +0300 |
commit | 81b96eda5ff8077873072facd20b9d85a80c61bd (patch) | |
tree | 3e08e45371e2cc28910eb6693d422f7c381a119e /drivers/scsi/lpfc/lpfc_sli.c | |
parent | c73455e1b5ef165aed82e36ae04e74a71d2d7d5b (diff) | |
download | linux-81b96eda5ff8077873072facd20b9d85a80c61bd.tar.xz |
scsi: lpfc: Expand WQE capability of every NVME hardware queue
Hardware queues are a fast staging area to push commands into the
adapter. The adapter should drain them extremely quickly. However,
under heavy io load, the host cpu is pushing commands faster than the
drain rate of the adapter causing the driver to resource busy commands.
Enlarge the hardware queue (wq & cq) to support a larger number of queue
entries (4x the prior size) before backpressure. Enlarging the queue
requires larger contiguous buffers (16k) per logical page for the
hardware. This changed calling sequences that were expecting 4K page
sizes that now must pass a parameter with the page sizes. It also
required use of a new version of an adapter command that can vary the
page size values.
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index aecd2399005d..ddc234284980 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -13919,7 +13919,7 @@ lpfc_sli4_queue_free(struct lpfc_queue *queue) while (!list_empty(&queue->page_list)) { list_remove_head(&queue->page_list, dmabuf, struct lpfc_dmabuf, list); - dma_free_coherent(&queue->phba->pcidev->dev, SLI4_PAGE_SIZE, + dma_free_coherent(&queue->phba->pcidev->dev, queue->page_size, dmabuf->virt, dmabuf->phys); kfree(dmabuf); } @@ -13938,6 +13938,7 @@ lpfc_sli4_queue_free(struct lpfc_queue *queue) /** * lpfc_sli4_queue_alloc - Allocate and initialize a queue structure * @phba: The HBA that this queue is being created on. + * @page_size: The size of a queue page * @entry_size: The size of each queue entry for this queue. * @entry count: The number of entries that this queue will handle. * @@ -13946,8 +13947,8 @@ lpfc_sli4_queue_free(struct lpfc_queue *queue) * queue on the HBA. **/ struct lpfc_queue * -lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, - uint32_t entry_count) +lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size, + uint32_t entry_size, uint32_t entry_count) { struct lpfc_queue *queue; struct lpfc_dmabuf *dmabuf; @@ -13956,7 +13957,7 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; if (!phba->sli4_hba.pc_sli4_params.supported) - hw_page_size = SLI4_PAGE_SIZE; + hw_page_size = page_size; queue = kzalloc(sizeof(struct lpfc_queue) + (sizeof(union sli4_qe) * entry_count), GFP_KERNEL); @@ -13973,6 +13974,15 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, INIT_LIST_HEAD(&queue->wq_list); INIT_LIST_HEAD(&queue->page_list); INIT_LIST_HEAD(&queue->child_list); + + /* Set queue parameters now. If the system cannot provide memory + * resources, the free routine needs to know what was allocated. + */ + queue->entry_size = entry_size; + queue->entry_count = entry_count; + queue->page_size = hw_page_size; + queue->phba = phba; + for (x = 0, total_qe_count = 0; x < queue->page_count; x++) { dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (!dmabuf) @@ -13994,9 +14004,6 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, queue->qe[total_qe_count].address = dma_pointer; } } - queue->entry_size = entry_size; - queue->entry_count = entry_count; - queue->phba = phba; INIT_WORK(&queue->irqwork, lpfc_sli4_hba_process_cq); INIT_WORK(&queue->spwork, lpfc_sli4_sp_process_cq); @@ -14299,7 +14306,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, if (!cq || !eq) return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) - hw_page_size = SLI4_PAGE_SIZE; + hw_page_size = cq->page_size; mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) @@ -14318,8 +14325,8 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, bf_set(lpfc_mbox_hdr_version, &shdr->request, phba->sli4_hba.pc_sli4_params.cqv); if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) { - /* FW only supports 1. Should be PAGE_SIZE/SLI4_PAGE_SIZE */ - bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request, 1); + bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request, + (cq->page_size / SLI4_PAGE_SIZE)); bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context, eq->queue_id); } else { @@ -14327,6 +14334,18 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, eq->queue_id); } switch (cq->entry_count) { + case 2048: + case 4096: + if (phba->sli4_hba.pc_sli4_params.cqv == + LPFC_Q_CREATE_VERSION_2) { + cq_create->u.request.context.lpfc_cq_context_count = + cq->entry_count; + bf_set(lpfc_cq_context_count, + &cq_create->u.request.context, + LPFC_CQ_CNT_WORD7); + break; + } + /* Fall Thru */ default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0361 Unsupported CQ count: " @@ -14352,7 +14371,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, break; } list_for_each_entry(dmabuf, &cq->page_list, list) { - memset(dmabuf->virt, 0, hw_page_size); + memset(dmabuf->virt, 0, cq->page_size); cq_create->u.request.page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys); cq_create->u.request.page[dmabuf->buffer_tag].addr_hi = @@ -14433,8 +14452,6 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, numcq = phba->cfg_nvmet_mrq; if (!cqp || !eqp || !numcq) return -ENODEV; - if (!phba->sli4_hba.pc_sli4_params.supported) - hw_page_size = SLI4_PAGE_SIZE; mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) @@ -14465,6 +14482,8 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, status = -ENOMEM; goto out; } + if (!phba->sli4_hba.pc_sli4_params.supported) + hw_page_size = cq->page_size; switch (idx) { case 0: @@ -14482,6 +14501,19 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, bf_set(lpfc_mbx_cq_create_set_num_cq, &cq_set->u.request, numcq); switch (cq->entry_count) { + case 2048: + case 4096: + if (phba->sli4_hba.pc_sli4_params.cqv == + LPFC_Q_CREATE_VERSION_2) { + bf_set(lpfc_mbx_cq_create_set_cqe_cnt, + &cq_set->u.request, + cq->entry_count); + bf_set(lpfc_mbx_cq_create_set_cqe_cnt, + &cq_set->u.request, + LPFC_CQ_CNT_WORD7); + break; + } + /* Fall Thru */ default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "3118 Bad CQ count. (%d)\n", @@ -14578,6 +14610,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, cq->host_index = 0; cq->hba_index = 0; cq->entry_repost = LPFC_CQ_REPOST; + cq->chann = idx; rc = 0; list_for_each_entry(dmabuf, &cq->page_list, list) { @@ -14872,12 +14905,13 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, void __iomem *bar_memmap_p; uint32_t db_offset; uint16_t pci_barset; + uint8_t wq_create_version; /* sanity check on queue memory */ if (!wq || !cq) return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) - hw_page_size = SLI4_PAGE_SIZE; + hw_page_size = wq->page_size; mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) @@ -14898,7 +14932,12 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, bf_set(lpfc_mbox_hdr_version, &shdr->request, phba->sli4_hba.pc_sli4_params.wqv); - switch (phba->sli4_hba.pc_sli4_params.wqv) { + if (phba->sli4_hba.pc_sli4_params.wqsize & LPFC_WQ_SZ128_SUPPORT) + wq_create_version = LPFC_Q_CREATE_VERSION_1; + else + wq_create_version = LPFC_Q_CREATE_VERSION_0; + + switch (wq_create_version) { case LPFC_Q_CREATE_VERSION_0: switch (wq->entry_size) { default: @@ -14956,7 +14995,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, } bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1, - LPFC_WQ_PAGE_SIZE_4096); + (wq->page_size / SLI4_PAGE_SIZE)); page = wq_create->u.request_1.page; break; default: |