Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e565cf0 authored by James Smart's avatar James Smart Committed by Martin K. Petersen
Browse files

scsi: lpfc: Work around NVME cmd iu SGL type



The hardware offload for NVME commands was created when the
FC-NVME standard was setting SGL Descriptor Type to SGL Data
Block Descriptor (0h) and SGL Descriptor Sub Type to Address (0h).

A late change in NVMe-over-Fabrics obsoleted these values, creating
a transport SGL descriptor type with new values to go into these
fields.

For initial hardware support, in order to be compliant to the spec,
use host-supplied cmd IU buffers instead of the adapter generated
values. Later hardware will correct this.

Add a module parameter to override this offload disablement if looking
for lowest latency. This is reasonable as nothing in FC-NVME uses
the SQE SGL values.

Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 63452e14
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -782,6 +782,7 @@ struct lpfc_hba {
	uint32_t cfg_fcp_io_channel;
	uint32_t cfg_suppress_rsp;
	uint32_t cfg_nvme_oas;
	uint32_t cfg_nvme_embed_cmd;
	uint32_t cfg_nvme_io_channel;
	uint32_t cfg_nvmet_mrq;
	uint32_t cfg_enable_nvmet;
+14 −0
Original line number Diff line number Diff line
@@ -5041,6 +5041,18 @@ LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
	     "Use OAS bit on NVME IOs");

/*
 * lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs
 *
 *      0  = Put NVME Command in SGL
 *      1  = Embed NVME Command in WQE (unless G7)
 *      2 =  Embed NVME Command in WQE (force)
 *
 * Value range is [0,2]. Default value is 1.
 */
LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
	     "Embed NVME Command in WQE");

/*
 * lpfc_fcp_io_channel: Set the number of FCP IO channels the driver
 * will advertise it supports to the SCSI layer. This also will map to
@@ -5282,6 +5294,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
	&dev_attr_lpfc_task_mgmt_tmo,
	&dev_attr_lpfc_use_msi,
	&dev_attr_lpfc_nvme_oas,
	&dev_attr_lpfc_nvme_embed_cmd,
	&dev_attr_lpfc_auto_imax,
	&dev_attr_lpfc_fcp_imax,
	&dev_attr_lpfc_fcp_cpu_map,
@@ -6306,6 +6319,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
	lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN);
	lpfc_use_msi_init(phba, lpfc_use_msi);
	lpfc_nvme_oas_init(phba, lpfc_nvme_oas);
	lpfc_nvme_embed_cmd_init(phba, lpfc_nvme_embed_cmd);
	lpfc_auto_imax_init(phba, lpfc_auto_imax);
	lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
	lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
+1 −0
Original line number Diff line number Diff line
@@ -2678,6 +2678,7 @@ struct lpfc_mbx_read_rev {
#define lpfc_mbx_rd_rev_vpd_MASK		0x00000001
#define lpfc_mbx_rd_rev_vpd_WORD		word1
	uint32_t first_hw_rev;
#define LPFC_G7_ASIC_1				0xd
	uint32_t second_hw_rev;
	uint32_t word4_rsvd;
	uint32_t third_hw_rev;
+2 −2
Original line number Diff line number Diff line
@@ -10653,11 +10653,11 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
		phba->fcp_embed_io = 0;

	lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME,
			"6422 XIB %d: FCP %d %d NVME %d %d %d\n",
			"6422 XIB %d: FCP %d %d NVME %d %d %d %d\n",
			bf_get(cfg_xib, mbx_sli4_parameters),
			phba->fcp_embed_pbde, phba->fcp_embed_io,
			phba->nvme_support, phba->nvme_embed_pbde,
			phba->cfg_suppress_rsp);
			phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);

	if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
	    (bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) &&
+36 −15
Original line number Diff line number Diff line
@@ -617,10 +617,20 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
		       struct lpfc_nvme_buf *lpfc_ncmd,
		       struct nvmefc_fcp_req *nCmd)
{
	struct lpfc_hba  *phba = vport->phba;
	struct sli4_sge *sgl;
	union lpfc_wqe128 *wqe;
	uint32_t *wptr, *dptr;

	/*
	 * Get a local pointer to the built-in wqe and correct
	 * the cmd size to match NVME's 96 bytes and fix
	 * the dma address.
	 */

	/* 128 byte wqe support here */
	wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe;

	/*
	 * Adjust the FCP_CMD and FCP_RSP DMA data and sge_len to
	 * match NVME.  NVME sends 96 bytes. Also, use the
@@ -630,6 +640,25 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
	 */
	sgl = lpfc_ncmd->nvme_sgl;
	sgl->sge_len = cpu_to_le32(nCmd->cmdlen);
	if (phba->cfg_nvme_embed_cmd) {
		sgl->addr_hi = 0;
		sgl->addr_lo = 0;

		/* Word 0-2 - NVME CMND IU (embedded payload) */
		wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED;
		wqe->generic.bde.tus.f.bdeSize = 56;
		wqe->generic.bde.addrHigh = 0;
		wqe->generic.bde.addrLow =  64;  /* Word 16 */
	} else {
		sgl->addr_hi = cpu_to_le32(putPaddrHigh(nCmd->cmddma));
		sgl->addr_lo = cpu_to_le32(putPaddrLow(nCmd->cmddma));

		/* Word 0-2 - NVME CMND IU Inline BDE */
		wqe->generic.bde.tus.f.bdeFlags =  BUFF_TYPE_BDE_64;
		wqe->generic.bde.tus.f.bdeSize = nCmd->cmdlen;
		wqe->generic.bde.addrHigh = sgl->addr_hi;
		wqe->generic.bde.addrLow =  sgl->addr_lo;
	}

	sgl++;

@@ -644,27 +673,19 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
	sgl->word2 = cpu_to_le32(sgl->word2);
	sgl->sge_len = cpu_to_le32(nCmd->rsplen);

	/*
	 * Get a local pointer to the built-in wqe and correct
	 * the cmd size to match NVME's 96 bytes and fix
	 * the dma address.
	 */

	/* 128 byte wqe support here */
	wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe;

	/* Word 0-2 - NVME CMND IU (embedded payload) */
	wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED;
	wqe->generic.bde.tus.f.bdeSize = 56;
	wqe->generic.bde.addrHigh = 0;
	wqe->generic.bde.addrLow =  64;  /* Word 16 */

	/* Word 3 */
	bf_set(payload_offset_len, &wqe->fcp_icmd,
	       (nCmd->rsplen + nCmd->cmdlen));

	/* Word 10 */
	bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1);

	if (!phba->cfg_nvme_embed_cmd) {
		bf_set(wqe_dbde, &wqe->generic.wqe_com, 1);
		bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 0);
		return;
	}
	bf_set(wqe_dbde, &wqe->generic.wqe_com, 0);
	bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1);

	/*
Loading