summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_debugfs.c
diff options
context:
space:
mode:
authorJames Smart2017-02-12 22:52:30 +0100
committerMartin K. Petersen2017-02-23 00:41:43 +0100
commit895427bd012ce5814fc9888c7c0ee9de44761833 (patch)
tree307a6d5500f676e5df31b8120a3c5986d0636eba /drivers/scsi/lpfc/lpfc_debugfs.c
parentscsi: lpfc: refactor debugfs queue dump routines (diff)
downloadkernel-qcow2-linux-895427bd012ce5814fc9888c7c0ee9de44761833.tar.gz
kernel-qcow2-linux-895427bd012ce5814fc9888c7c0ee9de44761833.tar.xz
kernel-qcow2-linux-895427bd012ce5814fc9888c7c0ee9de44761833.zip
scsi: lpfc: NVME Initiator: Base modifications
NVME Initiator: Base modifications This patch adds base modifications for NVME initiator support. The base modifications consist of: - Formal split of SLI3 rings from SLI-4 WQs (sometimes referred to as rings as well) as implementation now widely varies between the two. - Addition of configuration modes: SCSI initiator only; NVME initiator only; NVME target only; and SCSI and NVME initiator. The configuration mode drives overall adapter configuration, offloads enabled, and resource splits. NVME support is only available on SLI-4 devices and newer fw. - Implements the following based on configuration mode: - Exchange resources are split by protocol; Obviously, if only 1 mode, then no split occurs. Default is 50/50. module attribute allows tuning. - Pools and config parameters are separated per-protocol - Each protocol has it's own set of queues, but share interrupt vectors. SCSI: SLI3 devices have few queues and the original style of queue allocation remains. SLI4 devices piggy back on an "io-channel" concept that eventually needs to merge with scsi-mq/blk-mq support (it is underway). For now, the paradigm continues as it existed prior. io channel allocates N msix and N WQs (N=4 default) and either round robins or uses cpu # modulo N for scheduling. A bunch of module parameters allow the configuration to be tuned. NVME (initiator): Allocates an msix per cpu (or whatever pci_alloc_irq_vectors gets) Allocates a WQ per cpu, and maps the WQs to msix on a WQ # modulo msix vector count basis. Module parameters exist to cap/control the config if desired. - Each protocol has its own buffer and dma pools. I apologize for the size of the patch. 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_debugfs.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c178
1 files changed, 131 insertions, 47 deletions
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 93ddda16c632..d9bbebe8eb37 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -484,20 +484,23 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
off += (8 * sizeof(uint32_t));
}
- for (i = 0; i < 4; i++) {
- pgpp = &phba->port_gp[i];
- pring = &psli->ring[i];
- len += snprintf(buf+len, size-len,
- "Ring %d: CMD GetInx:%d (Max:%d Next:%d "
- "Local:%d flg:x%x) RSP PutInx:%d Max:%d\n",
- i, pgpp->cmdGetInx, pring->sli.sli3.numCiocb,
- pring->sli.sli3.next_cmdidx,
- pring->sli.sli3.local_getidx,
- pring->flag, pgpp->rspPutInx,
- pring->sli.sli3.numRiocb);
- }
-
if (phba->sli_rev <= LPFC_SLI_REV3) {
+ for (i = 0; i < 4; i++) {
+ pgpp = &phba->port_gp[i];
+ pring = &psli->sli3_ring[i];
+ len += snprintf(buf+len, size-len,
+ "Ring %d: CMD GetInx:%d "
+ "(Max:%d Next:%d "
+ "Local:%d flg:x%x) "
+ "RSP PutInx:%d Max:%d\n",
+ i, pgpp->cmdGetInx,
+ pring->sli.sli3.numCiocb,
+ pring->sli.sli3.next_cmdidx,
+ pring->sli.sli3.local_getidx,
+ pring->flag, pgpp->rspPutInx,
+ pring->sli.sli3.numRiocb);
+ }
+
word0 = readl(phba->HAregaddr);
word1 = readl(phba->CAregaddr);
word2 = readl(phba->HSregaddr);
@@ -535,6 +538,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
+ len += snprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n");
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
if (!cnt) {
@@ -2011,6 +2015,14 @@ lpfc_idiag_wqs_for_cq(struct lpfc_hba *phba, char *wqtype, char *pbuffer,
if (*len >= max_cnt)
return 1;
}
+ for (qidx = 0; qidx < phba->cfg_nvme_io_channel; qidx++) {
+ qp = phba->sli4_hba.nvme_wq[qidx];
+ if (qp->assoc_qid != cq_id)
+ continue;
+ *len = __lpfc_idiag_print_wq(qp, wqtype, pbuffer, *len);
+ if (*len >= max_cnt)
+ return 1;
+ }
return 0;
}
@@ -2096,6 +2108,25 @@ lpfc_idiag_cqs_for_eq(struct lpfc_hba *phba, char *pbuffer,
return 1;
}
+ for (qidx = 0; qidx < phba->cfg_nvme_io_channel; qidx++) {
+ qp = phba->sli4_hba.nvme_cq[qidx];
+ if (qp->assoc_qid != eq_id)
+ continue;
+
+ *len = __lpfc_idiag_print_cq(qp, "NVME", pbuffer, *len);
+
+ /* Reset max counter */
+ qp->CQ_max_cqe = 0;
+
+ if (*len >= max_cnt)
+ return 1;
+
+ rc = lpfc_idiag_wqs_for_cq(phba, "NVME", pbuffer, len,
+ max_cnt, qp->queue_id);
+ if (rc)
+ return 1;
+ }
+
return 0;
}
@@ -2162,21 +2193,21 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
spin_lock_irq(&phba->hbalock);
/* Fast-path event queue */
- if (phba->sli4_hba.hba_eq && phba->cfg_fcp_io_channel) {
+ if (phba->sli4_hba.hba_eq && phba->io_channel_irqs) {
x = phba->lpfc_idiag_last_eq;
- if (phba->cfg_fof && (x >= phba->cfg_fcp_io_channel)) {
+ if (phba->cfg_fof && (x >= phba->io_channel_irqs)) {
phba->lpfc_idiag_last_eq = 0;
goto fof;
}
phba->lpfc_idiag_last_eq++;
- if (phba->lpfc_idiag_last_eq >= phba->cfg_fcp_io_channel)
+ if (phba->lpfc_idiag_last_eq >= phba->io_channel_irqs)
if (phba->cfg_fof == 0)
phba->lpfc_idiag_last_eq = 0;
len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
"EQ %d out of %d HBA EQs\n",
- x, phba->cfg_fcp_io_channel);
+ x, phba->io_channel_irqs);
/* Fast-path EQ */
qp = phba->sli4_hba.hba_eq[x];
@@ -2191,6 +2222,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
if (len >= max_cnt)
goto too_big;
+ /* will dump both fcp and nvme cqs/wqs for the eq */
rc = lpfc_idiag_cqs_for_eq(phba, pbuffer, &len,
max_cnt, qp->queue_id);
if (rc)
@@ -2227,6 +2259,23 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
if (len >= max_cnt)
goto too_big;
+ /* Slow-path NVME LS response CQ */
+ qp = phba->sli4_hba.nvmels_cq;
+ len = __lpfc_idiag_print_cq(qp, "NVME LS",
+ pbuffer, len);
+ /* Reset max counter */
+ if (qp)
+ qp->CQ_max_cqe = 0;
+ if (len >= max_cnt)
+ goto too_big;
+
+ /* Slow-path NVME LS WQ */
+ qp = phba->sli4_hba.nvmels_wq;
+ len = __lpfc_idiag_print_wq(qp, "NVME LS",
+ pbuffer, len);
+ if (len >= max_cnt)
+ goto too_big;
+
qp = phba->sli4_hba.hdr_rq;
len = __lpfc_idiag_print_rqpair(qp, phba->sli4_hba.dat_rq,
"RQpair", pbuffer, len);
@@ -2447,7 +2496,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
uint32_t qidx, quetp, queid, index, count, offset, value;
uint32_t *pentry;
- struct lpfc_queue *pque;
+ struct lpfc_queue *pque, *qp;
int rc;
/* This is a user write operation */
@@ -2483,19 +2532,15 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
case LPFC_IDIAG_EQ:
/* HBA event queue */
if (phba->sli4_hba.hba_eq) {
- for (qidx = 0; qidx < phba->cfg_fcp_io_channel;
- qidx++) {
- if (phba->sli4_hba.hba_eq[qidx] &&
- phba->sli4_hba.hba_eq[qidx]->queue_id ==
- queid) {
+ for (qidx = 0; qidx < phba->io_channel_irqs; qidx++) {
+ qp = phba->sli4_hba.hba_eq[qidx];
+ if (qp && qp->queue_id == queid) {
/* Sanity check */
- rc = lpfc_idiag_que_param_check(
- phba->sli4_hba.hba_eq[qidx],
+ rc = lpfc_idiag_que_param_check(qp,
index, count);
if (rc)
goto error_out;
- idiag.ptr_private =
- phba->sli4_hba.hba_eq[qidx];
+ idiag.ptr_private = qp;
goto pass_check;
}
}
@@ -2525,24 +2570,32 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
idiag.ptr_private = phba->sli4_hba.els_cq;
goto pass_check;
}
+ /* NVME LS complete queue */
+ if (phba->sli4_hba.nvmels_cq &&
+ phba->sli4_hba.nvmels_cq->queue_id == queid) {
+ /* Sanity check */
+ rc = lpfc_idiag_que_param_check(
+ phba->sli4_hba.nvmels_cq, index, count);
+ if (rc)
+ goto error_out;
+ idiag.ptr_private = phba->sli4_hba.nvmels_cq;
+ goto pass_check;
+ }
/* FCP complete queue */
if (phba->sli4_hba.fcp_cq) {
- qidx = 0;
- do {
- if (phba->sli4_hba.fcp_cq[qidx] &&
- phba->sli4_hba.fcp_cq[qidx]->queue_id ==
- queid) {
+ for (qidx = 0; qidx < phba->cfg_fcp_io_channel;
+ qidx++) {
+ qp = phba->sli4_hba.fcp_cq[qidx];
+ if (qp && qp->queue_id == queid) {
/* Sanity check */
rc = lpfc_idiag_que_param_check(
- phba->sli4_hba.fcp_cq[qidx],
- index, count);
+ qp, index, count);
if (rc)
goto error_out;
- idiag.ptr_private =
- phba->sli4_hba.fcp_cq[qidx];
+ idiag.ptr_private = qp;
goto pass_check;
}
- } while (++qidx < phba->cfg_fcp_io_channel);
+ }
}
goto error_out;
break;
@@ -2572,22 +2625,45 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
idiag.ptr_private = phba->sli4_hba.els_wq;
goto pass_check;
}
+ /* NVME LS work queue */
+ if (phba->sli4_hba.nvmels_wq &&
+ phba->sli4_hba.nvmels_wq->queue_id == queid) {
+ /* Sanity check */
+ rc = lpfc_idiag_que_param_check(
+ phba->sli4_hba.nvmels_wq, index, count);
+ if (rc)
+ goto error_out;
+ idiag.ptr_private = phba->sli4_hba.nvmels_wq;
+ goto pass_check;
+ }
/* FCP work queue */
if (phba->sli4_hba.fcp_wq) {
for (qidx = 0; qidx < phba->cfg_fcp_io_channel;
- qidx++) {
- if (!phba->sli4_hba.fcp_wq[qidx])
- continue;
- if (phba->sli4_hba.fcp_wq[qidx]->queue_id ==
- queid) {
+ qidx++) {
+ qp = phba->sli4_hba.fcp_wq[qidx];
+ if (qp && qp->queue_id == queid) {
/* Sanity check */
rc = lpfc_idiag_que_param_check(
- phba->sli4_hba.fcp_wq[qidx],
- index, count);
+ qp, index, count);
+ if (rc)
+ goto error_out;
+ idiag.ptr_private = qp;
+ goto pass_check;
+ }
+ }
+ }
+ /* NVME work queue */
+ if (phba->sli4_hba.nvme_wq) {
+ for (qidx = 0; qidx < phba->cfg_nvme_io_channel;
+ qidx++) {
+ qp = phba->sli4_hba.nvme_wq[qidx];
+ if (qp && qp->queue_id == queid) {
+ /* Sanity check */
+ rc = lpfc_idiag_que_param_check(
+ qp, index, count);
if (rc)
goto error_out;
- idiag.ptr_private =
- phba->sli4_hba.fcp_wq[qidx];
+ idiag.ptr_private = qp;
goto pass_check;
}
}
@@ -4562,10 +4638,14 @@ lpfc_debug_dump_all_queues(struct lpfc_hba *phba)
*/
lpfc_debug_dump_wq(phba, DUMP_MBX, 0);
lpfc_debug_dump_wq(phba, DUMP_ELS, 0);
+ lpfc_debug_dump_wq(phba, DUMP_NVMELS, 0);
for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++)
lpfc_debug_dump_wq(phba, DUMP_FCP, idx);
+ for (idx = 0; idx < phba->cfg_nvme_io_channel; idx++)
+ lpfc_debug_dump_wq(phba, DUMP_NVME, idx);
+
lpfc_debug_dump_hdr_rq(phba);
lpfc_debug_dump_dat_rq(phba);
/*
@@ -4573,13 +4653,17 @@ lpfc_debug_dump_all_queues(struct lpfc_hba *phba)
*/
lpfc_debug_dump_cq(phba, DUMP_MBX, 0);
lpfc_debug_dump_cq(phba, DUMP_ELS, 0);
+ lpfc_debug_dump_cq(phba, DUMP_NVMELS, 0);
for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++)
lpfc_debug_dump_cq(phba, DUMP_FCP, idx);
+ for (idx = 0; idx < phba->cfg_nvme_io_channel; idx++)
+ lpfc_debug_dump_cq(phba, DUMP_NVME, idx);
+
/*
* Dump Event Queues (EQs)
*/
- for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++)
+ for (idx = 0; idx < phba->io_channel_irqs; idx++)
lpfc_debug_dump_hba_eq(phba, idx);
}