diff mbox series

[12/25] lpfc: Synchronize hardware queues with SCSI MQ interface

Message ID 20181226233334.27518-13-jsmart2021@gmail.com (mailing list archive)
State Superseded
Headers show
Series lpfc updates for 12.2.0.0 | expand

Commit Message

James Smart Dec. 26, 2018, 11:33 p.m. UTC
Now that the lower half has much better per-cpu parallelization
using the hardware queues, the SCSI MQ support needs to be tied
into it.

The involves the following mods:
- Rather than selecting SCSI MQ support at compile time, detect
  support at driver init time using shost_use_blk_mq().
- Add a module parameter, lpfc_enable_scsi_mq, to allow control of
  the drivers default behavior.
- When scsi mq is enabled, use the hardware queue info from the
  midlayer to help select the hardware queue to utilize. This
  required change to the get_scsi-buf_xxx routines.
= Remove lpfc_sli4_scmd_to_wqidx_distr() routine. No longer needed.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
---
 drivers/scsi/lpfc/lpfc.h      |  3 +-
 drivers/scsi/lpfc/lpfc_attr.c | 10 ++++++
 drivers/scsi/lpfc/lpfc_init.c |  7 ++++-
 drivers/scsi/lpfc/lpfc_scsi.c | 73 ++++++++++++-------------------------------
 4 files changed, 38 insertions(+), 55 deletions(-)

Comments

Hannes Reinecke Dec. 28, 2018, 9:21 a.m. UTC | #1
On 12/27/18 12:33 AM, James Smart wrote:
> Now that the lower half has much better per-cpu parallelization
> using the hardware queues, the SCSI MQ support needs to be tied
> into it.
> 
> The involves the following mods:
> - Rather than selecting SCSI MQ support at compile time, detect
>    support at driver init time using shost_use_blk_mq().
> - Add a module parameter, lpfc_enable_scsi_mq, to allow control of
>    the drivers default behavior.
> - When scsi mq is enabled, use the hardware queue info from the
>    midlayer to help select the hardware queue to utilize. This
>    required change to the get_scsi-buf_xxx routines.
> = Remove lpfc_sli4_scmd_to_wqidx_distr() routine. No longer needed.
> 
> Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
>   drivers/scsi/lpfc/lpfc.h      |  3 +-
>   drivers/scsi/lpfc/lpfc_attr.c | 10 ++++++
>   drivers/scsi/lpfc/lpfc_init.c |  7 ++++-
>   drivers/scsi/lpfc/lpfc_scsi.c | 73 ++++++++++++-------------------------------
>   4 files changed, 38 insertions(+), 55 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
diff mbox series

Patch

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 9262c52e32d6..ee4f572144e5 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -619,7 +619,7 @@  struct lpfc_ras_fwlog {
 struct lpfc_hba {
 	/* SCSI interface function jump table entries */
 	struct lpfc_scsi_buf * (*lpfc_get_scsi_buf)
-		(struct lpfc_hba *, struct lpfc_nodelist *);
+		(struct lpfc_hba *, struct lpfc_nodelist *, struct scsi_cmnd *);
 	int (*lpfc_scsi_prep_dma_buf)
 		(struct lpfc_hba *, struct lpfc_scsi_buf *);
 	void (*lpfc_scsi_unprep_dma_buf)
@@ -876,6 +876,7 @@  struct lpfc_hba {
 #define LPFC_ENABLE_NVME 2
 #define LPFC_ENABLE_BOTH 3
 	uint32_t cfg_enable_pbde;
+	uint32_t cfg_enable_scsi_mq;
 	struct nvmet_fc_target_port *targetport;
 	lpfc_vpd_t vpd;		/* vital product data */
 
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index e10d930fcb6a..70686ed6ec2a 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5689,6 +5689,14 @@  LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
  */
 LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
 
+/*
+ * lpfc_enable_scsi_mq: Enable SCSI MQ support in lpfc
+ *       0  = disabled
+ *       1  = enabled (default)
+ * Value range is [0,1]. Default value is 1
+ */
+LPFC_ATTR_R(enable_scsi_mq, 1, 0, 1, "Enable SCSI MQ support in LPFC");
+
 struct device_attribute *lpfc_hba_attrs[] = {
 	&dev_attr_nvme_info,
 	&dev_attr_scsi_stat,
@@ -5803,6 +5811,7 @@  struct device_attribute *lpfc_hba_attrs[] = {
 	&dev_attr_lpfc_ras_fwlog_func,
 	&dev_attr_lpfc_enable_bbcr,
 	&dev_attr_lpfc_enable_dpp,
+	&dev_attr_lpfc_enable_scsi_mq,
 	NULL,
 };
 
@@ -6840,6 +6849,7 @@  lpfc_get_cfgparam(struct lpfc_hba *phba)
 	lpfc_hdw_queue_init(phba, lpfc_hdw_queue);
 	lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
 	lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
+	lpfc_enable_scsi_mq_init(phba, lpfc_enable_scsi_mq);
 
 	if (phba->sli_rev != LPFC_SLI_REV4) {
 		/* NVME only supported on SLI4 */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 3608eba398c6..477fd8a62dc0 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4059,7 +4059,9 @@  lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
 	shost->max_lun = vport->cfg_max_luns;
 	shost->this_id = -1;
 	shost->max_cmd_len = 16;
-	shost->nr_hw_queues = phba->cfg_hdw_queue;
+	if (shost_use_blk_mq(shost) && phba->cfg_enable_scsi_mq) {
+		shost->nr_hw_queues = phba->cfg_hdw_queue;
+	}
 	if (phba->sli_rev == LPFC_SLI_REV4) {
 		shost->dma_boundary =
 			phba->sli4_hba.pc_sli4_params.sge_supp_len-1;
@@ -10981,6 +10983,9 @@  lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
 		goto out_unset_pci_mem_s3;
 	}
 
+	/* no SCSI MQ support for SLI 3 */
+	phba->cfg_enable_scsi_mq = 0;
+
 	/* Initialize and populate the iocb list per host */
 
 	error = lpfc_init_iocb_list(phba, LPFC_IOCB_LIST_CNT);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 12458a0562b7..b3e08520e8b3 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -636,7 +636,8 @@  lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
  *   Pointer to lpfc_scsi_buf - Success
  **/
 static struct lpfc_scsi_buf*
-lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+		     struct scsi_cmnd *cmnd)
 {
 	struct  lpfc_scsi_buf * lpfc_cmd = NULL;
 	struct list_head *scsi_buf_list_get = &phba->lpfc_scsi_buf_list_get;
@@ -674,7 +675,8 @@  lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
  *   Pointer to lpfc_scsi_buf - Success
  **/
 static struct lpfc_scsi_buf*
-lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+		     struct scsi_cmnd *cmnd)
 {
 	struct lpfc_scsi_buf *lpfc_cmd, *lpfc_cmd_next;
 	struct lpfc_sli4_hdw_queue *qp;
@@ -685,12 +687,19 @@  lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 	dma_addr_t pdma_phys_fcp_cmd;
 	uint32_t sgl_size, cpu, idx;
 	int found = 0;
+	int tag;
 
 	cpu = smp_processor_id();
-	if (cpu < phba->cfg_hdw_queue)
-		idx = cpu;
-	else
-		idx = cpu % phba->cfg_hdw_queue;
+	if (cmnd && shost_use_blk_mq(cmnd->device->host) &&
+	    phba->cfg_enable_scsi_mq) {
+		tag = blk_mq_unique_tag(cmnd->request);
+		idx = blk_mq_unique_tag_to_hwq(tag);
+	} else {
+		if (cpu < phba->cfg_hdw_queue)
+			idx = cpu;
+		else
+			idx = cpu % phba->cfg_hdw_queue;
+	}
 
 	qp = &phba->sli4_hba.hdwq[idx];
 	spin_lock_irqsave(&qp->io_buf_list_get_lock, iflag);
@@ -814,9 +823,10 @@  lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
  *   Pointer to lpfc_scsi_buf - Success
  **/
 static struct lpfc_scsi_buf*
-lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+		  struct scsi_cmnd *cmnd)
 {
-	return  phba->lpfc_get_scsi_buf(phba, ndlp);
+	return  phba->lpfc_get_scsi_buf(phba, ndlp, cmnd);
 }
 
 /**
@@ -3657,49 +3667,6 @@  lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
 }
 
 /**
- * lpfc_sli4_scmd_to_wqidx_distr - scsi command to SLI4 WQ index distribution
- * @phba: Pointer to HBA context object.
- *
- * This routine performs a roundrobin SCSI command to SLI4 FCP WQ index
- * distribution.  This is called by __lpfc_sli_issue_iocb_s4() with the hbalock
- * held.
- * If scsi-mq is enabled, get the default block layer mapping of software queues
- * to hardware queues. This information is saved in request tag.
- *
- * Return: index into SLI4 fast-path FCP queue index.
- **/
-int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba,
-				  struct lpfc_scsi_buf *lpfc_cmd)
-{
-	struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
-	struct lpfc_vector_map_info *cpup;
-	int chann, cpu;
-	uint32_t tag;
-	uint16_t hwq;
-
-	if (cmnd && shost_use_blk_mq(cmnd->device->host)) {
-		tag = blk_mq_unique_tag(cmnd->request);
-		hwq = blk_mq_unique_tag_to_hwq(tag);
-
-		return hwq;
-	}
-
-	if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU &&
-	    phba->cfg_hdw_queue > 1) {
-		cpu = lpfc_cmd->cpu;
-		if (cpu < phba->sli4_hba.num_present_cpu) {
-			cpup = phba->sli4_hba.cpu_map;
-			cpup += cpu;
-			return cpup->channel_id;
-		}
-	}
-	chann = atomic_add_return(1, &phba->fcp_qidx);
-	chann = chann % phba->cfg_hdw_queue;
-	return chann;
-}
-
-
-/**
  * lpfc_scsi_cmd_iocb_cmpl - Scsi cmnd IOCB completion routine
  * @phba: The Hba for which this call is being executed.
  * @pIocbIn: The command IOCBQ for the scsi cmnd.
@@ -4475,7 +4442,7 @@  lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
 		}
 	}
 
-	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
+	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp, cmnd);
 	if (lpfc_cmd == NULL) {
 		lpfc_rampdown_queue_depth(phba);
 
@@ -4914,7 +4881,7 @@  lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
 		return FAILED;
 	pnode = rdata->pnode;
 
-	lpfc_cmd = lpfc_get_scsi_buf(phba, pnode);
+	lpfc_cmd = lpfc_get_scsi_buf(phba, pnode, NULL);
 	if (lpfc_cmd == NULL)
 		return FAILED;
 	lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;