diff mbox series

[02/12] qla2xxx: Add First Burst support for FC-NVMe devices

Message ID 20190212234046.29809-3-hmadhani@marvell.com (mailing list archive)
State Superseded
Headers show
Series qla2xxx: Misc bug fixes for the driver | expand

Commit Message

Himanshu Madhani Feb. 12, 2019, 11:40 p.m. UTC
From: Darren Trapp <darren.trapp@cavium.com>

Add Support for First Burst for FC-NVMe protocol. This
feature requires First Burst support in the firmware.

Signed-off-by: Darren Trapp <darren.trapp@cavium.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h  |  4 ++++
 drivers/scsi/qla2xxx/qla_init.c |  6 ++++++
 drivers/scsi/qla2xxx/qla_iocb.c |  5 ++++-
 drivers/scsi/qla2xxx/qla_isr.c  |  9 +++++++++
 drivers/scsi/qla2xxx/qla_mbx.c  |  5 +++--
 drivers/scsi/qla2xxx/qla_nvme.c | 15 ++++++++++++---
 drivers/scsi/qla2xxx/qla_nvme.h |  2 +-
 7 files changed, 39 insertions(+), 7 deletions(-)

Comments

kernel test robot Feb. 13, 2019, 1:50 p.m. UTC | #1
Hi Darren,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on scsi/for-next]
[also build test WARNING on next-20190212]
[cannot apply to v5.0-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Himanshu-Madhani/qla2xxx-Misc-bug-fixes-for-the-driver/20190213-094944
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

All warnings (new ones prefixed by >>):

   drivers/scsi/qla2xxx/qla_nvme.c:361:40: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:361:40: sparse:    expected unsigned short [usertype] control_flags
   drivers/scsi/qla2xxx/qla_nvme.c:361:40: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:366:40: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:366:40: sparse:    expected unsigned short [usertype] control_flags
   drivers/scsi/qla2xxx/qla_nvme.c:366:40: sparse:    got restricted __le16 [usertype]
>> drivers/scsi/qla2xxx/qla_nvme.c:374:56: sparse: warning: invalid assignment: |=
   drivers/scsi/qla2xxx/qla_nvme.c:374:56: sparse:    left side has type unsigned short
   drivers/scsi/qla2xxx/qla_nvme.c:374:56: sparse:    right side has type restricted __le16
   drivers/scsi/qla2xxx/qla_nvme.c:384:31: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:384:31: sparse:    expected unsigned short [usertype] nport_handle
   drivers/scsi/qla2xxx/qla_nvme.c:384:31: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:391:35: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:391:35: sparse:    expected unsigned short [usertype] nvme_rsp_dsd_len
   drivers/scsi/qla2xxx/qla_nvme.c:391:35: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:392:43: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:392:43: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:392:43: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:393:43: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:393:43: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:393:43: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:396:37: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:396:37: sparse:    expected unsigned short [usertype] nvme_cmnd_dseg_len
   drivers/scsi/qla2xxx/qla_nvme.c:396:37: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:397:44: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:397:44: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:397:44: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:398:44: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:398:44: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:398:44: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:400:29: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:400:29: sparse:    expected unsigned short [usertype] dseg_count
   drivers/scsi/qla2xxx/qla_nvme.c:400:29: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:401:29: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:401:29: sparse:    expected unsigned int [usertype] byte_count
   drivers/scsi/qla2xxx/qla_nvme.c:401:29: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:429:64: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:429:64: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:429:64: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:437:28: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:437:28: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:437:28: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:438:28: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:438:28: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:438:28: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:439:28: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:439:28: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:439:28: sparse:    got restricted __le32 [usertype]

sparse warnings: (new ones prefixed by >>)

   drivers/scsi/qla2xxx/qla_nvme.c:361:40: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:361:40: sparse:    expected unsigned short [usertype] control_flags
   drivers/scsi/qla2xxx/qla_nvme.c:361:40: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:366:40: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:366:40: sparse:    expected unsigned short [usertype] control_flags
   drivers/scsi/qla2xxx/qla_nvme.c:366:40: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:374:56: sparse: warning: invalid assignment: |=
>> drivers/scsi/qla2xxx/qla_nvme.c:374:56: sparse:    left side has type unsigned short
>> drivers/scsi/qla2xxx/qla_nvme.c:374:56: sparse:    right side has type restricted __le16
   drivers/scsi/qla2xxx/qla_nvme.c:384:31: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:384:31: sparse:    expected unsigned short [usertype] nport_handle
   drivers/scsi/qla2xxx/qla_nvme.c:384:31: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:391:35: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:391:35: sparse:    expected unsigned short [usertype] nvme_rsp_dsd_len
   drivers/scsi/qla2xxx/qla_nvme.c:391:35: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:392:43: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:392:43: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:392:43: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:393:43: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:393:43: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:393:43: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:396:37: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:396:37: sparse:    expected unsigned short [usertype] nvme_cmnd_dseg_len
   drivers/scsi/qla2xxx/qla_nvme.c:396:37: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:397:44: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:397:44: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:397:44: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:398:44: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:398:44: sparse:    expected unsigned int
   drivers/scsi/qla2xxx/qla_nvme.c:398:44: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:400:29: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:400:29: sparse:    expected unsigned short [usertype] dseg_count
   drivers/scsi/qla2xxx/qla_nvme.c:400:29: sparse:    got restricted __le16 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:401:29: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:401:29: sparse:    expected unsigned int [usertype] byte_count
   drivers/scsi/qla2xxx/qla_nvme.c:401:29: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:429:64: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:429:64: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:429:64: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:437:28: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:437:28: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:437:28: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:438:28: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:438:28: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:438:28: sparse:    got restricted __le32 [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:439:28: sparse: warning: incorrect type in assignment (different base types)
   drivers/scsi/qla2xxx/qla_nvme.c:439:28: sparse:    expected unsigned int [usertype]
   drivers/scsi/qla2xxx/qla_nvme.c:439:28: sparse:    got restricted __le32 [usertype]

vim +374 drivers/scsi/qla2xxx/qla_nvme.c

   274	
   275	static inline int qla2x00_start_nvme_mq(srb_t *sp)
   276	{
   277		unsigned long   flags;
   278		uint32_t        *clr_ptr;
   279		uint32_t        index;
   280		uint32_t        handle;
   281		struct cmd_nvme *cmd_pkt;
   282		uint16_t        cnt, i;
   283		uint16_t        req_cnt;
   284		uint16_t        tot_dsds;
   285		uint16_t	avail_dsds;
   286		uint32_t	*cur_dsd;
   287		struct req_que *req = NULL;
   288		struct scsi_qla_host *vha = sp->fcport->vha;
   289		struct qla_hw_data *ha = vha->hw;
   290		struct qla_qpair *qpair = sp->qpair;
   291		struct srb_iocb *nvme = &sp->u.iocb_cmd;
   292		struct scatterlist *sgl, *sg;
   293		struct nvmefc_fcp_req *fd = nvme->u.nvme.desc;
   294		uint32_t        rval = QLA_SUCCESS;
   295	
   296		/* Setup qpair pointers */
   297		req = qpair->req;
   298		tot_dsds = fd->sg_cnt;
   299	
   300		/* Acquire qpair specific lock */
   301		spin_lock_irqsave(&qpair->qp_lock, flags);
   302	
   303		/* Check for room in outstanding command list. */
   304		handle = req->current_outstanding_cmd;
   305		for (index = 1; index < req->num_outstanding_cmds; index++) {
   306			handle++;
   307			if (handle == req->num_outstanding_cmds)
   308				handle = 1;
   309			if (!req->outstanding_cmds[handle])
   310				break;
   311		}
   312	
   313		if (index == req->num_outstanding_cmds) {
   314			rval = -EBUSY;
   315			goto queuing_error;
   316		}
   317		req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
   318		if (req->cnt < (req_cnt + 2)) {
   319			cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
   320			    RD_REG_DWORD_RELAXED(req->req_q_out);
   321	
   322			if (req->ring_index < cnt)
   323				req->cnt = cnt - req->ring_index;
   324			else
   325				req->cnt = req->length - (req->ring_index - cnt);
   326	
   327			if (req->cnt < (req_cnt + 2)){
   328				rval = -EBUSY;
   329				goto queuing_error;
   330			}
   331		}
   332	
   333		if (unlikely(!fd->sqid)) {
   334			struct nvme_fc_cmd_iu *cmd = fd->cmdaddr;
   335			if (cmd->sqe.common.opcode == nvme_admin_async_event) {
   336				nvme->u.nvme.aen_op = 1;
   337				atomic_inc(&ha->nvme_active_aen_cnt);
   338			}
   339		}
   340	
   341		/* Build command packet. */
   342		req->current_outstanding_cmd = handle;
   343		req->outstanding_cmds[handle] = sp;
   344		sp->handle = handle;
   345		req->cnt -= req_cnt;
   346	
   347		cmd_pkt = (struct cmd_nvme *)req->ring_ptr;
   348		cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
   349	
   350		/* Zero out remaining portion of packet. */
   351		clr_ptr = (uint32_t *)cmd_pkt + 2;
   352		memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
   353	
   354		cmd_pkt->entry_status = 0;
   355	
   356		/* Update entry type to indicate Command NVME IOCB */
   357		cmd_pkt->entry_type = COMMAND_NVME;
   358	
   359		/* No data transfer how do we check buffer len == 0?? */
   360		if (fd->io_dir == NVMEFC_FCP_READ) {
 > 361			cmd_pkt->control_flags =
   362			    cpu_to_le16(CF_READ_DATA);
   363			vha->qla_stats.input_bytes += fd->payload_length;
   364			vha->qla_stats.input_requests++;
   365		} else if (fd->io_dir == NVMEFC_FCP_WRITE) {
   366			cmd_pkt->control_flags =
   367			    cpu_to_le16(CF_WRITE_DATA);
   368			if ((vha->flags.nvme_first_burst) &&
   369			    (sp->fcport->nvme_prli_service_param &
   370				NVME_PRLI_SP_FIRST_BURST)) {
   371				if ((fd->payload_length <=
   372				    sp->fcport->nvme_first_burst_size) ||
   373					(sp->fcport->nvme_first_burst_size == 0))
 > 374					cmd_pkt->control_flags |=
   375					    cpu_to_le16(CF_NVME_FIRST_BURST_ENABLE);
   376			}
   377			vha->qla_stats.output_bytes += fd->payload_length;
   378			vha->qla_stats.output_requests++;
   379		} else if (fd->io_dir == 0) {
   380			cmd_pkt->control_flags = 0;
   381		}
   382	
   383		/* Set NPORT-ID */
   384		cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
   385		cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
   386		cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
   387		cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
   388		cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
   389	
   390		/* NVME RSP IU */
   391		cmd_pkt->nvme_rsp_dsd_len = cpu_to_le16(fd->rsplen);
   392		cmd_pkt->nvme_rsp_dseg_address[0] = cpu_to_le32(LSD(fd->rspdma));
   393		cmd_pkt->nvme_rsp_dseg_address[1] = cpu_to_le32(MSD(fd->rspdma));
   394	
   395		/* NVME CNMD IU */
   396		cmd_pkt->nvme_cmnd_dseg_len = cpu_to_le16(fd->cmdlen);
   397		cmd_pkt->nvme_cmnd_dseg_address[0] = cpu_to_le32(LSD(fd->cmddma));
   398		cmd_pkt->nvme_cmnd_dseg_address[1] = cpu_to_le32(MSD(fd->cmddma));
   399	
   400		cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
   401		cmd_pkt->byte_count = cpu_to_le32(fd->payload_length);
   402	
   403		/* One DSD is available in the Command Type NVME IOCB */
   404		avail_dsds = 1;
   405		cur_dsd = (uint32_t *)&cmd_pkt->nvme_data_dseg_address[0];
   406		sgl = fd->first_sgl;
   407	
   408		/* Load data segments */
   409		for_each_sg(sgl, sg, tot_dsds, i) {
   410			dma_addr_t      sle_dma;
   411			cont_a64_entry_t *cont_pkt;
   412	
   413			/* Allocate additional continuation packets? */
   414			if (avail_dsds == 0) {
   415				/*
   416				 * Five DSDs are available in the Continuation
   417				 * Type 1 IOCB.
   418				 */
   419	
   420				/* Adjust ring index */
   421				req->ring_index++;
   422				if (req->ring_index == req->length) {
   423					req->ring_index = 0;
   424					req->ring_ptr = req->ring;
   425				} else {
   426					req->ring_ptr++;
   427				}
   428				cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
   429				*((uint32_t *)(&cont_pkt->entry_type)) =
   430				    cpu_to_le32(CONTINUE_A64_TYPE);
   431	
   432				cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
   433				avail_dsds = 5;
   434			}
   435	
   436			sle_dma = sg_dma_address(sg);
   437			*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
   438			*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
   439			*cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
   440			avail_dsds--;
   441		}
   442	
   443		/* Set total entry count. */
   444		cmd_pkt->entry_count = (uint8_t)req_cnt;
   445		wmb();
   446	
   447		/* Adjust ring index. */
   448		req->ring_index++;
   449		if (req->ring_index == req->length) {
   450			req->ring_index = 0;
   451			req->ring_ptr = req->ring;
   452		} else {
   453			req->ring_ptr++;
   454		}
   455	
   456		/* Set chip new ring index. */
   457		WRT_REG_DWORD(req->req_q_in, req->ring_index);
   458	
   459	queuing_error:
   460		spin_unlock_irqrestore(&qpair->qp_lock, flags);
   461		return rval;
   462	}
   463	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 80acf30fd8a5..c256ba7fba84 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2367,7 +2367,9 @@  typedef struct fc_port {
 #define NVME_PRLI_SP_INITIATOR  BIT_5
 #define NVME_PRLI_SP_TARGET     BIT_4
 #define NVME_PRLI_SP_DISCOVERY  BIT_3
+#define NVME_PRLI_SP_FIRST_BURST	BIT_0
 	uint8_t nvme_flag;
+	uint32_t nvme_first_burst_size;
 #define NVME_FLAG_REGISTERED 4
 #define NVME_FLAG_DELETING 2
 #define NVME_FLAG_RESETTING 1
@@ -3966,6 +3968,7 @@  struct qla_hw_data {
 	uint16_t	fw_subminor_version;
 	uint16_t	fw_attributes;
 	uint16_t	fw_attributes_h;
+#define FW_ATTR_H_NVME_FBURST 	BIT_1
 #define FW_ATTR_H_NVME		BIT_10
 #define FW_ATTR_H_NVME_UPDATED  BIT_14
 
@@ -4260,6 +4263,7 @@  typedef struct scsi_qla_host {
 		uint32_t	qpairs_req_created:1;
 		uint32_t	qpairs_rsp_created:1;
 		uint32_t	nvme_enabled:1;
+		uint32_t        nvme_first_burst:1;
 	} flags;
 
 	atomic_t	loop_state;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index cdf57eb643b3..2d9336a87e42 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1829,6 +1829,12 @@  qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 
 		ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
 		ea->fcport->logout_on_delete = 1;
+		ea->fcport->nvme_prli_service_param = ea->iop[0];
+		if (ea->iop[0] & NVME_PRLI_SP_FIRST_BURST)
+			ea->fcport->nvme_first_burst_size =
+			    (ea->iop[1] & 0xffff) * 512;
+		else
+			ea->fcport->nvme_first_burst_size = 0;
 		qla24xx_post_gpdb_work(vha, ea->fcport, 0);
 		break;
 	default:
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 2c27ae1924c5..cdac282b5bd3 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2419,8 +2419,11 @@  qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 
 	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
 	logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI);
-	if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI)
+	if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI) {
 		logio->control_flags |= LCF_NVME_PRLI;
+		if (sp->vha->flags.nvme_first_burst)
+			logio->io_parameter[0] = NVME_PRLI_SP_FIRST_BURST;
+	}
 
 	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
 	logio->port_id[0] = sp->fcport->d_id.b.al_pa;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index bde9940ea7d1..b5ae76869d5b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1715,6 +1715,15 @@  qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 
 		vha->hw->exch_starvation = 0;
 		data[0] = MBS_COMMAND_COMPLETE;
+
+		if (sp->type == SRB_PRLI_CMD) {
+			lio->u.logio.iop[0] =
+			    le32_to_cpu(logio->io_parameter[0]);
+			lio->u.logio.iop[1] =
+			    le32_to_cpu(logio->io_parameter[1]);
+			goto logio_done;
+		}
+
 		if (sp->type != SRB_LOGIN_CMD)
 			goto logio_done;
 
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f4adf6baee69..6c911f2e4cdb 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1112,6 +1112,9 @@  qla2x00_get_fw_version(scsi_qla_host_t *vha)
 		if ((ha->fw_attributes_h &
 		    (FW_ATTR_H_NVME | FW_ATTR_H_NVME_UPDATED)) &&
 			ql2xnvmeenable) {
+			if (ha->fw_attributes_h & FW_ATTR_H_NVME_FBURST)
+				vha->flags.nvme_first_burst = 1;
+
 			vha->flags.nvme_enabled = 1;
 			ql_log(ql_log_info, vha, 0xd302,
 			    "%s: FC-NVMe is Enabled (0x%x)\n",
@@ -6267,8 +6270,6 @@  int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
 	fcport->d_id.b.rsvd_1 = 0;
 
 	if (fcport->fc4f_nvme) {
-		fcport->nvme_prli_service_param =
-		    pd->prli_nvme_svc_param_word_3;
 		fcport->port_type = FCT_NVME;
 	} else {
 		/* If not target must be initiator or unknown type. */
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 39d892bbd219..efc23761de1c 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -359,16 +359,25 @@  static inline int qla2x00_start_nvme_mq(srb_t *sp)
 	/* No data transfer how do we check buffer len == 0?? */
 	if (fd->io_dir == NVMEFC_FCP_READ) {
 		cmd_pkt->control_flags =
-		    cpu_to_le16(CF_READ_DATA | CF_NVME_ENABLE);
+		    cpu_to_le16(CF_READ_DATA);
 		vha->qla_stats.input_bytes += fd->payload_length;
 		vha->qla_stats.input_requests++;
 	} else if (fd->io_dir == NVMEFC_FCP_WRITE) {
 		cmd_pkt->control_flags =
-		    cpu_to_le16(CF_WRITE_DATA | CF_NVME_ENABLE);
+		    cpu_to_le16(CF_WRITE_DATA);
+		if ((vha->flags.nvme_first_burst) &&
+		    (sp->fcport->nvme_prli_service_param &
+			NVME_PRLI_SP_FIRST_BURST)) {
+			if ((fd->payload_length <=
+			    sp->fcport->nvme_first_burst_size) ||
+				(sp->fcport->nvme_first_burst_size == 0))
+				cmd_pkt->control_flags |=
+				    cpu_to_le16(CF_NVME_FIRST_BURST_ENABLE);
+		}
 		vha->qla_stats.output_bytes += fd->payload_length;
 		vha->qla_stats.output_requests++;
 	} else if (fd->io_dir == 0) {
-		cmd_pkt->control_flags = cpu_to_le16(CF_NVME_ENABLE);
+		cmd_pkt->control_flags = 0;
 	}
 
 	/* Set NPORT-ID */
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h
index 4941d107fb1c..da8dad5ad693 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.h
+++ b/drivers/scsi/qla2xxx/qla_nvme.h
@@ -57,7 +57,7 @@  struct cmd_nvme {
 	uint64_t rsvd;
 
 	uint16_t control_flags;         /* Control Flags */
-#define CF_NVME_ENABLE                  BIT_9
+#define CF_NVME_FIRST_BURST_ENABLE	BIT_11
 #define CF_DIF_SEG_DESCR_ENABLE         BIT_3
 #define CF_DATA_SEG_DESCR_ENABLE        BIT_2
 #define CF_READ_DATA                    BIT_1