xref: /openbmc/linux/drivers/scsi/lpfc/lpfc_nvmet.c (revision 771db5c0)
1d613b6a7SJames Smart /*******************************************************************
2d613b6a7SJames Smart  * This file is part of the Emulex Linux Device Driver for         *
3d613b6a7SJames Smart  * Fibre Channsel Host Bus Adapters.                               *
4d080abe0SJames Smart  * Copyright (C) 2017 Broadcom. All Rights Reserved. The term      *
5d080abe0SJames Smart  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
6d613b6a7SJames Smart  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
7d613b6a7SJames Smart  * EMULEX and SLI are trademarks of Emulex.                        *
8d080abe0SJames Smart  * www.broadcom.com                                                *
9d613b6a7SJames Smart  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
10d613b6a7SJames Smart  *                                                                 *
11d613b6a7SJames Smart  * This program is free software; you can redistribute it and/or   *
12d613b6a7SJames Smart  * modify it under the terms of version 2 of the GNU General       *
13d613b6a7SJames Smart  * Public License as published by the Free Software Foundation.    *
14d613b6a7SJames Smart  * This program is distributed in the hope that it will be useful. *
15d613b6a7SJames Smart  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
16d613b6a7SJames Smart  * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
17d613b6a7SJames Smart  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
18d613b6a7SJames Smart  * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
19d613b6a7SJames Smart  * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
20d613b6a7SJames Smart  * more details, a copy of which can be found in the file COPYING  *
21d613b6a7SJames Smart  * included with this package.                                     *
22d613b6a7SJames Smart  ********************************************************************/
23d613b6a7SJames Smart #include <linux/pci.h>
24d613b6a7SJames Smart #include <linux/slab.h>
25d613b6a7SJames Smart #include <linux/interrupt.h>
26d613b6a7SJames Smart #include <linux/delay.h>
27d613b6a7SJames Smart #include <asm/unaligned.h>
28d613b6a7SJames Smart #include <linux/crc-t10dif.h>
29d613b6a7SJames Smart #include <net/checksum.h>
30d613b6a7SJames Smart 
31d613b6a7SJames Smart #include <scsi/scsi.h>
32d613b6a7SJames Smart #include <scsi/scsi_device.h>
33d613b6a7SJames Smart #include <scsi/scsi_eh.h>
34d613b6a7SJames Smart #include <scsi/scsi_host.h>
35d613b6a7SJames Smart #include <scsi/scsi_tcq.h>
36d613b6a7SJames Smart #include <scsi/scsi_transport_fc.h>
37d613b6a7SJames Smart #include <scsi/fc/fc_fs.h>
38d613b6a7SJames Smart 
39d613b6a7SJames Smart #include <../drivers/nvme/host/nvme.h>
40d613b6a7SJames Smart #include <linux/nvme-fc-driver.h>
41d613b6a7SJames Smart 
42d613b6a7SJames Smart #include "lpfc_version.h"
43d613b6a7SJames Smart #include "lpfc_hw4.h"
44d613b6a7SJames Smart #include "lpfc_hw.h"
45d613b6a7SJames Smart #include "lpfc_sli.h"
46d613b6a7SJames Smart #include "lpfc_sli4.h"
47d613b6a7SJames Smart #include "lpfc_nl.h"
48d613b6a7SJames Smart #include "lpfc_disc.h"
49d613b6a7SJames Smart #include "lpfc.h"
50d613b6a7SJames Smart #include "lpfc_scsi.h"
51d613b6a7SJames Smart #include "lpfc_nvme.h"
52d613b6a7SJames Smart #include "lpfc_nvmet.h"
53d613b6a7SJames Smart #include "lpfc_logmsg.h"
54d613b6a7SJames Smart #include "lpfc_crtn.h"
55d613b6a7SJames Smart #include "lpfc_vport.h"
562b65e182SJames Smart #include "lpfc_debugfs.h"
57d613b6a7SJames Smart 
58d613b6a7SJames Smart static struct lpfc_iocbq *lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *,
59d613b6a7SJames Smart 						 struct lpfc_nvmet_rcv_ctx *,
60d613b6a7SJames Smart 						 dma_addr_t rspbuf,
61d613b6a7SJames Smart 						 uint16_t rspsize);
62d613b6a7SJames Smart static struct lpfc_iocbq *lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *,
63d613b6a7SJames Smart 						  struct lpfc_nvmet_rcv_ctx *);
64d613b6a7SJames Smart static int lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *,
65d613b6a7SJames Smart 					  struct lpfc_nvmet_rcv_ctx *,
66d613b6a7SJames Smart 					  uint32_t, uint16_t);
67d613b6a7SJames Smart static int lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *,
68d613b6a7SJames Smart 					    struct lpfc_nvmet_rcv_ctx *,
69d613b6a7SJames Smart 					    uint32_t, uint16_t);
70d613b6a7SJames Smart static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *,
71d613b6a7SJames Smart 					   struct lpfc_nvmet_rcv_ctx *,
72d613b6a7SJames Smart 					   uint32_t, uint16_t);
73d613b6a7SJames Smart 
7486c67379SJames Smart void
7586c67379SJames Smart lpfc_nvmet_defer_release(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp)
7686c67379SJames Smart {
7786c67379SJames Smart 	unsigned long iflag;
7886c67379SJames Smart 
7986c67379SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
8086c67379SJames Smart 			"6313 NVMET Defer ctx release xri x%x flg x%x\n",
8186c67379SJames Smart 			ctxp->oxid, ctxp->flag);
8286c67379SJames Smart 
8386c67379SJames Smart 	spin_lock_irqsave(&phba->sli4_hba.abts_nvme_buf_list_lock, iflag);
8486c67379SJames Smart 	if (ctxp->flag & LPFC_NVMET_CTX_RLS) {
8586c67379SJames Smart 		spin_unlock_irqrestore(&phba->sli4_hba.abts_nvme_buf_list_lock,
8686c67379SJames Smart 				       iflag);
8786c67379SJames Smart 		return;
8886c67379SJames Smart 	}
8986c67379SJames Smart 	ctxp->flag |= LPFC_NVMET_CTX_RLS;
9086c67379SJames Smart 	list_add_tail(&ctxp->list, &phba->sli4_hba.lpfc_abts_nvmet_ctx_list);
9186c67379SJames Smart 	spin_unlock_irqrestore(&phba->sli4_hba.abts_nvme_buf_list_lock, iflag);
9286c67379SJames Smart }
9386c67379SJames Smart 
94d613b6a7SJames Smart /**
95d613b6a7SJames Smart  * lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response
96d613b6a7SJames Smart  * @phba: Pointer to HBA context object.
97d613b6a7SJames Smart  * @cmdwqe: Pointer to driver command WQE object.
98d613b6a7SJames Smart  * @wcqe: Pointer to driver response CQE object.
99d613b6a7SJames Smart  *
100d613b6a7SJames Smart  * The function is called from SLI ring event handler with no
101d613b6a7SJames Smart  * lock held. This function is the completion handler for NVME LS commands
102d613b6a7SJames Smart  * The function frees memory resources used for the NVME commands.
103d613b6a7SJames Smart  **/
104d613b6a7SJames Smart static void
105d613b6a7SJames Smart lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
106d613b6a7SJames Smart 			  struct lpfc_wcqe_complete *wcqe)
107d613b6a7SJames Smart {
108d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
109d613b6a7SJames Smart 	struct nvmefc_tgt_ls_req *rsp;
110d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
111d613b6a7SJames Smart 	uint32_t status, result;
112d613b6a7SJames Smart 
113d613b6a7SJames Smart 	status = bf_get(lpfc_wcqe_c_status, wcqe);
114d613b6a7SJames Smart 	result = wcqe->parameter;
115ce1b591cSJames Smart 	ctxp = cmdwqe->context2;
116ce1b591cSJames Smart 
117ce1b591cSJames Smart 	if (ctxp->state != LPFC_NVMET_STE_LS_RSP || ctxp->entry_cnt != 2) {
118ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
119ce1b591cSJames Smart 				"6410 NVMET LS cmpl state mismatch IO x%x: "
120ce1b591cSJames Smart 				"%d %d\n",
121ce1b591cSJames Smart 				ctxp->oxid, ctxp->state, ctxp->entry_cnt);
122ce1b591cSJames Smart 	}
123ce1b591cSJames Smart 
124d613b6a7SJames Smart 	if (!phba->targetport)
125d613b6a7SJames Smart 		goto out;
126d613b6a7SJames Smart 
127d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
128d613b6a7SJames Smart 
129d613b6a7SJames Smart 	if (status)
130d613b6a7SJames Smart 		atomic_inc(&tgtp->xmt_ls_rsp_error);
131d613b6a7SJames Smart 	else
132d613b6a7SJames Smart 		atomic_inc(&tgtp->xmt_ls_rsp_cmpl);
133d613b6a7SJames Smart 
134d613b6a7SJames Smart out:
135d613b6a7SJames Smart 	rsp = &ctxp->ctx.ls_req;
136d613b6a7SJames Smart 
1372b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET LS  CMPL: xri x%x stat x%x result x%x\n",
1382b65e182SJames Smart 			 ctxp->oxid, status, result);
1392b65e182SJames Smart 
140d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
141ce1b591cSJames Smart 			"6038 NVMET LS rsp cmpl: %d %d oxid x%x\n",
142ce1b591cSJames Smart 			status, result, ctxp->oxid);
143d613b6a7SJames Smart 
144d613b6a7SJames Smart 	lpfc_nlp_put(cmdwqe->context1);
145d613b6a7SJames Smart 	cmdwqe->context2 = NULL;
146d613b6a7SJames Smart 	cmdwqe->context3 = NULL;
147d613b6a7SJames Smart 	lpfc_sli_release_iocbq(phba, cmdwqe);
148d613b6a7SJames Smart 	rsp->done(rsp);
149d613b6a7SJames Smart 	kfree(ctxp);
150d613b6a7SJames Smart }
151d613b6a7SJames Smart 
152d613b6a7SJames Smart /**
1536c621a22SJames Smart  * lpfc_nvmet_ctxbuf_post - Repost a NVMET RQ DMA buffer and clean up context
154d613b6a7SJames Smart  * @phba: HBA buffer is associated with
155d613b6a7SJames Smart  * @ctxp: context to clean up
156d613b6a7SJames Smart  * @mp: Buffer to free
157d613b6a7SJames Smart  *
158d613b6a7SJames Smart  * Description: Frees the given DMA buffer in the appropriate way given by
159d613b6a7SJames Smart  * reposting it to its associated RQ so it can be reused.
160d613b6a7SJames Smart  *
161d613b6a7SJames Smart  * Notes: Takes phba->hbalock.  Can be called with or without other locks held.
162d613b6a7SJames Smart  *
163d613b6a7SJames Smart  * Returns: None
164d613b6a7SJames Smart  **/
165d613b6a7SJames Smart void
1666c621a22SJames Smart lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
167d613b6a7SJames Smart {
168eeeb51d8SJames Smart #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
1696c621a22SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp = ctx_buf->context;
170a8cf5dfeSJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
171a8cf5dfeSJames Smart 	struct fc_frame_header *fc_hdr;
172a8cf5dfeSJames Smart 	struct rqb_dmabuf *nvmebuf;
173a8cf5dfeSJames Smart 	uint32_t *payload;
174a8cf5dfeSJames Smart 	uint32_t size, oxid, sid, rc;
1756c621a22SJames Smart 	unsigned long iflag;
17686c67379SJames Smart 
177d613b6a7SJames Smart 	if (ctxp->txrdy) {
178771db5c0SRomain Perier 		dma_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
179d613b6a7SJames Smart 			      ctxp->txrdy_phys);
180d613b6a7SJames Smart 		ctxp->txrdy = NULL;
181d613b6a7SJames Smart 		ctxp->txrdy_phys = 0;
182d613b6a7SJames Smart 	}
183ce1b591cSJames Smart 
184ce1b591cSJames Smart 	if (ctxp->state == LPFC_NVMET_STE_FREE) {
185ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
186ce1b591cSJames Smart 				"6411 NVMET free, already free IO x%x: %d %d\n",
187ce1b591cSJames Smart 				ctxp->oxid, ctxp->state, ctxp->entry_cnt);
188ce1b591cSJames Smart 	}
189d613b6a7SJames Smart 	ctxp->state = LPFC_NVMET_STE_FREE;
1906c621a22SJames Smart 
191a8cf5dfeSJames Smart 	spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
192a8cf5dfeSJames Smart 	if (phba->sli4_hba.nvmet_io_wait_cnt) {
193a8cf5dfeSJames Smart 		list_remove_head(&phba->sli4_hba.lpfc_nvmet_io_wait_list,
194a8cf5dfeSJames Smart 				 nvmebuf, struct rqb_dmabuf,
195a8cf5dfeSJames Smart 				 hbuf.list);
196a8cf5dfeSJames Smart 		phba->sli4_hba.nvmet_io_wait_cnt--;
197a8cf5dfeSJames Smart 		spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
198a8cf5dfeSJames Smart 				       iflag);
199a8cf5dfeSJames Smart 
200a8cf5dfeSJames Smart 		fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
201a8cf5dfeSJames Smart 		oxid = be16_to_cpu(fc_hdr->fh_ox_id);
202a8cf5dfeSJames Smart 		tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
203a8cf5dfeSJames Smart 		payload = (uint32_t *)(nvmebuf->dbuf.virt);
204a8cf5dfeSJames Smart 		size = nvmebuf->bytes_recv;
205a8cf5dfeSJames Smart 		sid = sli4_sid_from_fc_hdr(fc_hdr);
206a8cf5dfeSJames Smart 
207a8cf5dfeSJames Smart 		ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
208a8cf5dfeSJames Smart 		ctxp->wqeq = NULL;
209a8cf5dfeSJames Smart 		ctxp->txrdy = NULL;
210a8cf5dfeSJames Smart 		ctxp->offset = 0;
211a8cf5dfeSJames Smart 		ctxp->phba = phba;
212a8cf5dfeSJames Smart 		ctxp->size = size;
213a8cf5dfeSJames Smart 		ctxp->oxid = oxid;
214a8cf5dfeSJames Smart 		ctxp->sid = sid;
215a8cf5dfeSJames Smart 		ctxp->state = LPFC_NVMET_STE_RCV;
216a8cf5dfeSJames Smart 		ctxp->entry_cnt = 1;
217a8cf5dfeSJames Smart 		ctxp->flag = 0;
218a8cf5dfeSJames Smart 		ctxp->ctxbuf = ctx_buf;
219a8cf5dfeSJames Smart 		spin_lock_init(&ctxp->ctxlock);
220a8cf5dfeSJames Smart 
221a8cf5dfeSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
222a8cf5dfeSJames Smart 		if (phba->ktime_on) {
223a8cf5dfeSJames Smart 			ctxp->ts_cmd_nvme = ktime_get_ns();
224a8cf5dfeSJames Smart 			ctxp->ts_isr_cmd = ctxp->ts_cmd_nvme;
225a8cf5dfeSJames Smart 			ctxp->ts_nvme_data = 0;
226a8cf5dfeSJames Smart 			ctxp->ts_data_wqput = 0;
227a8cf5dfeSJames Smart 			ctxp->ts_isr_data = 0;
228a8cf5dfeSJames Smart 			ctxp->ts_data_nvme = 0;
229a8cf5dfeSJames Smart 			ctxp->ts_nvme_status = 0;
230a8cf5dfeSJames Smart 			ctxp->ts_status_wqput = 0;
231a8cf5dfeSJames Smart 			ctxp->ts_isr_status = 0;
232a8cf5dfeSJames Smart 			ctxp->ts_status_nvme = 0;
233d613b6a7SJames Smart 		}
234a8cf5dfeSJames Smart #endif
235a8cf5dfeSJames Smart 		atomic_inc(&tgtp->rcv_fcp_cmd_in);
236a8cf5dfeSJames Smart 		/*
237a8cf5dfeSJames Smart 		 * The calling sequence should be:
238a8cf5dfeSJames Smart 		 * nvmet_fc_rcv_fcp_req->lpfc_nvmet_xmt_fcp_op/cmp- req->done
239a8cf5dfeSJames Smart 		 * lpfc_nvmet_xmt_fcp_op_cmp should free the allocated ctxp.
240a8cf5dfeSJames Smart 		 * When we return from nvmet_fc_rcv_fcp_req, all relevant info
241a8cf5dfeSJames Smart 		 * the NVME command / FC header is stored.
242a8cf5dfeSJames Smart 		 * A buffer has already been reposted for this IO, so just free
243a8cf5dfeSJames Smart 		 * the nvmebuf.
244a8cf5dfeSJames Smart 		 */
245a8cf5dfeSJames Smart 		rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
246a8cf5dfeSJames Smart 					  payload, size);
247a8cf5dfeSJames Smart 
248a8cf5dfeSJames Smart 		/* Process FCP command */
249a8cf5dfeSJames Smart 		if (rc == 0) {
250a8cf5dfeSJames Smart 			atomic_inc(&tgtp->rcv_fcp_cmd_out);
251a8cf5dfeSJames Smart 			nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
252a8cf5dfeSJames Smart 			return;
253a8cf5dfeSJames Smart 		}
254a8cf5dfeSJames Smart 
255a8cf5dfeSJames Smart 		atomic_inc(&tgtp->rcv_fcp_cmd_drop);
256a8cf5dfeSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
257a8cf5dfeSJames Smart 				"2582 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
258a8cf5dfeSJames Smart 				ctxp->oxid, rc,
259a8cf5dfeSJames Smart 				atomic_read(&tgtp->rcv_fcp_cmd_in),
260a8cf5dfeSJames Smart 				atomic_read(&tgtp->rcv_fcp_cmd_out),
261a8cf5dfeSJames Smart 				atomic_read(&tgtp->xmt_fcp_release));
262a8cf5dfeSJames Smart 
263a8cf5dfeSJames Smart 		lpfc_nvmet_defer_release(phba, ctxp);
264a8cf5dfeSJames Smart 		lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, sid, oxid);
265a8cf5dfeSJames Smart 		nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
266a8cf5dfeSJames Smart 		return;
267a8cf5dfeSJames Smart 	}
268a8cf5dfeSJames Smart 	spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
269a8cf5dfeSJames Smart 
270966bb5b7SJames Smart 	spin_lock_irqsave(&phba->sli4_hba.nvmet_ctx_put_lock, iflag);
2716c621a22SJames Smart 	list_add_tail(&ctx_buf->list,
272966bb5b7SJames Smart 		      &phba->sli4_hba.lpfc_nvmet_ctx_put_list);
273966bb5b7SJames Smart 	phba->sli4_hba.nvmet_ctx_put_cnt++;
274966bb5b7SJames Smart 	spin_unlock_irqrestore(&phba->sli4_hba.nvmet_ctx_put_lock, iflag);
275eeeb51d8SJames Smart #endif
276d613b6a7SJames Smart }
277d613b6a7SJames Smart 
2782b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
2792b65e182SJames Smart static void
2802b65e182SJames Smart lpfc_nvmet_ktime(struct lpfc_hba *phba,
2812b65e182SJames Smart 		 struct lpfc_nvmet_rcv_ctx *ctxp)
2822b65e182SJames Smart {
2832b65e182SJames Smart 	uint64_t seg1, seg2, seg3, seg4, seg5;
2842b65e182SJames Smart 	uint64_t seg6, seg7, seg8, seg9, seg10;
2852b65e182SJames Smart 
2862b65e182SJames Smart 	if (!phba->ktime_on)
2872b65e182SJames Smart 		return;
2882b65e182SJames Smart 
2892b65e182SJames Smart 	if (!ctxp->ts_isr_cmd || !ctxp->ts_cmd_nvme ||
2902b65e182SJames Smart 	    !ctxp->ts_nvme_data || !ctxp->ts_data_wqput ||
2912b65e182SJames Smart 	    !ctxp->ts_isr_data || !ctxp->ts_data_nvme ||
2922b65e182SJames Smart 	    !ctxp->ts_nvme_status || !ctxp->ts_status_wqput ||
2932b65e182SJames Smart 	    !ctxp->ts_isr_status || !ctxp->ts_status_nvme)
2942b65e182SJames Smart 		return;
2952b65e182SJames Smart 
2962b65e182SJames Smart 	if (ctxp->ts_isr_cmd  > ctxp->ts_cmd_nvme)
2972b65e182SJames Smart 		return;
2982b65e182SJames Smart 	if (ctxp->ts_cmd_nvme > ctxp->ts_nvme_data)
2992b65e182SJames Smart 		return;
3002b65e182SJames Smart 	if (ctxp->ts_nvme_data > ctxp->ts_data_wqput)
3012b65e182SJames Smart 		return;
3022b65e182SJames Smart 	if (ctxp->ts_data_wqput > ctxp->ts_isr_data)
3032b65e182SJames Smart 		return;
3042b65e182SJames Smart 	if (ctxp->ts_isr_data > ctxp->ts_data_nvme)
3052b65e182SJames Smart 		return;
3062b65e182SJames Smart 	if (ctxp->ts_data_nvme > ctxp->ts_nvme_status)
3072b65e182SJames Smart 		return;
3082b65e182SJames Smart 	if (ctxp->ts_nvme_status > ctxp->ts_status_wqput)
3092b65e182SJames Smart 		return;
3102b65e182SJames Smart 	if (ctxp->ts_status_wqput > ctxp->ts_isr_status)
3112b65e182SJames Smart 		return;
3122b65e182SJames Smart 	if (ctxp->ts_isr_status > ctxp->ts_status_nvme)
3132b65e182SJames Smart 		return;
3142b65e182SJames Smart 	/*
3152b65e182SJames Smart 	 * Segment 1 - Time from FCP command received by MSI-X ISR
3162b65e182SJames Smart 	 * to FCP command is passed to NVME Layer.
3172b65e182SJames Smart 	 * Segment 2 - Time from FCP command payload handed
3182b65e182SJames Smart 	 * off to NVME Layer to Driver receives a Command op
3192b65e182SJames Smart 	 * from NVME Layer.
3202b65e182SJames Smart 	 * Segment 3 - Time from Driver receives a Command op
3212b65e182SJames Smart 	 * from NVME Layer to Command is put on WQ.
3222b65e182SJames Smart 	 * Segment 4 - Time from Driver WQ put is done
3232b65e182SJames Smart 	 * to MSI-X ISR for Command cmpl.
3242b65e182SJames Smart 	 * Segment 5 - Time from MSI-X ISR for Command cmpl to
3252b65e182SJames Smart 	 * Command cmpl is passed to NVME Layer.
3262b65e182SJames Smart 	 * Segment 6 - Time from Command cmpl is passed to NVME
3272b65e182SJames Smart 	 * Layer to Driver receives a RSP op from NVME Layer.
3282b65e182SJames Smart 	 * Segment 7 - Time from Driver receives a RSP op from
3292b65e182SJames Smart 	 * NVME Layer to WQ put is done on TRSP FCP Status.
3302b65e182SJames Smart 	 * Segment 8 - Time from Driver WQ put is done on TRSP
3312b65e182SJames Smart 	 * FCP Status to MSI-X ISR for TRSP cmpl.
3322b65e182SJames Smart 	 * Segment 9 - Time from MSI-X ISR for TRSP cmpl to
3332b65e182SJames Smart 	 * TRSP cmpl is passed to NVME Layer.
3342b65e182SJames Smart 	 * Segment 10 - Time from FCP command received by
3352b65e182SJames Smart 	 * MSI-X ISR to command is completed on wire.
3362b65e182SJames Smart 	 * (Segments 1 thru 8) for READDATA / WRITEDATA
3372b65e182SJames Smart 	 * (Segments 1 thru 4) for READDATA_RSP
3382b65e182SJames Smart 	 */
3392b65e182SJames Smart 	seg1 = ctxp->ts_cmd_nvme - ctxp->ts_isr_cmd;
3402b65e182SJames Smart 	seg2 = (ctxp->ts_nvme_data - ctxp->ts_isr_cmd) - seg1;
3412b65e182SJames Smart 	seg3 = (ctxp->ts_data_wqput - ctxp->ts_isr_cmd) -
3422b65e182SJames Smart 		seg1 - seg2;
3432b65e182SJames Smart 	seg4 = (ctxp->ts_isr_data - ctxp->ts_isr_cmd) -
3442b65e182SJames Smart 		seg1 - seg2 - seg3;
3452b65e182SJames Smart 	seg5 = (ctxp->ts_data_nvme - ctxp->ts_isr_cmd) -
3462b65e182SJames Smart 		seg1 - seg2 - seg3 - seg4;
3472b65e182SJames Smart 
3482b65e182SJames Smart 	/* For auto rsp commands seg6 thru seg10 will be 0 */
3492b65e182SJames Smart 	if (ctxp->ts_nvme_status > ctxp->ts_data_nvme) {
3502b65e182SJames Smart 		seg6 = (ctxp->ts_nvme_status -
3512b65e182SJames Smart 			ctxp->ts_isr_cmd) -
3522b65e182SJames Smart 			seg1 - seg2 - seg3 - seg4 - seg5;
3532b65e182SJames Smart 		seg7 = (ctxp->ts_status_wqput -
3542b65e182SJames Smart 			ctxp->ts_isr_cmd) -
3552b65e182SJames Smart 			seg1 - seg2 - seg3 -
3562b65e182SJames Smart 			seg4 - seg5 - seg6;
3572b65e182SJames Smart 		seg8 = (ctxp->ts_isr_status -
3582b65e182SJames Smart 			ctxp->ts_isr_cmd) -
3592b65e182SJames Smart 			seg1 - seg2 - seg3 - seg4 -
3602b65e182SJames Smart 			seg5 - seg6 - seg7;
3612b65e182SJames Smart 		seg9 = (ctxp->ts_status_nvme -
3622b65e182SJames Smart 			ctxp->ts_isr_cmd) -
3632b65e182SJames Smart 			seg1 - seg2 - seg3 - seg4 -
3642b65e182SJames Smart 			seg5 - seg6 - seg7 - seg8;
3652b65e182SJames Smart 		seg10 = (ctxp->ts_isr_status -
3662b65e182SJames Smart 			ctxp->ts_isr_cmd);
3672b65e182SJames Smart 	} else {
3682b65e182SJames Smart 		seg6 =  0;
3692b65e182SJames Smart 		seg7 =  0;
3702b65e182SJames Smart 		seg8 =  0;
3712b65e182SJames Smart 		seg9 =  0;
3722b65e182SJames Smart 		seg10 = (ctxp->ts_isr_data - ctxp->ts_isr_cmd);
3732b65e182SJames Smart 	}
3742b65e182SJames Smart 
3752b65e182SJames Smart 	phba->ktime_seg1_total += seg1;
3762b65e182SJames Smart 	if (seg1 < phba->ktime_seg1_min)
3772b65e182SJames Smart 		phba->ktime_seg1_min = seg1;
3782b65e182SJames Smart 	else if (seg1 > phba->ktime_seg1_max)
3792b65e182SJames Smart 		phba->ktime_seg1_max = seg1;
3802b65e182SJames Smart 
3812b65e182SJames Smart 	phba->ktime_seg2_total += seg2;
3822b65e182SJames Smart 	if (seg2 < phba->ktime_seg2_min)
3832b65e182SJames Smart 		phba->ktime_seg2_min = seg2;
3842b65e182SJames Smart 	else if (seg2 > phba->ktime_seg2_max)
3852b65e182SJames Smart 		phba->ktime_seg2_max = seg2;
3862b65e182SJames Smart 
3872b65e182SJames Smart 	phba->ktime_seg3_total += seg3;
3882b65e182SJames Smart 	if (seg3 < phba->ktime_seg3_min)
3892b65e182SJames Smart 		phba->ktime_seg3_min = seg3;
3902b65e182SJames Smart 	else if (seg3 > phba->ktime_seg3_max)
3912b65e182SJames Smart 		phba->ktime_seg3_max = seg3;
3922b65e182SJames Smart 
3932b65e182SJames Smart 	phba->ktime_seg4_total += seg4;
3942b65e182SJames Smart 	if (seg4 < phba->ktime_seg4_min)
3952b65e182SJames Smart 		phba->ktime_seg4_min = seg4;
3962b65e182SJames Smart 	else if (seg4 > phba->ktime_seg4_max)
3972b65e182SJames Smart 		phba->ktime_seg4_max = seg4;
3982b65e182SJames Smart 
3992b65e182SJames Smart 	phba->ktime_seg5_total += seg5;
4002b65e182SJames Smart 	if (seg5 < phba->ktime_seg5_min)
4012b65e182SJames Smart 		phba->ktime_seg5_min = seg5;
4022b65e182SJames Smart 	else if (seg5 > phba->ktime_seg5_max)
4032b65e182SJames Smart 		phba->ktime_seg5_max = seg5;
4042b65e182SJames Smart 
4052b65e182SJames Smart 	phba->ktime_data_samples++;
4062b65e182SJames Smart 	if (!seg6)
4072b65e182SJames Smart 		goto out;
4082b65e182SJames Smart 
4092b65e182SJames Smart 	phba->ktime_seg6_total += seg6;
4102b65e182SJames Smart 	if (seg6 < phba->ktime_seg6_min)
4112b65e182SJames Smart 		phba->ktime_seg6_min = seg6;
4122b65e182SJames Smart 	else if (seg6 > phba->ktime_seg6_max)
4132b65e182SJames Smart 		phba->ktime_seg6_max = seg6;
4142b65e182SJames Smart 
4152b65e182SJames Smart 	phba->ktime_seg7_total += seg7;
4162b65e182SJames Smart 	if (seg7 < phba->ktime_seg7_min)
4172b65e182SJames Smart 		phba->ktime_seg7_min = seg7;
4182b65e182SJames Smart 	else if (seg7 > phba->ktime_seg7_max)
4192b65e182SJames Smart 		phba->ktime_seg7_max = seg7;
4202b65e182SJames Smart 
4212b65e182SJames Smart 	phba->ktime_seg8_total += seg8;
4222b65e182SJames Smart 	if (seg8 < phba->ktime_seg8_min)
4232b65e182SJames Smart 		phba->ktime_seg8_min = seg8;
4242b65e182SJames Smart 	else if (seg8 > phba->ktime_seg8_max)
4252b65e182SJames Smart 		phba->ktime_seg8_max = seg8;
4262b65e182SJames Smart 
4272b65e182SJames Smart 	phba->ktime_seg9_total += seg9;
4282b65e182SJames Smart 	if (seg9 < phba->ktime_seg9_min)
4292b65e182SJames Smart 		phba->ktime_seg9_min = seg9;
4302b65e182SJames Smart 	else if (seg9 > phba->ktime_seg9_max)
4312b65e182SJames Smart 		phba->ktime_seg9_max = seg9;
4322b65e182SJames Smart out:
4332b65e182SJames Smart 	phba->ktime_seg10_total += seg10;
4342b65e182SJames Smart 	if (seg10 < phba->ktime_seg10_min)
4352b65e182SJames Smart 		phba->ktime_seg10_min = seg10;
4362b65e182SJames Smart 	else if (seg10 > phba->ktime_seg10_max)
4372b65e182SJames Smart 		phba->ktime_seg10_max = seg10;
4382b65e182SJames Smart 	phba->ktime_status_samples++;
4392b65e182SJames Smart }
4402b65e182SJames Smart #endif
4412b65e182SJames Smart 
442d613b6a7SJames Smart /**
443d613b6a7SJames Smart  * lpfc_nvmet_xmt_fcp_op_cmp - Completion handler for FCP Response
444d613b6a7SJames Smart  * @phba: Pointer to HBA context object.
445d613b6a7SJames Smart  * @cmdwqe: Pointer to driver command WQE object.
446d613b6a7SJames Smart  * @wcqe: Pointer to driver response CQE object.
447d613b6a7SJames Smart  *
448d613b6a7SJames Smart  * The function is called from SLI ring event handler with no
449d613b6a7SJames Smart  * lock held. This function is the completion handler for NVME FCP commands
450d613b6a7SJames Smart  * The function frees memory resources used for the NVME commands.
451d613b6a7SJames Smart  **/
452d613b6a7SJames Smart static void
453d613b6a7SJames Smart lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
454d613b6a7SJames Smart 			  struct lpfc_wcqe_complete *wcqe)
455d613b6a7SJames Smart {
456d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
457d613b6a7SJames Smart 	struct nvmefc_tgt_fcp_req *rsp;
458d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
459d613b6a7SJames Smart 	uint32_t status, result, op, start_clean;
4602b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
4612b65e182SJames Smart 	uint32_t id;
4622b65e182SJames Smart #endif
463d613b6a7SJames Smart 
464d613b6a7SJames Smart 	ctxp = cmdwqe->context2;
46586c67379SJames Smart 	ctxp->flag &= ~LPFC_NVMET_IO_INP;
46686c67379SJames Smart 
467d613b6a7SJames Smart 	rsp = &ctxp->ctx.fcp_req;
468d613b6a7SJames Smart 	op = rsp->op;
469d613b6a7SJames Smart 
470d613b6a7SJames Smart 	status = bf_get(lpfc_wcqe_c_status, wcqe);
471d613b6a7SJames Smart 	result = wcqe->parameter;
472d613b6a7SJames Smart 
47386c67379SJames Smart 	if (phba->targetport)
47486c67379SJames Smart 		tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
47586c67379SJames Smart 	else
47686c67379SJames Smart 		tgtp = NULL;
477d613b6a7SJames Smart 
4782b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET FCP CMPL: xri x%x op x%x status x%x\n",
4792b65e182SJames Smart 			 ctxp->oxid, op, status);
4802b65e182SJames Smart 
481d613b6a7SJames Smart 	if (status) {
482d613b6a7SJames Smart 		rsp->fcp_error = NVME_SC_DATA_XFER_ERROR;
483d613b6a7SJames Smart 		rsp->transferred_length = 0;
48486c67379SJames Smart 		if (tgtp)
485d613b6a7SJames Smart 			atomic_inc(&tgtp->xmt_fcp_rsp_error);
48686c67379SJames Smart 
48786c67379SJames Smart 		/* pick up SLI4 exhange busy condition */
48886c67379SJames Smart 		if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
48986c67379SJames Smart 			ctxp->flag |= LPFC_NVMET_XBUSY;
49086c67379SJames Smart 
49186c67379SJames Smart 			lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
49286c67379SJames Smart 					"6315 IO Cmpl XBUSY: xri x%x: %x/%x\n",
49386c67379SJames Smart 					ctxp->oxid, status, result);
49486c67379SJames Smart 		} else {
49586c67379SJames Smart 			ctxp->flag &= ~LPFC_NVMET_XBUSY;
49686c67379SJames Smart 		}
49786c67379SJames Smart 
498d613b6a7SJames Smart 	} else {
499d613b6a7SJames Smart 		rsp->fcp_error = NVME_SC_SUCCESS;
500d613b6a7SJames Smart 		if (op == NVMET_FCOP_RSP)
501d613b6a7SJames Smart 			rsp->transferred_length = rsp->rsplen;
502d613b6a7SJames Smart 		else
503d613b6a7SJames Smart 			rsp->transferred_length = rsp->transfer_length;
50486c67379SJames Smart 		if (tgtp)
505d613b6a7SJames Smart 			atomic_inc(&tgtp->xmt_fcp_rsp_cmpl);
506d613b6a7SJames Smart 	}
507d613b6a7SJames Smart 
508d613b6a7SJames Smart 	if ((op == NVMET_FCOP_READDATA_RSP) ||
509d613b6a7SJames Smart 	    (op == NVMET_FCOP_RSP)) {
510d613b6a7SJames Smart 		/* Sanity check */
511d613b6a7SJames Smart 		ctxp->state = LPFC_NVMET_STE_DONE;
512d613b6a7SJames Smart 		ctxp->entry_cnt++;
51386c67379SJames Smart 
5142b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5152b65e182SJames Smart 		if (phba->ktime_on) {
5162b65e182SJames Smart 			if (rsp->op == NVMET_FCOP_READDATA_RSP) {
5172b65e182SJames Smart 				ctxp->ts_isr_data =
5182b65e182SJames Smart 					cmdwqe->isr_timestamp;
5192b65e182SJames Smart 				ctxp->ts_data_nvme =
5202b65e182SJames Smart 					ktime_get_ns();
5212b65e182SJames Smart 				ctxp->ts_nvme_status =
5222b65e182SJames Smart 					ctxp->ts_data_nvme;
5232b65e182SJames Smart 				ctxp->ts_status_wqput =
5242b65e182SJames Smart 					ctxp->ts_data_nvme;
5252b65e182SJames Smart 				ctxp->ts_isr_status =
5262b65e182SJames Smart 					ctxp->ts_data_nvme;
5272b65e182SJames Smart 				ctxp->ts_status_nvme =
5282b65e182SJames Smart 					ctxp->ts_data_nvme;
5292b65e182SJames Smart 			} else {
5302b65e182SJames Smart 				ctxp->ts_isr_status =
5312b65e182SJames Smart 					cmdwqe->isr_timestamp;
5322b65e182SJames Smart 				ctxp->ts_status_nvme =
5332b65e182SJames Smart 					ktime_get_ns();
5342b65e182SJames Smart 			}
5352b65e182SJames Smart 		}
5362b65e182SJames Smart 		if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) {
5372b65e182SJames Smart 			id = smp_processor_id();
5382b65e182SJames Smart 			if (ctxp->cpu != id)
5392b65e182SJames Smart 				lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
5402b65e182SJames Smart 						"6703 CPU Check cmpl: "
5412b65e182SJames Smart 						"cpu %d expect %d\n",
5422b65e182SJames Smart 						id, ctxp->cpu);
5432b65e182SJames Smart 			if (ctxp->cpu < LPFC_CHECK_CPU_CNT)
5442b65e182SJames Smart 				phba->cpucheck_cmpl_io[id]++;
5452b65e182SJames Smart 		}
5462b65e182SJames Smart #endif
547d613b6a7SJames Smart 		rsp->done(rsp);
5482b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5492b65e182SJames Smart 		if (phba->ktime_on)
5502b65e182SJames Smart 			lpfc_nvmet_ktime(phba, ctxp);
5512b65e182SJames Smart #endif
55219b58d94SJames Smart 		/* lpfc_nvmet_xmt_fcp_release() will recycle the context */
553d613b6a7SJames Smart 	} else {
554d613b6a7SJames Smart 		ctxp->entry_cnt++;
555d613b6a7SJames Smart 		start_clean = offsetof(struct lpfc_iocbq, wqe);
556d613b6a7SJames Smart 		memset(((char *)cmdwqe) + start_clean, 0,
557d613b6a7SJames Smart 		       (sizeof(struct lpfc_iocbq) - start_clean));
5582b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5592b65e182SJames Smart 		if (phba->ktime_on) {
5602b65e182SJames Smart 			ctxp->ts_isr_data = cmdwqe->isr_timestamp;
5612b65e182SJames Smart 			ctxp->ts_data_nvme = ktime_get_ns();
5622b65e182SJames Smart 		}
5632b65e182SJames Smart 		if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) {
5642b65e182SJames Smart 			id = smp_processor_id();
5652b65e182SJames Smart 			if (ctxp->cpu != id)
5662b65e182SJames Smart 				lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
5672b65e182SJames Smart 						"6704 CPU Check cmdcmpl: "
5682b65e182SJames Smart 						"cpu %d expect %d\n",
5692b65e182SJames Smart 						id, ctxp->cpu);
5702b65e182SJames Smart 			if (ctxp->cpu < LPFC_CHECK_CPU_CNT)
5712b65e182SJames Smart 				phba->cpucheck_ccmpl_io[id]++;
5722b65e182SJames Smart 		}
5732b65e182SJames Smart #endif
574d613b6a7SJames Smart 		rsp->done(rsp);
575d613b6a7SJames Smart 	}
576d613b6a7SJames Smart }
577d613b6a7SJames Smart 
578d613b6a7SJames Smart static int
579d613b6a7SJames Smart lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
580d613b6a7SJames Smart 		      struct nvmefc_tgt_ls_req *rsp)
581d613b6a7SJames Smart {
582d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp =
583d613b6a7SJames Smart 		container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.ls_req);
584d613b6a7SJames Smart 	struct lpfc_hba *phba = ctxp->phba;
585d613b6a7SJames Smart 	struct hbq_dmabuf *nvmebuf =
586d613b6a7SJames Smart 		(struct hbq_dmabuf *)ctxp->rqb_buffer;
587d613b6a7SJames Smart 	struct lpfc_iocbq *nvmewqeq;
588d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *nvmep = tgtport->private;
589d613b6a7SJames Smart 	struct lpfc_dmabuf dmabuf;
590d613b6a7SJames Smart 	struct ulp_bde64 bpl;
591d613b6a7SJames Smart 	int rc;
592d613b6a7SJames Smart 
593d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
594ce1b591cSJames Smart 			"6023 NVMET LS rsp oxid x%x\n", ctxp->oxid);
595ce1b591cSJames Smart 
596ce1b591cSJames Smart 	if ((ctxp->state != LPFC_NVMET_STE_LS_RCV) ||
597ce1b591cSJames Smart 	    (ctxp->entry_cnt != 1)) {
598ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
599ce1b591cSJames Smart 				"6412 NVMET LS rsp state mismatch "
600ce1b591cSJames Smart 				"oxid x%x: %d %d\n",
601ce1b591cSJames Smart 				ctxp->oxid, ctxp->state, ctxp->entry_cnt);
602ce1b591cSJames Smart 	}
603ce1b591cSJames Smart 	ctxp->state = LPFC_NVMET_STE_LS_RSP;
604ce1b591cSJames Smart 	ctxp->entry_cnt++;
605d613b6a7SJames Smart 
606d613b6a7SJames Smart 	nvmewqeq = lpfc_nvmet_prep_ls_wqe(phba, ctxp, rsp->rspdma,
607d613b6a7SJames Smart 				      rsp->rsplen);
608d613b6a7SJames Smart 	if (nvmewqeq == NULL) {
609d613b6a7SJames Smart 		atomic_inc(&nvmep->xmt_ls_drop);
610d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
611d613b6a7SJames Smart 				"6150 LS Drop IO x%x: Prep\n",
612d613b6a7SJames Smart 				ctxp->oxid);
613d613b6a7SJames Smart 		lpfc_in_buf_free(phba, &nvmebuf->dbuf);
614547077a4SJames Smart 		atomic_inc(&nvmep->xmt_ls_abort);
615d613b6a7SJames Smart 		lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp,
616d613b6a7SJames Smart 						ctxp->sid, ctxp->oxid);
617d613b6a7SJames Smart 		return -ENOMEM;
618d613b6a7SJames Smart 	}
619d613b6a7SJames Smart 
620d613b6a7SJames Smart 	/* Save numBdes for bpl2sgl */
621d613b6a7SJames Smart 	nvmewqeq->rsvd2 = 1;
622d613b6a7SJames Smart 	nvmewqeq->hba_wqidx = 0;
623d613b6a7SJames Smart 	nvmewqeq->context3 = &dmabuf;
624d613b6a7SJames Smart 	dmabuf.virt = &bpl;
625d613b6a7SJames Smart 	bpl.addrLow = nvmewqeq->wqe.xmit_sequence.bde.addrLow;
626d613b6a7SJames Smart 	bpl.addrHigh = nvmewqeq->wqe.xmit_sequence.bde.addrHigh;
627d613b6a7SJames Smart 	bpl.tus.f.bdeSize = rsp->rsplen;
628d613b6a7SJames Smart 	bpl.tus.f.bdeFlags = 0;
629d613b6a7SJames Smart 	bpl.tus.w = le32_to_cpu(bpl.tus.w);
630d613b6a7SJames Smart 
631d613b6a7SJames Smart 	nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_rsp_cmp;
632d613b6a7SJames Smart 	nvmewqeq->iocb_cmpl = NULL;
633d613b6a7SJames Smart 	nvmewqeq->context2 = ctxp;
634d613b6a7SJames Smart 
6352b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET LS  RESP: xri x%x wqidx x%x len x%x\n",
6362b65e182SJames Smart 			 ctxp->oxid, nvmewqeq->hba_wqidx, rsp->rsplen);
6372b65e182SJames Smart 
638d613b6a7SJames Smart 	rc = lpfc_sli4_issue_wqe(phba, LPFC_ELS_RING, nvmewqeq);
639d613b6a7SJames Smart 	if (rc == WQE_SUCCESS) {
640d613b6a7SJames Smart 		/*
641d613b6a7SJames Smart 		 * Okay to repost buffer here, but wait till cmpl
642d613b6a7SJames Smart 		 * before freeing ctxp and iocbq.
643d613b6a7SJames Smart 		 */
644d613b6a7SJames Smart 		lpfc_in_buf_free(phba, &nvmebuf->dbuf);
645d613b6a7SJames Smart 		ctxp->rqb_buffer = 0;
646d613b6a7SJames Smart 		atomic_inc(&nvmep->xmt_ls_rsp);
647d613b6a7SJames Smart 		return 0;
648d613b6a7SJames Smart 	}
649d613b6a7SJames Smart 	/* Give back resources */
650d613b6a7SJames Smart 	atomic_inc(&nvmep->xmt_ls_drop);
651d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
652d613b6a7SJames Smart 			"6151 LS Drop IO x%x: Issue %d\n",
653d613b6a7SJames Smart 			ctxp->oxid, rc);
654d613b6a7SJames Smart 
655d613b6a7SJames Smart 	lpfc_nlp_put(nvmewqeq->context1);
656d613b6a7SJames Smart 
657d613b6a7SJames Smart 	lpfc_in_buf_free(phba, &nvmebuf->dbuf);
658547077a4SJames Smart 	atomic_inc(&nvmep->xmt_ls_abort);
659d613b6a7SJames Smart 	lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, ctxp->sid, ctxp->oxid);
660d613b6a7SJames Smart 	return -ENXIO;
661d613b6a7SJames Smart }
662d613b6a7SJames Smart 
663d613b6a7SJames Smart static int
664d613b6a7SJames Smart lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
665d613b6a7SJames Smart 		      struct nvmefc_tgt_fcp_req *rsp)
666d613b6a7SJames Smart {
667d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
668d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp =
669d613b6a7SJames Smart 		container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
670d613b6a7SJames Smart 	struct lpfc_hba *phba = ctxp->phba;
671d613b6a7SJames Smart 	struct lpfc_iocbq *nvmewqeq;
672223b78eaSArnd Bergmann 	int rc;
6732b65e182SJames Smart 
6742b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
6752b65e182SJames Smart 	if (phba->ktime_on) {
6762b65e182SJames Smart 		if (rsp->op == NVMET_FCOP_RSP)
6772b65e182SJames Smart 			ctxp->ts_nvme_status = ktime_get_ns();
6782b65e182SJames Smart 		else
6792b65e182SJames Smart 			ctxp->ts_nvme_data = ktime_get_ns();
6802b65e182SJames Smart 	}
6812b65e182SJames Smart 	if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) {
682223b78eaSArnd Bergmann 		int id = smp_processor_id();
6832b65e182SJames Smart 		ctxp->cpu = id;
6842b65e182SJames Smart 		if (id < LPFC_CHECK_CPU_CNT)
6852b65e182SJames Smart 			phba->cpucheck_xmt_io[id]++;
6862b65e182SJames Smart 		if (rsp->hwqid != id) {
6872b65e182SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
6882b65e182SJames Smart 					"6705 CPU Check OP: "
6892b65e182SJames Smart 					"cpu %d expect %d\n",
6902b65e182SJames Smart 					id, rsp->hwqid);
6912b65e182SJames Smart 			ctxp->cpu = rsp->hwqid;
6922b65e182SJames Smart 		}
6932b65e182SJames Smart 	}
6942b65e182SJames Smart #endif
695d613b6a7SJames Smart 
696d613b6a7SJames Smart 	/* Sanity check */
69786c67379SJames Smart 	if ((ctxp->flag & LPFC_NVMET_ABTS_RCV) ||
69886c67379SJames Smart 	    (ctxp->state == LPFC_NVMET_STE_ABORT)) {
699d613b6a7SJames Smart 		atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
700d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
70186c67379SJames Smart 				"6102 IO xri x%x aborted\n",
702d613b6a7SJames Smart 				ctxp->oxid);
703a5068b46SJames Smart 		rc = -ENXIO;
704d613b6a7SJames Smart 		goto aerr;
705d613b6a7SJames Smart 	}
706d613b6a7SJames Smart 
707d613b6a7SJames Smart 	nvmewqeq = lpfc_nvmet_prep_fcp_wqe(phba, ctxp);
708d613b6a7SJames Smart 	if (nvmewqeq == NULL) {
709d613b6a7SJames Smart 		atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
710d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
711d613b6a7SJames Smart 				"6152 FCP Drop IO x%x: Prep\n",
712d613b6a7SJames Smart 				ctxp->oxid);
713a5068b46SJames Smart 		rc = -ENXIO;
714d613b6a7SJames Smart 		goto aerr;
715d613b6a7SJames Smart 	}
716d613b6a7SJames Smart 
717d613b6a7SJames Smart 	nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_fcp_op_cmp;
718d613b6a7SJames Smart 	nvmewqeq->iocb_cmpl = NULL;
719d613b6a7SJames Smart 	nvmewqeq->context2 = ctxp;
720d613b6a7SJames Smart 	nvmewqeq->iocb_flag |=  LPFC_IO_NVMET;
721d613b6a7SJames Smart 	ctxp->wqeq->hba_wqidx = rsp->hwqid;
722d613b6a7SJames Smart 
7232b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n",
7242b65e182SJames Smart 			 ctxp->oxid, rsp->op, rsp->rsplen);
7252b65e182SJames Smart 
72661f3d4bfSJames Smart 	ctxp->flag |= LPFC_NVMET_IO_INP;
727d613b6a7SJames Smart 	rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, nvmewqeq);
728d613b6a7SJames Smart 	if (rc == WQE_SUCCESS) {
7292b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
7302b65e182SJames Smart 		if (!phba->ktime_on)
7312b65e182SJames Smart 			return 0;
7322b65e182SJames Smart 		if (rsp->op == NVMET_FCOP_RSP)
7332b65e182SJames Smart 			ctxp->ts_status_wqput = ktime_get_ns();
7342b65e182SJames Smart 		else
7352b65e182SJames Smart 			ctxp->ts_data_wqput = ktime_get_ns();
7362b65e182SJames Smart #endif
737d613b6a7SJames Smart 		return 0;
738d613b6a7SJames Smart 	}
739d613b6a7SJames Smart 
740d613b6a7SJames Smart 	/* Give back resources */
741d613b6a7SJames Smart 	atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
742d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
743d613b6a7SJames Smart 			"6153 FCP Drop IO x%x: Issue: %d\n",
744d613b6a7SJames Smart 			ctxp->oxid, rc);
745d613b6a7SJames Smart 
746d613b6a7SJames Smart 	ctxp->wqeq->hba_wqidx = 0;
747d613b6a7SJames Smart 	nvmewqeq->context2 = NULL;
748d613b6a7SJames Smart 	nvmewqeq->context3 = NULL;
749a5068b46SJames Smart 	rc = -EBUSY;
750d613b6a7SJames Smart aerr:
751a5068b46SJames Smart 	return rc;
752d613b6a7SJames Smart }
753d613b6a7SJames Smart 
754d613b6a7SJames Smart static void
755d613b6a7SJames Smart lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
756d613b6a7SJames Smart {
757d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tport = targetport->private;
758d613b6a7SJames Smart 
759d613b6a7SJames Smart 	/* release any threads waiting for the unreg to complete */
760d613b6a7SJames Smart 	complete(&tport->tport_unreg_done);
761d613b6a7SJames Smart }
762d613b6a7SJames Smart 
76319b58d94SJames Smart static void
764a97ec51bSJames Smart lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport,
765a97ec51bSJames Smart 			 struct nvmefc_tgt_fcp_req *req)
766a97ec51bSJames Smart {
767a97ec51bSJames Smart 	struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
768a97ec51bSJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp =
769a97ec51bSJames Smart 		container_of(req, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
770a97ec51bSJames Smart 	struct lpfc_hba *phba = ctxp->phba;
77186c67379SJames Smart 	unsigned long flags;
772a97ec51bSJames Smart 
773a97ec51bSJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
774ce1b591cSJames Smart 			"6103 NVMET Abort op: oxri x%x flg x%x ste %d\n",
775ce1b591cSJames Smart 			ctxp->oxid, ctxp->flag, ctxp->state);
776a97ec51bSJames Smart 
777ce1b591cSJames Smart 	lpfc_nvmeio_data(phba, "NVMET FCP ABRT: xri x%x flg x%x ste x%x\n",
778ce1b591cSJames Smart 			 ctxp->oxid, ctxp->flag, ctxp->state);
779a97ec51bSJames Smart 
780a97ec51bSJames Smart 	atomic_inc(&lpfc_nvmep->xmt_fcp_abort);
781ce1b591cSJames Smart 
78286c67379SJames Smart 	spin_lock_irqsave(&ctxp->ctxlock, flags);
78386c67379SJames Smart 
78486c67379SJames Smart 	/* Since iaab/iaar are NOT set, we need to check
78586c67379SJames Smart 	 * if the firmware is in process of aborting IO
78686c67379SJames Smart 	 */
78786c67379SJames Smart 	if (ctxp->flag & LPFC_NVMET_XBUSY) {
78886c67379SJames Smart 		spin_unlock_irqrestore(&ctxp->ctxlock, flags);
78986c67379SJames Smart 		return;
79086c67379SJames Smart 	}
791a97ec51bSJames Smart 	ctxp->flag |= LPFC_NVMET_ABORT_OP;
792ce1b591cSJames Smart 
793ce1b591cSJames Smart 	/* An state of LPFC_NVMET_STE_RCV means we have just received
794ce1b591cSJames Smart 	 * the NVME command and have not started processing it.
795ce1b591cSJames Smart 	 * (by issuing any IO WQEs on this exchange yet)
796ce1b591cSJames Smart 	 */
797ce1b591cSJames Smart 	if (ctxp->state == LPFC_NVMET_STE_RCV)
798ce1b591cSJames Smart 		lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid,
799a97ec51bSJames Smart 						 ctxp->oxid);
800a97ec51bSJames Smart 	else
801ce1b591cSJames Smart 		lpfc_nvmet_sol_fcp_issue_abort(phba, ctxp, ctxp->sid,
802a97ec51bSJames Smart 					       ctxp->oxid);
80386c67379SJames Smart 	spin_unlock_irqrestore(&ctxp->ctxlock, flags);
804a97ec51bSJames Smart }
805a97ec51bSJames Smart 
806a97ec51bSJames Smart static void
80719b58d94SJames Smart lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
80819b58d94SJames Smart 			   struct nvmefc_tgt_fcp_req *rsp)
80919b58d94SJames Smart {
810547077a4SJames Smart 	struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
81119b58d94SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp =
81219b58d94SJames Smart 		container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
81319b58d94SJames Smart 	struct lpfc_hba *phba = ctxp->phba;
81419b58d94SJames Smart 	unsigned long flags;
81519b58d94SJames Smart 	bool aborting = false;
81619b58d94SJames Smart 
817ce1b591cSJames Smart 	if (ctxp->state != LPFC_NVMET_STE_DONE &&
818ce1b591cSJames Smart 	    ctxp->state != LPFC_NVMET_STE_ABORT) {
819ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
820ce1b591cSJames Smart 				"6413 NVMET release bad state %d %d oxid x%x\n",
821ce1b591cSJames Smart 				ctxp->state, ctxp->entry_cnt, ctxp->oxid);
822ce1b591cSJames Smart 	}
823ce1b591cSJames Smart 
82419b58d94SJames Smart 	spin_lock_irqsave(&ctxp->ctxlock, flags);
82586c67379SJames Smart 	if ((ctxp->flag & LPFC_NVMET_ABORT_OP) ||
82686c67379SJames Smart 	    (ctxp->flag & LPFC_NVMET_XBUSY)) {
82719b58d94SJames Smart 		aborting = true;
82886c67379SJames Smart 		/* let the abort path do the real release */
82986c67379SJames Smart 		lpfc_nvmet_defer_release(phba, ctxp);
83019b58d94SJames Smart 	}
83119b58d94SJames Smart 	spin_unlock_irqrestore(&ctxp->ctxlock, flags);
83219b58d94SJames Smart 
8339094367aSArnd Bergmann 	lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d abt %d\n", ctxp->oxid,
8349094367aSArnd Bergmann 			 ctxp->state, aborting);
83519b58d94SJames Smart 
836547077a4SJames Smart 	atomic_inc(&lpfc_nvmep->xmt_fcp_release);
837547077a4SJames Smart 
83886c67379SJames Smart 	if (aborting)
83986c67379SJames Smart 		return;
84086c67379SJames Smart 
8416c621a22SJames Smart 	lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
84219b58d94SJames Smart }
84319b58d94SJames Smart 
844d613b6a7SJames Smart static struct nvmet_fc_target_template lpfc_tgttemplate = {
845d613b6a7SJames Smart 	.targetport_delete = lpfc_nvmet_targetport_delete,
846d613b6a7SJames Smart 	.xmt_ls_rsp     = lpfc_nvmet_xmt_ls_rsp,
847d613b6a7SJames Smart 	.fcp_op         = lpfc_nvmet_xmt_fcp_op,
848a97ec51bSJames Smart 	.fcp_abort      = lpfc_nvmet_xmt_fcp_abort,
84919b58d94SJames Smart 	.fcp_req_release = lpfc_nvmet_xmt_fcp_release,
850d613b6a7SJames Smart 
851d613b6a7SJames Smart 	.max_hw_queues  = 1,
852d613b6a7SJames Smart 	.max_sgl_segments = LPFC_NVMET_DEFAULT_SEGS,
853d613b6a7SJames Smart 	.max_dif_sgl_segments = LPFC_NVMET_DEFAULT_SEGS,
854d613b6a7SJames Smart 	.dma_boundary = 0xFFFFFFFF,
855d613b6a7SJames Smart 
856d613b6a7SJames Smart 	/* optional features */
857d613b6a7SJames Smart 	.target_features = 0,
858d613b6a7SJames Smart 	/* sizes of additional private data for data structures */
859d613b6a7SJames Smart 	.target_priv_sz = sizeof(struct lpfc_nvmet_tgtport),
860d613b6a7SJames Smart };
861d613b6a7SJames Smart 
86239aa23f9SColin Ian King static void
8636c621a22SJames Smart lpfc_nvmet_cleanup_io_context(struct lpfc_hba *phba)
8646c621a22SJames Smart {
8656c621a22SJames Smart 	struct lpfc_nvmet_ctxbuf *ctx_buf, *next_ctx_buf;
8666c621a22SJames Smart 	unsigned long flags;
8676c621a22SJames Smart 
868966bb5b7SJames Smart 	spin_lock_irqsave(&phba->sli4_hba.nvmet_ctx_get_lock, flags);
869c4031db7SDan Carpenter 	spin_lock(&phba->sli4_hba.nvmet_ctx_put_lock);
870966bb5b7SJames Smart 	list_for_each_entry_safe(ctx_buf, next_ctx_buf,
871966bb5b7SJames Smart 			&phba->sli4_hba.lpfc_nvmet_ctx_get_list, list) {
872c4031db7SDan Carpenter 		spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock);
8736c621a22SJames Smart 		list_del_init(&ctx_buf->list);
874c4031db7SDan Carpenter 		spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
8756c621a22SJames Smart 		__lpfc_clear_active_sglq(phba,
8766c621a22SJames Smart 					 ctx_buf->sglq->sli4_lxritag);
8776c621a22SJames Smart 		ctx_buf->sglq->state = SGL_FREED;
8786c621a22SJames Smart 		ctx_buf->sglq->ndlp = NULL;
8796c621a22SJames Smart 
880c4031db7SDan Carpenter 		spin_lock(&phba->sli4_hba.sgl_list_lock);
8816c621a22SJames Smart 		list_add_tail(&ctx_buf->sglq->list,
8826c621a22SJames Smart 			      &phba->sli4_hba.lpfc_nvmet_sgl_list);
883c4031db7SDan Carpenter 		spin_unlock(&phba->sli4_hba.sgl_list_lock);
8846c621a22SJames Smart 
8856c621a22SJames Smart 		lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
8866c621a22SJames Smart 		kfree(ctx_buf->context);
8876c621a22SJames Smart 	}
888966bb5b7SJames Smart 	list_for_each_entry_safe(ctx_buf, next_ctx_buf,
889966bb5b7SJames Smart 			&phba->sli4_hba.lpfc_nvmet_ctx_put_list, list) {
890c4031db7SDan Carpenter 		spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock);
891966bb5b7SJames Smart 		list_del_init(&ctx_buf->list);
892c4031db7SDan Carpenter 		spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
893966bb5b7SJames Smart 		__lpfc_clear_active_sglq(phba,
894966bb5b7SJames Smart 					 ctx_buf->sglq->sli4_lxritag);
895966bb5b7SJames Smart 		ctx_buf->sglq->state = SGL_FREED;
896966bb5b7SJames Smart 		ctx_buf->sglq->ndlp = NULL;
897966bb5b7SJames Smart 
898c4031db7SDan Carpenter 		spin_lock(&phba->sli4_hba.sgl_list_lock);
899966bb5b7SJames Smart 		list_add_tail(&ctx_buf->sglq->list,
900966bb5b7SJames Smart 			      &phba->sli4_hba.lpfc_nvmet_sgl_list);
901c4031db7SDan Carpenter 		spin_unlock(&phba->sli4_hba.sgl_list_lock);
902966bb5b7SJames Smart 
903966bb5b7SJames Smart 		lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
904966bb5b7SJames Smart 		kfree(ctx_buf->context);
905966bb5b7SJames Smart 	}
906c4031db7SDan Carpenter 	spin_unlock(&phba->sli4_hba.nvmet_ctx_put_lock);
907966bb5b7SJames Smart 	spin_unlock_irqrestore(&phba->sli4_hba.nvmet_ctx_get_lock, flags);
9086c621a22SJames Smart }
9096c621a22SJames Smart 
91039aa23f9SColin Ian King static int
9116c621a22SJames Smart lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
9126c621a22SJames Smart {
9136c621a22SJames Smart 	struct lpfc_nvmet_ctxbuf *ctx_buf;
9146c621a22SJames Smart 	struct lpfc_iocbq *nvmewqe;
9156c621a22SJames Smart 	union lpfc_wqe128 *wqe;
9166c621a22SJames Smart 	int i;
9176c621a22SJames Smart 
9186c621a22SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME,
9196c621a22SJames Smart 			"6403 Allocate NVMET resources for %d XRIs\n",
9206c621a22SJames Smart 			phba->sli4_hba.nvmet_xri_cnt);
9216c621a22SJames Smart 
9226c621a22SJames Smart 	/* For all nvmet xris, allocate resources needed to process a
9236c621a22SJames Smart 	 * received command on a per xri basis.
9246c621a22SJames Smart 	 */
9256c621a22SJames Smart 	for (i = 0; i < phba->sli4_hba.nvmet_xri_cnt; i++) {
9266c621a22SJames Smart 		ctx_buf = kzalloc(sizeof(*ctx_buf), GFP_KERNEL);
9276c621a22SJames Smart 		if (!ctx_buf) {
9286c621a22SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
9296c621a22SJames Smart 					"6404 Ran out of memory for NVMET\n");
9306c621a22SJames Smart 			return -ENOMEM;
9316c621a22SJames Smart 		}
9326c621a22SJames Smart 
9336c621a22SJames Smart 		ctx_buf->context = kzalloc(sizeof(*ctx_buf->context),
9346c621a22SJames Smart 					   GFP_KERNEL);
9356c621a22SJames Smart 		if (!ctx_buf->context) {
9366c621a22SJames Smart 			kfree(ctx_buf);
9376c621a22SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
9386c621a22SJames Smart 					"6405 Ran out of NVMET "
9396c621a22SJames Smart 					"context memory\n");
9406c621a22SJames Smart 			return -ENOMEM;
9416c621a22SJames Smart 		}
9426c621a22SJames Smart 		ctx_buf->context->ctxbuf = ctx_buf;
943ce1b591cSJames Smart 		ctx_buf->context->state = LPFC_NVMET_STE_FREE;
9446c621a22SJames Smart 
9456c621a22SJames Smart 		ctx_buf->iocbq = lpfc_sli_get_iocbq(phba);
9466c621a22SJames Smart 		if (!ctx_buf->iocbq) {
9476c621a22SJames Smart 			kfree(ctx_buf->context);
9486c621a22SJames Smart 			kfree(ctx_buf);
9496c621a22SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
9506c621a22SJames Smart 					"6406 Ran out of NVMET iocb/WQEs\n");
9516c621a22SJames Smart 			return -ENOMEM;
9526c621a22SJames Smart 		}
9536c621a22SJames Smart 		ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
9546c621a22SJames Smart 		nvmewqe = ctx_buf->iocbq;
9556c621a22SJames Smart 		wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
9566c621a22SJames Smart 		/* Initialize WQE */
9576c621a22SJames Smart 		memset(wqe, 0, sizeof(union lpfc_wqe));
9586c621a22SJames Smart 		/* Word 7 */
9596c621a22SJames Smart 		bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI);
9606c621a22SJames Smart 		bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
9616c621a22SJames Smart 		bf_set(wqe_pu, &wqe->generic.wqe_com, 1);
9626c621a22SJames Smart 		/* Word 10 */
9636c621a22SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
9646c621a22SJames Smart 		bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
9656c621a22SJames Smart 		bf_set(wqe_qosd, &wqe->generic.wqe_com, 0);
9666c621a22SJames Smart 
9676c621a22SJames Smart 		ctx_buf->iocbq->context1 = NULL;
9686c621a22SJames Smart 		spin_lock(&phba->sli4_hba.sgl_list_lock);
9696c621a22SJames Smart 		ctx_buf->sglq = __lpfc_sli_get_nvmet_sglq(phba, ctx_buf->iocbq);
9706c621a22SJames Smart 		spin_unlock(&phba->sli4_hba.sgl_list_lock);
9716c621a22SJames Smart 		if (!ctx_buf->sglq) {
9726c621a22SJames Smart 			lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
9736c621a22SJames Smart 			kfree(ctx_buf->context);
9746c621a22SJames Smart 			kfree(ctx_buf);
9756c621a22SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
9766c621a22SJames Smart 					"6407 Ran out of NVMET XRIs\n");
9776c621a22SJames Smart 			return -ENOMEM;
9786c621a22SJames Smart 		}
979966bb5b7SJames Smart 		spin_lock(&phba->sli4_hba.nvmet_ctx_get_lock);
9806c621a22SJames Smart 		list_add_tail(&ctx_buf->list,
981966bb5b7SJames Smart 			      &phba->sli4_hba.lpfc_nvmet_ctx_get_list);
982966bb5b7SJames Smart 		spin_unlock(&phba->sli4_hba.nvmet_ctx_get_lock);
9836c621a22SJames Smart 	}
984966bb5b7SJames Smart 	phba->sli4_hba.nvmet_ctx_get_cnt = phba->sli4_hba.nvmet_xri_cnt;
9856c621a22SJames Smart 	return 0;
9866c621a22SJames Smart }
9876c621a22SJames Smart 
988d613b6a7SJames Smart int
989d613b6a7SJames Smart lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
990d613b6a7SJames Smart {
991d613b6a7SJames Smart 	struct lpfc_vport  *vport = phba->pport;
992d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
993d613b6a7SJames Smart 	struct nvmet_fc_port_info pinfo;
9946c621a22SJames Smart 	int error;
995d613b6a7SJames Smart 
996d613b6a7SJames Smart 	if (phba->targetport)
997d613b6a7SJames Smart 		return 0;
998d613b6a7SJames Smart 
9996c621a22SJames Smart 	error = lpfc_nvmet_setup_io_context(phba);
10006c621a22SJames Smart 	if (error)
10016c621a22SJames Smart 		return error;
10026c621a22SJames Smart 
1003d613b6a7SJames Smart 	memset(&pinfo, 0, sizeof(struct nvmet_fc_port_info));
1004d613b6a7SJames Smart 	pinfo.node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
1005d613b6a7SJames Smart 	pinfo.port_name = wwn_to_u64(vport->fc_portname.u.wwn);
1006d613b6a7SJames Smart 	pinfo.port_id = vport->fc_myDID;
1007d613b6a7SJames Smart 
10084d4c4a4aSJames Smart 	/* Limit to LPFC_MAX_NVME_SEG_CNT.
10094d4c4a4aSJames Smart 	 * For now need + 1 to get around NVME transport logic.
10104d4c4a4aSJames Smart 	 */
10114d4c4a4aSJames Smart 	if (phba->cfg_sg_seg_cnt > LPFC_MAX_NVME_SEG_CNT) {
10124d4c4a4aSJames Smart 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_INIT,
10134d4c4a4aSJames Smart 				"6400 Reducing sg segment cnt to %d\n",
10144d4c4a4aSJames Smart 				LPFC_MAX_NVME_SEG_CNT);
10154d4c4a4aSJames Smart 		phba->cfg_nvme_seg_cnt = LPFC_MAX_NVME_SEG_CNT;
10164d4c4a4aSJames Smart 	} else {
10174d4c4a4aSJames Smart 		phba->cfg_nvme_seg_cnt = phba->cfg_sg_seg_cnt;
10184d4c4a4aSJames Smart 	}
10194d4c4a4aSJames Smart 	lpfc_tgttemplate.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
1020d613b6a7SJames Smart 	lpfc_tgttemplate.max_hw_queues = phba->cfg_nvme_io_channel;
1021d613b6a7SJames Smart 	lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP |
102239498faeSJames Smart 					   NVMET_FCTGTFEAT_CMD_IN_ISR |
102339498faeSJames Smart 					   NVMET_FCTGTFEAT_OPDONE_IN_ISR;
1024d613b6a7SJames Smart 
10257d708033SJames Smart #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
1026d613b6a7SJames Smart 	error = nvmet_fc_register_targetport(&pinfo, &lpfc_tgttemplate,
1027d613b6a7SJames Smart 					     &phba->pcidev->dev,
1028d613b6a7SJames Smart 					     &phba->targetport);
1029166d7211SJames Smart #else
10306c621a22SJames Smart 	error = -ENOENT;
1031166d7211SJames Smart #endif
1032d613b6a7SJames Smart 	if (error) {
1033d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
1034d613b6a7SJames Smart 				"6025 Cannot register NVME targetport "
1035d613b6a7SJames Smart 				"x%x\n", error);
1036d613b6a7SJames Smart 		phba->targetport = NULL;
10376c621a22SJames Smart 
10386c621a22SJames Smart 		lpfc_nvmet_cleanup_io_context(phba);
10396c621a22SJames Smart 
1040d613b6a7SJames Smart 	} else {
1041d613b6a7SJames Smart 		tgtp = (struct lpfc_nvmet_tgtport *)
1042d613b6a7SJames Smart 			phba->targetport->private;
1043d613b6a7SJames Smart 		tgtp->phba = phba;
1044d613b6a7SJames Smart 
1045d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
1046d613b6a7SJames Smart 				"6026 Registered NVME "
1047d613b6a7SJames Smart 				"targetport: %p, private %p "
1048d613b6a7SJames Smart 				"portnm %llx nodenm %llx\n",
1049d613b6a7SJames Smart 				phba->targetport, tgtp,
1050d613b6a7SJames Smart 				pinfo.port_name, pinfo.node_name);
1051d613b6a7SJames Smart 
1052d613b6a7SJames Smart 		atomic_set(&tgtp->rcv_ls_req_in, 0);
1053d613b6a7SJames Smart 		atomic_set(&tgtp->rcv_ls_req_out, 0);
1054d613b6a7SJames Smart 		atomic_set(&tgtp->rcv_ls_req_drop, 0);
1055d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_ls_abort, 0);
1056547077a4SJames Smart 		atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
1057d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_ls_rsp, 0);
1058d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_ls_drop, 0);
1059d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_ls_rsp_error, 0);
1060d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_ls_rsp_cmpl, 0);
1061d613b6a7SJames Smart 		atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
1062d613b6a7SJames Smart 		atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
1063d613b6a7SJames Smart 		atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
1064d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_drop, 0);
1065d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
1066d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_read, 0);
1067d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_write, 0);
1068d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_rsp, 0);
1069547077a4SJames Smart 		atomic_set(&tgtp->xmt_fcp_release, 0);
1070d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
1071d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
1072d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
1073547077a4SJames Smart 		atomic_set(&tgtp->xmt_fcp_abort, 0);
1074547077a4SJames Smart 		atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
1075547077a4SJames Smart 		atomic_set(&tgtp->xmt_abort_unsol, 0);
1076547077a4SJames Smart 		atomic_set(&tgtp->xmt_abort_sol, 0);
1077d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_abort_rsp, 0);
1078d613b6a7SJames Smart 		atomic_set(&tgtp->xmt_abort_rsp_error, 0);
1079d613b6a7SJames Smart 	}
1080d613b6a7SJames Smart 	return error;
1081d613b6a7SJames Smart }
1082d613b6a7SJames Smart 
1083d613b6a7SJames Smart int
1084d613b6a7SJames Smart lpfc_nvmet_update_targetport(struct lpfc_hba *phba)
1085d613b6a7SJames Smart {
1086d613b6a7SJames Smart 	struct lpfc_vport  *vport = phba->pport;
1087d613b6a7SJames Smart 
1088d613b6a7SJames Smart 	if (!phba->targetport)
1089d613b6a7SJames Smart 		return 0;
1090d613b6a7SJames Smart 
1091d613b6a7SJames Smart 	lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME,
1092d613b6a7SJames Smart 			 "6007 Update NVMET port %p did x%x\n",
1093d613b6a7SJames Smart 			 phba->targetport, vport->fc_myDID);
1094d613b6a7SJames Smart 
1095d613b6a7SJames Smart 	phba->targetport->port_id = vport->fc_myDID;
1096d613b6a7SJames Smart 	return 0;
1097d613b6a7SJames Smart }
1098d613b6a7SJames Smart 
1099318083adSJames Smart /**
1100318083adSJames Smart  * lpfc_sli4_nvmet_xri_aborted - Fast-path process of nvmet xri abort
1101318083adSJames Smart  * @phba: pointer to lpfc hba data structure.
1102318083adSJames Smart  * @axri: pointer to the nvmet xri abort wcqe structure.
1103318083adSJames Smart  *
1104318083adSJames Smart  * This routine is invoked by the worker thread to process a SLI4 fast-path
1105318083adSJames Smart  * NVMET aborted xri.
1106318083adSJames Smart  **/
1107318083adSJames Smart void
1108318083adSJames Smart lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
1109318083adSJames Smart 			    struct sli4_wcqe_xri_aborted *axri)
1110318083adSJames Smart {
111186c67379SJames Smart 	uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
111286c67379SJames Smart 	uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
111386c67379SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
111486c67379SJames Smart 	struct lpfc_nodelist *ndlp;
111586c67379SJames Smart 	unsigned long iflag = 0;
111686c67379SJames Smart 	int rrq_empty = 0;
111786c67379SJames Smart 	bool released = false;
111886c67379SJames Smart 
111986c67379SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
112086c67379SJames Smart 			"6317 XB aborted xri x%x rxid x%x\n", xri, rxid);
112186c67379SJames Smart 
112286c67379SJames Smart 	if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
112386c67379SJames Smart 		return;
112486c67379SJames Smart 	spin_lock_irqsave(&phba->hbalock, iflag);
112586c67379SJames Smart 	spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock);
112686c67379SJames Smart 	list_for_each_entry_safe(ctxp, next_ctxp,
112786c67379SJames Smart 				 &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
112886c67379SJames Smart 				 list) {
11296c621a22SJames Smart 		if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
113086c67379SJames Smart 			continue;
113186c67379SJames Smart 
113286c67379SJames Smart 		/* Check if we already received a free context call
113386c67379SJames Smart 		 * and we have completed processing an abort situation.
113486c67379SJames Smart 		 */
113586c67379SJames Smart 		if (ctxp->flag & LPFC_NVMET_CTX_RLS &&
113686c67379SJames Smart 		    !(ctxp->flag & LPFC_NVMET_ABORT_OP)) {
113786c67379SJames Smart 			list_del(&ctxp->list);
113886c67379SJames Smart 			released = true;
113986c67379SJames Smart 		}
114086c67379SJames Smart 		ctxp->flag &= ~LPFC_NVMET_XBUSY;
114186c67379SJames Smart 		spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
114286c67379SJames Smart 
114386c67379SJames Smart 		rrq_empty = list_empty(&phba->active_rrq_list);
114486c67379SJames Smart 		spin_unlock_irqrestore(&phba->hbalock, iflag);
114586c67379SJames Smart 		ndlp = lpfc_findnode_did(phba->pport, ctxp->sid);
114686c67379SJames Smart 		if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
114786c67379SJames Smart 		    (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE ||
114886c67379SJames Smart 		     ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
114986c67379SJames Smart 			lpfc_set_rrq_active(phba, ndlp,
11506c621a22SJames Smart 				ctxp->ctxbuf->sglq->sli4_lxritag,
115186c67379SJames Smart 				rxid, 1);
115286c67379SJames Smart 			lpfc_sli4_abts_err_handler(phba, ndlp, axri);
115386c67379SJames Smart 		}
115486c67379SJames Smart 
115586c67379SJames Smart 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
1156ce1b591cSJames Smart 				"6318 XB aborted oxid %x flg x%x (%x)\n",
115786c67379SJames Smart 				ctxp->oxid, ctxp->flag, released);
115886c67379SJames Smart 		if (released)
11596c621a22SJames Smart 			lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
11606c621a22SJames Smart 
116186c67379SJames Smart 		if (rrq_empty)
116286c67379SJames Smart 			lpfc_worker_wake_up(phba);
116386c67379SJames Smart 		return;
116486c67379SJames Smart 	}
116586c67379SJames Smart 	spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
116686c67379SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, iflag);
116786c67379SJames Smart }
116886c67379SJames Smart 
116986c67379SJames Smart int
117086c67379SJames Smart lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
117186c67379SJames Smart 			   struct fc_frame_header *fc_hdr)
117286c67379SJames Smart 
117386c67379SJames Smart {
117486c67379SJames Smart #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
117586c67379SJames Smart 	struct lpfc_hba *phba = vport->phba;
117686c67379SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
117786c67379SJames Smart 	struct nvmefc_tgt_fcp_req *rsp;
117886c67379SJames Smart 	uint16_t xri;
117986c67379SJames Smart 	unsigned long iflag = 0;
118086c67379SJames Smart 
118186c67379SJames Smart 	xri = be16_to_cpu(fc_hdr->fh_ox_id);
118286c67379SJames Smart 
118386c67379SJames Smart 	spin_lock_irqsave(&phba->hbalock, iflag);
118486c67379SJames Smart 	spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock);
118586c67379SJames Smart 	list_for_each_entry_safe(ctxp, next_ctxp,
118686c67379SJames Smart 				 &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
118786c67379SJames Smart 				 list) {
11886c621a22SJames Smart 		if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
118986c67379SJames Smart 			continue;
119086c67379SJames Smart 
119186c67379SJames Smart 		spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
119286c67379SJames Smart 		spin_unlock_irqrestore(&phba->hbalock, iflag);
119386c67379SJames Smart 
119486c67379SJames Smart 		spin_lock_irqsave(&ctxp->ctxlock, iflag);
119586c67379SJames Smart 		ctxp->flag |= LPFC_NVMET_ABTS_RCV;
119686c67379SJames Smart 		spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
119786c67379SJames Smart 
119886c67379SJames Smart 		lpfc_nvmeio_data(phba,
119986c67379SJames Smart 			"NVMET ABTS RCV: xri x%x CPU %02x rjt %d\n",
120086c67379SJames Smart 			xri, smp_processor_id(), 0);
120186c67379SJames Smart 
120286c67379SJames Smart 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
120386c67379SJames Smart 				"6319 NVMET Rcv ABTS:acc xri x%x\n", xri);
120486c67379SJames Smart 
120586c67379SJames Smart 		rsp = &ctxp->ctx.fcp_req;
120686c67379SJames Smart 		nvmet_fc_rcv_fcp_abort(phba->targetport, rsp);
120786c67379SJames Smart 
120886c67379SJames Smart 		/* Respond with BA_ACC accordingly */
120986c67379SJames Smart 		lpfc_sli4_seq_abort_rsp(vport, fc_hdr, 1);
121086c67379SJames Smart 		return 0;
121186c67379SJames Smart 	}
121286c67379SJames Smart 	spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
121386c67379SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, iflag);
121486c67379SJames Smart 
121586c67379SJames Smart 	lpfc_nvmeio_data(phba, "NVMET ABTS RCV: xri x%x CPU %02x rjt %d\n",
121686c67379SJames Smart 			 xri, smp_processor_id(), 1);
121786c67379SJames Smart 
121886c67379SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
121986c67379SJames Smart 			"6320 NVMET Rcv ABTS:rjt xri x%x\n", xri);
122086c67379SJames Smart 
122186c67379SJames Smart 	/* Respond with BA_RJT accordingly */
122286c67379SJames Smart 	lpfc_sli4_seq_abort_rsp(vport, fc_hdr, 0);
122386c67379SJames Smart #endif
1224b06e13c3SJens Axboe 	return 0;
1225318083adSJames Smart }
1226318083adSJames Smart 
1227d613b6a7SJames Smart void
1228d613b6a7SJames Smart lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
1229d613b6a7SJames Smart {
12307d708033SJames Smart #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
1231d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
1232d613b6a7SJames Smart 
1233d613b6a7SJames Smart 	if (phba->nvmet_support == 0)
1234d613b6a7SJames Smart 		return;
1235d613b6a7SJames Smart 	if (phba->targetport) {
1236d613b6a7SJames Smart 		tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
1237d613b6a7SJames Smart 		init_completion(&tgtp->tport_unreg_done);
1238d613b6a7SJames Smart 		nvmet_fc_unregister_targetport(phba->targetport);
1239d613b6a7SJames Smart 		wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
12406c621a22SJames Smart 		lpfc_nvmet_cleanup_io_context(phba);
1241d613b6a7SJames Smart 	}
1242d613b6a7SJames Smart 	phba->targetport = NULL;
1243166d7211SJames Smart #endif
1244d613b6a7SJames Smart }
1245d613b6a7SJames Smart 
1246d613b6a7SJames Smart /**
1247d613b6a7SJames Smart  * lpfc_nvmet_unsol_ls_buffer - Process an unsolicited event data buffer
1248d613b6a7SJames Smart  * @phba: pointer to lpfc hba data structure.
1249d613b6a7SJames Smart  * @pring: pointer to a SLI ring.
1250d613b6a7SJames Smart  * @nvmebuf: pointer to lpfc nvme command HBQ data structure.
1251d613b6a7SJames Smart  *
1252d613b6a7SJames Smart  * This routine is used for processing the WQE associated with a unsolicited
1253d613b6a7SJames Smart  * event. It first determines whether there is an existing ndlp that matches
1254d613b6a7SJames Smart  * the DID from the unsolicited WQE. If not, it will create a new one with
1255d613b6a7SJames Smart  * the DID from the unsolicited WQE. The ELS command from the unsolicited
1256d613b6a7SJames Smart  * WQE is then used to invoke the proper routine and to set up proper state
1257d613b6a7SJames Smart  * of the discovery state machine.
1258d613b6a7SJames Smart  **/
1259d613b6a7SJames Smart static void
1260d613b6a7SJames Smart lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1261d613b6a7SJames Smart 			   struct hbq_dmabuf *nvmebuf)
1262d613b6a7SJames Smart {
12637d708033SJames Smart #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
1264d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
1265d613b6a7SJames Smart 	struct fc_frame_header *fc_hdr;
1266d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
1267d613b6a7SJames Smart 	uint32_t *payload;
1268d613b6a7SJames Smart 	uint32_t size, oxid, sid, rc;
1269d613b6a7SJames Smart 
1270d613b6a7SJames Smart 	if (!nvmebuf || !phba->targetport) {
1271d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1272d613b6a7SJames Smart 				"6154 LS Drop IO\n");
12732b65e182SJames Smart 		oxid = 0;
12742b65e182SJames Smart 		size = 0;
12752b65e182SJames Smart 		sid = 0;
1276547077a4SJames Smart 		ctxp = NULL;
1277d613b6a7SJames Smart 		goto dropit;
1278d613b6a7SJames Smart 	}
1279d613b6a7SJames Smart 
1280d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
1281d613b6a7SJames Smart 	payload = (uint32_t *)(nvmebuf->dbuf.virt);
1282d613b6a7SJames Smart 	fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
1283d613b6a7SJames Smart 	size = bf_get(lpfc_rcqe_length,  &nvmebuf->cq_event.cqe.rcqe_cmpl);
1284d613b6a7SJames Smart 	oxid = be16_to_cpu(fc_hdr->fh_ox_id);
1285d613b6a7SJames Smart 	sid = sli4_sid_from_fc_hdr(fc_hdr);
1286d613b6a7SJames Smart 
1287d613b6a7SJames Smart 	ctxp = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx), GFP_ATOMIC);
1288d613b6a7SJames Smart 	if (ctxp == NULL) {
1289d613b6a7SJames Smart 		atomic_inc(&tgtp->rcv_ls_req_drop);
1290d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1291d613b6a7SJames Smart 				"6155 LS Drop IO x%x: Alloc\n",
1292d613b6a7SJames Smart 				oxid);
1293d613b6a7SJames Smart dropit:
12942b65e182SJames Smart 		lpfc_nvmeio_data(phba, "NVMET LS  DROP: "
12952b65e182SJames Smart 				 "xri x%x sz %d from %06x\n",
12962b65e182SJames Smart 				 oxid, size, sid);
1297d613b6a7SJames Smart 		if (nvmebuf)
1298d613b6a7SJames Smart 			lpfc_in_buf_free(phba, &nvmebuf->dbuf);
1299d613b6a7SJames Smart 		return;
1300d613b6a7SJames Smart 	}
1301d613b6a7SJames Smart 	ctxp->phba = phba;
1302d613b6a7SJames Smart 	ctxp->size = size;
1303d613b6a7SJames Smart 	ctxp->oxid = oxid;
1304d613b6a7SJames Smart 	ctxp->sid = sid;
1305d613b6a7SJames Smart 	ctxp->wqeq = NULL;
1306ce1b591cSJames Smart 	ctxp->state = LPFC_NVMET_STE_LS_RCV;
1307ce1b591cSJames Smart 	ctxp->entry_cnt = 1;
1308d613b6a7SJames Smart 	ctxp->rqb_buffer = (void *)nvmebuf;
13092b65e182SJames Smart 
13102b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET LS   RCV: xri x%x sz %d from %06x\n",
13112b65e182SJames Smart 			 oxid, size, sid);
1312d613b6a7SJames Smart 	/*
1313d613b6a7SJames Smart 	 * The calling sequence should be:
1314d613b6a7SJames Smart 	 * nvmet_fc_rcv_ls_req -> lpfc_nvmet_xmt_ls_rsp/cmp ->_req->done
1315d613b6a7SJames Smart 	 * lpfc_nvmet_xmt_ls_rsp_cmp should free the allocated ctxp.
1316d613b6a7SJames Smart 	 */
1317d613b6a7SJames Smart 	atomic_inc(&tgtp->rcv_ls_req_in);
1318d613b6a7SJames Smart 	rc = nvmet_fc_rcv_ls_req(phba->targetport, &ctxp->ctx.ls_req,
1319d613b6a7SJames Smart 				 payload, size);
1320d613b6a7SJames Smart 
1321d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
1322ce1b591cSJames Smart 			"6037 NVMET Unsol rcv: sz %d rc %d: %08x %08x %08x "
1323ce1b591cSJames Smart 			"%08x %08x %08x\n", size, rc,
1324d613b6a7SJames Smart 			*payload, *(payload+1), *(payload+2),
1325d613b6a7SJames Smart 			*(payload+3), *(payload+4), *(payload+5));
13262b65e182SJames Smart 
1327d613b6a7SJames Smart 	if (rc == 0) {
1328d613b6a7SJames Smart 		atomic_inc(&tgtp->rcv_ls_req_out);
1329d613b6a7SJames Smart 		return;
1330d613b6a7SJames Smart 	}
13312b65e182SJames Smart 
13322b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET LS  DROP: xri x%x sz %d from %06x\n",
13332b65e182SJames Smart 			 oxid, size, sid);
13342b65e182SJames Smart 
1335d613b6a7SJames Smart 	atomic_inc(&tgtp->rcv_ls_req_drop);
1336d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1337d613b6a7SJames Smart 			"6156 LS Drop IO x%x: nvmet_fc_rcv_ls_req %d\n",
1338d613b6a7SJames Smart 			ctxp->oxid, rc);
1339d613b6a7SJames Smart 
1340d613b6a7SJames Smart 	/* We assume a rcv'ed cmd ALWAYs fits into 1 buffer */
1341d613b6a7SJames Smart 	if (nvmebuf)
1342d613b6a7SJames Smart 		lpfc_in_buf_free(phba, &nvmebuf->dbuf);
1343d613b6a7SJames Smart 
1344d613b6a7SJames Smart 	atomic_inc(&tgtp->xmt_ls_abort);
1345d613b6a7SJames Smart 	lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, sid, oxid);
1346166d7211SJames Smart #endif
1347d613b6a7SJames Smart }
1348d613b6a7SJames Smart 
1349d613b6a7SJames Smart /**
1350d613b6a7SJames Smart  * lpfc_nvmet_unsol_fcp_buffer - Process an unsolicited event data buffer
1351d613b6a7SJames Smart  * @phba: pointer to lpfc hba data structure.
1352d613b6a7SJames Smart  * @pring: pointer to a SLI ring.
1353d613b6a7SJames Smart  * @nvmebuf: pointer to lpfc nvme command HBQ data structure.
1354d613b6a7SJames Smart  *
1355d613b6a7SJames Smart  * This routine is used for processing the WQE associated with a unsolicited
1356d613b6a7SJames Smart  * event. It first determines whether there is an existing ndlp that matches
1357d613b6a7SJames Smart  * the DID from the unsolicited WQE. If not, it will create a new one with
1358d613b6a7SJames Smart  * the DID from the unsolicited WQE. The ELS command from the unsolicited
1359d613b6a7SJames Smart  * WQE is then used to invoke the proper routine and to set up proper state
1360d613b6a7SJames Smart  * of the discovery state machine.
1361d613b6a7SJames Smart  **/
1362d613b6a7SJames Smart static void
1363d613b6a7SJames Smart lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
1364d613b6a7SJames Smart 			    struct lpfc_sli_ring *pring,
1365d613b6a7SJames Smart 			    struct rqb_dmabuf *nvmebuf,
1366d613b6a7SJames Smart 			    uint64_t isr_timestamp)
1367d613b6a7SJames Smart {
13687d708033SJames Smart #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
1369d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
1370d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
1371d613b6a7SJames Smart 	struct fc_frame_header *fc_hdr;
13726c621a22SJames Smart 	struct lpfc_nvmet_ctxbuf *ctx_buf;
1373d613b6a7SJames Smart 	uint32_t *payload;
1374a8cf5dfeSJames Smart 	uint32_t size, oxid, sid, rc, qno;
13756c621a22SJames Smart 	unsigned long iflag;
13762b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
13772b65e182SJames Smart 	uint32_t id;
13782b65e182SJames Smart #endif
1379d613b6a7SJames Smart 
13806c621a22SJames Smart 	ctx_buf = NULL;
1381d613b6a7SJames Smart 	if (!nvmebuf || !phba->targetport) {
1382d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
13836c621a22SJames Smart 				"6157 NVMET FCP Drop IO\n");
13842b65e182SJames Smart 		oxid = 0;
13852b65e182SJames Smart 		size = 0;
13862b65e182SJames Smart 		sid = 0;
1387547077a4SJames Smart 		ctxp = NULL;
1388d613b6a7SJames Smart 		goto dropit;
1389d613b6a7SJames Smart 	}
1390d613b6a7SJames Smart 
1391966bb5b7SJames Smart 	spin_lock_irqsave(&phba->sli4_hba.nvmet_ctx_get_lock, iflag);
1392966bb5b7SJames Smart 	if (phba->sli4_hba.nvmet_ctx_get_cnt) {
1393966bb5b7SJames Smart 		list_remove_head(&phba->sli4_hba.lpfc_nvmet_ctx_get_list,
13946c621a22SJames Smart 				 ctx_buf, struct lpfc_nvmet_ctxbuf, list);
1395966bb5b7SJames Smart 		phba->sli4_hba.nvmet_ctx_get_cnt--;
1396966bb5b7SJames Smart 	} else {
1397966bb5b7SJames Smart 		spin_lock(&phba->sli4_hba.nvmet_ctx_put_lock);
1398966bb5b7SJames Smart 		if (phba->sli4_hba.nvmet_ctx_put_cnt) {
1399966bb5b7SJames Smart 			list_splice(&phba->sli4_hba.lpfc_nvmet_ctx_put_list,
1400966bb5b7SJames Smart 				    &phba->sli4_hba.lpfc_nvmet_ctx_get_list);
1401966bb5b7SJames Smart 			INIT_LIST_HEAD(&phba->sli4_hba.lpfc_nvmet_ctx_put_list);
1402966bb5b7SJames Smart 			phba->sli4_hba.nvmet_ctx_get_cnt =
1403966bb5b7SJames Smart 				phba->sli4_hba.nvmet_ctx_put_cnt;
1404966bb5b7SJames Smart 			phba->sli4_hba.nvmet_ctx_put_cnt = 0;
1405966bb5b7SJames Smart 			spin_unlock(&phba->sli4_hba.nvmet_ctx_put_lock);
1406966bb5b7SJames Smart 
1407966bb5b7SJames Smart 			list_remove_head(
1408966bb5b7SJames Smart 				&phba->sli4_hba.lpfc_nvmet_ctx_get_list,
1409966bb5b7SJames Smart 				ctx_buf, struct lpfc_nvmet_ctxbuf, list);
1410966bb5b7SJames Smart 			phba->sli4_hba.nvmet_ctx_get_cnt--;
1411966bb5b7SJames Smart 		} else {
1412966bb5b7SJames Smart 			spin_unlock(&phba->sli4_hba.nvmet_ctx_put_lock);
14136c621a22SJames Smart 		}
1414966bb5b7SJames Smart 	}
1415966bb5b7SJames Smart 	spin_unlock_irqrestore(&phba->sli4_hba.nvmet_ctx_get_lock, iflag);
14166c621a22SJames Smart 
1417a8cf5dfeSJames Smart 	fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
1418a8cf5dfeSJames Smart 	oxid = be16_to_cpu(fc_hdr->fh_ox_id);
1419a8cf5dfeSJames Smart 	size = nvmebuf->bytes_recv;
1420a8cf5dfeSJames Smart 
1421a8cf5dfeSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1422a8cf5dfeSJames Smart 	if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) {
1423a8cf5dfeSJames Smart 		id = smp_processor_id();
1424a8cf5dfeSJames Smart 		if (id < LPFC_CHECK_CPU_CNT)
1425a8cf5dfeSJames Smart 			phba->cpucheck_rcv_io[id]++;
1426a8cf5dfeSJames Smart 	}
1427a8cf5dfeSJames Smart #endif
1428a8cf5dfeSJames Smart 
1429a8cf5dfeSJames Smart 	lpfc_nvmeio_data(phba, "NVMET FCP  RCV: xri x%x sz %d CPU %02x\n",
1430a8cf5dfeSJames Smart 			 oxid, size, smp_processor_id());
1431a8cf5dfeSJames Smart 
14326c621a22SJames Smart 	if (!ctx_buf) {
1433a8cf5dfeSJames Smart 		/* Queue this NVME IO to process later */
1434a8cf5dfeSJames Smart 		spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
1435a8cf5dfeSJames Smart 		list_add_tail(&nvmebuf->hbuf.list,
1436a8cf5dfeSJames Smart 			      &phba->sli4_hba.lpfc_nvmet_io_wait_list);
1437a8cf5dfeSJames Smart 		phba->sli4_hba.nvmet_io_wait_cnt++;
1438a8cf5dfeSJames Smart 		phba->sli4_hba.nvmet_io_wait_total++;
1439a8cf5dfeSJames Smart 		spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
1440a8cf5dfeSJames Smart 				       iflag);
1441a8cf5dfeSJames Smart 
1442a8cf5dfeSJames Smart 		/* Post a brand new DMA buffer to RQ */
1443a8cf5dfeSJames Smart 		qno = nvmebuf->idx;
1444a8cf5dfeSJames Smart 		lpfc_post_rq_buffer(
1445a8cf5dfeSJames Smart 			phba, phba->sli4_hba.nvmet_mrq_hdr[qno],
1446a8cf5dfeSJames Smart 			phba->sli4_hba.nvmet_mrq_data[qno], 1, qno);
1447a8cf5dfeSJames Smart 		return;
14486c621a22SJames Smart 	}
1449d613b6a7SJames Smart 
1450d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
1451d613b6a7SJames Smart 	payload = (uint32_t *)(nvmebuf->dbuf.virt);
1452d613b6a7SJames Smart 	sid = sli4_sid_from_fc_hdr(fc_hdr);
1453d613b6a7SJames Smart 
14546c621a22SJames Smart 	ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
1455ce1b591cSJames Smart 	if (ctxp->state != LPFC_NVMET_STE_FREE) {
1456ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1457ce1b591cSJames Smart 				"6414 NVMET Context corrupt %d %d oxid x%x\n",
1458ce1b591cSJames Smart 				ctxp->state, ctxp->entry_cnt, ctxp->oxid);
1459ce1b591cSJames Smart 	}
1460d613b6a7SJames Smart 	ctxp->wqeq = NULL;
1461d613b6a7SJames Smart 	ctxp->txrdy = NULL;
1462d613b6a7SJames Smart 	ctxp->offset = 0;
1463d613b6a7SJames Smart 	ctxp->phba = phba;
1464d613b6a7SJames Smart 	ctxp->size = size;
1465d613b6a7SJames Smart 	ctxp->oxid = oxid;
1466d613b6a7SJames Smart 	ctxp->sid = sid;
1467d613b6a7SJames Smart 	ctxp->state = LPFC_NVMET_STE_RCV;
1468d613b6a7SJames Smart 	ctxp->entry_cnt = 1;
1469d613b6a7SJames Smart 	ctxp->flag = 0;
14706c621a22SJames Smart 	ctxp->ctxbuf = ctx_buf;
14712b7824d0SJames Smart 	spin_lock_init(&ctxp->ctxlock);
1472d613b6a7SJames Smart 
14732b65e182SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
14742b65e182SJames Smart 	if (phba->ktime_on) {
14752b65e182SJames Smart 		ctxp->ts_isr_cmd = isr_timestamp;
14762b65e182SJames Smart 		ctxp->ts_cmd_nvme = ktime_get_ns();
14772b65e182SJames Smart 		ctxp->ts_nvme_data = 0;
14782b65e182SJames Smart 		ctxp->ts_data_wqput = 0;
14792b65e182SJames Smart 		ctxp->ts_isr_data = 0;
14802b65e182SJames Smart 		ctxp->ts_data_nvme = 0;
14812b65e182SJames Smart 		ctxp->ts_nvme_status = 0;
14822b65e182SJames Smart 		ctxp->ts_status_wqput = 0;
14832b65e182SJames Smart 		ctxp->ts_isr_status = 0;
14842b65e182SJames Smart 		ctxp->ts_status_nvme = 0;
14852b65e182SJames Smart 	}
14862b65e182SJames Smart #endif
14872b65e182SJames Smart 
1488d613b6a7SJames Smart 	atomic_inc(&tgtp->rcv_fcp_cmd_in);
1489d613b6a7SJames Smart 	/*
1490d613b6a7SJames Smart 	 * The calling sequence should be:
1491d613b6a7SJames Smart 	 * nvmet_fc_rcv_fcp_req -> lpfc_nvmet_xmt_fcp_op/cmp -> req->done
1492d613b6a7SJames Smart 	 * lpfc_nvmet_xmt_fcp_op_cmp should free the allocated ctxp.
14936c621a22SJames Smart 	 * When we return from nvmet_fc_rcv_fcp_req, all relevant info in
14946c621a22SJames Smart 	 * the NVME command / FC header is stored, so we are free to repost
14956c621a22SJames Smart 	 * the buffer.
1496d613b6a7SJames Smart 	 */
1497d613b6a7SJames Smart 	rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
1498d613b6a7SJames Smart 				  payload, size);
1499d613b6a7SJames Smart 
1500d613b6a7SJames Smart 	/* Process FCP command */
1501d613b6a7SJames Smart 	if (rc == 0) {
1502d613b6a7SJames Smart 		atomic_inc(&tgtp->rcv_fcp_cmd_out);
15036c621a22SJames Smart 		lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
1504d613b6a7SJames Smart 		return;
1505d613b6a7SJames Smart 	}
1506d613b6a7SJames Smart 
1507d613b6a7SJames Smart 	atomic_inc(&tgtp->rcv_fcp_cmd_drop);
1508d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1509547077a4SJames Smart 			"6159 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
1510547077a4SJames Smart 			ctxp->oxid, rc,
1511547077a4SJames Smart 			atomic_read(&tgtp->rcv_fcp_cmd_in),
1512547077a4SJames Smart 			atomic_read(&tgtp->rcv_fcp_cmd_out),
1513547077a4SJames Smart 			atomic_read(&tgtp->xmt_fcp_release));
1514d613b6a7SJames Smart dropit:
15152b65e182SJames Smart 	lpfc_nvmeio_data(phba, "NVMET FCP DROP: xri x%x sz %d from %06x\n",
15162b65e182SJames Smart 			 oxid, size, sid);
1517d613b6a7SJames Smart 	if (oxid) {
15186c621a22SJames Smart 		lpfc_nvmet_defer_release(phba, ctxp);
1519d613b6a7SJames Smart 		lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, sid, oxid);
15206c621a22SJames Smart 		lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
1521d613b6a7SJames Smart 		return;
1522d613b6a7SJames Smart 	}
1523d613b6a7SJames Smart 
15246c621a22SJames Smart 	if (ctx_buf)
15256c621a22SJames Smart 		lpfc_nvmet_ctxbuf_post(phba, ctx_buf);
15266c621a22SJames Smart 
15276c621a22SJames Smart 	if (nvmebuf)
15286c621a22SJames Smart 		lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
1529166d7211SJames Smart #endif
1530d613b6a7SJames Smart }
1531d613b6a7SJames Smart 
1532d613b6a7SJames Smart /**
1533d613b6a7SJames Smart  * lpfc_nvmet_unsol_ls_event - Process an unsolicited event from an nvme nport
1534d613b6a7SJames Smart  * @phba: pointer to lpfc hba data structure.
1535d613b6a7SJames Smart  * @pring: pointer to a SLI ring.
1536d613b6a7SJames Smart  * @nvmebuf: pointer to received nvme data structure.
1537d613b6a7SJames Smart  *
1538d613b6a7SJames Smart  * This routine is used to process an unsolicited event received from a SLI
1539d613b6a7SJames Smart  * (Service Level Interface) ring. The actual processing of the data buffer
1540d613b6a7SJames Smart  * associated with the unsolicited event is done by invoking the routine
1541d613b6a7SJames Smart  * lpfc_nvmet_unsol_ls_buffer() after properly set up the buffer from the
1542d613b6a7SJames Smart  * SLI RQ on which the unsolicited event was received.
1543d613b6a7SJames Smart  **/
1544d613b6a7SJames Smart void
1545d613b6a7SJames Smart lpfc_nvmet_unsol_ls_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1546d613b6a7SJames Smart 			  struct lpfc_iocbq *piocb)
1547d613b6a7SJames Smart {
1548d613b6a7SJames Smart 	struct lpfc_dmabuf *d_buf;
1549d613b6a7SJames Smart 	struct hbq_dmabuf *nvmebuf;
1550d613b6a7SJames Smart 
1551d613b6a7SJames Smart 	d_buf = piocb->context2;
1552d613b6a7SJames Smart 	nvmebuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
1553d613b6a7SJames Smart 
1554d613b6a7SJames Smart 	if (phba->nvmet_support == 0) {
1555d613b6a7SJames Smart 		lpfc_in_buf_free(phba, &nvmebuf->dbuf);
1556d613b6a7SJames Smart 		return;
1557d613b6a7SJames Smart 	}
1558d613b6a7SJames Smart 	lpfc_nvmet_unsol_ls_buffer(phba, pring, nvmebuf);
1559d613b6a7SJames Smart }
1560d613b6a7SJames Smart 
1561d613b6a7SJames Smart /**
1562d613b6a7SJames Smart  * lpfc_nvmet_unsol_fcp_event - Process an unsolicited event from an nvme nport
1563d613b6a7SJames Smart  * @phba: pointer to lpfc hba data structure.
1564d613b6a7SJames Smart  * @pring: pointer to a SLI ring.
1565d613b6a7SJames Smart  * @nvmebuf: pointer to received nvme data structure.
1566d613b6a7SJames Smart  *
1567d613b6a7SJames Smart  * This routine is used to process an unsolicited event received from a SLI
1568d613b6a7SJames Smart  * (Service Level Interface) ring. The actual processing of the data buffer
1569d613b6a7SJames Smart  * associated with the unsolicited event is done by invoking the routine
1570d613b6a7SJames Smart  * lpfc_nvmet_unsol_fcp_buffer() after properly set up the buffer from the
1571d613b6a7SJames Smart  * SLI RQ on which the unsolicited event was received.
1572d613b6a7SJames Smart  **/
1573d613b6a7SJames Smart void
1574d613b6a7SJames Smart lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba,
1575d613b6a7SJames Smart 			   struct lpfc_sli_ring *pring,
1576d613b6a7SJames Smart 			   struct rqb_dmabuf *nvmebuf,
1577d613b6a7SJames Smart 			   uint64_t isr_timestamp)
1578d613b6a7SJames Smart {
1579d613b6a7SJames Smart 	if (phba->nvmet_support == 0) {
15806c621a22SJames Smart 		lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
1581d613b6a7SJames Smart 		return;
1582d613b6a7SJames Smart 	}
1583d613b6a7SJames Smart 	lpfc_nvmet_unsol_fcp_buffer(phba, pring, nvmebuf,
1584d613b6a7SJames Smart 				    isr_timestamp);
1585d613b6a7SJames Smart }
1586d613b6a7SJames Smart 
1587d613b6a7SJames Smart /**
1588d613b6a7SJames Smart  * lpfc_nvmet_prep_ls_wqe - Allocate and prepare a lpfc wqe data structure
1589d613b6a7SJames Smart  * @phba: pointer to a host N_Port data structure.
1590d613b6a7SJames Smart  * @ctxp: Context info for NVME LS Request
1591d613b6a7SJames Smart  * @rspbuf: DMA buffer of NVME command.
1592d613b6a7SJames Smart  * @rspsize: size of the NVME command.
1593d613b6a7SJames Smart  *
1594d613b6a7SJames Smart  * This routine is used for allocating a lpfc-WQE data structure from
1595d613b6a7SJames Smart  * the driver lpfc-WQE free-list and prepare the WQE with the parameters
1596d613b6a7SJames Smart  * passed into the routine for discovery state machine to issue an Extended
1597d613b6a7SJames Smart  * Link Service (NVME) commands. It is a generic lpfc-WQE allocation
1598d613b6a7SJames Smart  * and preparation routine that is used by all the discovery state machine
1599d613b6a7SJames Smart  * routines and the NVME command-specific fields will be later set up by
1600d613b6a7SJames Smart  * the individual discovery machine routines after calling this routine
1601d613b6a7SJames Smart  * allocating and preparing a generic WQE data structure. It fills in the
1602d613b6a7SJames Smart  * Buffer Descriptor Entries (BDEs), allocates buffers for both command
1603d613b6a7SJames Smart  * payload and response payload (if expected). The reference count on the
1604d613b6a7SJames Smart  * ndlp is incremented by 1 and the reference to the ndlp is put into
1605d613b6a7SJames Smart  * context1 of the WQE data structure for this WQE to hold the ndlp
1606d613b6a7SJames Smart  * reference for the command's callback function to access later.
1607d613b6a7SJames Smart  *
1608d613b6a7SJames Smart  * Return code
1609d613b6a7SJames Smart  *   Pointer to the newly allocated/prepared nvme wqe data structure
1610d613b6a7SJames Smart  *   NULL - when nvme wqe data structure allocation/preparation failed
1611d613b6a7SJames Smart  **/
1612d613b6a7SJames Smart static struct lpfc_iocbq *
1613d613b6a7SJames Smart lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba,
1614d613b6a7SJames Smart 		       struct lpfc_nvmet_rcv_ctx *ctxp,
1615d613b6a7SJames Smart 		       dma_addr_t rspbuf, uint16_t rspsize)
1616d613b6a7SJames Smart {
1617d613b6a7SJames Smart 	struct lpfc_nodelist *ndlp;
1618d613b6a7SJames Smart 	struct lpfc_iocbq *nvmewqe;
1619d613b6a7SJames Smart 	union lpfc_wqe *wqe;
1620d613b6a7SJames Smart 
1621d613b6a7SJames Smart 	if (!lpfc_is_link_up(phba)) {
1622d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
1623ce1b591cSJames Smart 				"6104 NVMET prep LS wqe: link err: "
1624ce1b591cSJames Smart 				"NPORT x%x oxid:x%x ste %d\n",
1625ce1b591cSJames Smart 				ctxp->sid, ctxp->oxid, ctxp->state);
1626d613b6a7SJames Smart 		return NULL;
1627d613b6a7SJames Smart 	}
1628d613b6a7SJames Smart 
1629d613b6a7SJames Smart 	/* Allocate buffer for  command wqe */
1630d613b6a7SJames Smart 	nvmewqe = lpfc_sli_get_iocbq(phba);
1631d613b6a7SJames Smart 	if (nvmewqe == NULL) {
1632d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
1633ce1b591cSJames Smart 				"6105 NVMET prep LS wqe: No WQE: "
1634ce1b591cSJames Smart 				"NPORT x%x oxid x%x ste %d\n",
1635ce1b591cSJames Smart 				ctxp->sid, ctxp->oxid, ctxp->state);
1636d613b6a7SJames Smart 		return NULL;
1637d613b6a7SJames Smart 	}
1638d613b6a7SJames Smart 
1639d613b6a7SJames Smart 	ndlp = lpfc_findnode_did(phba->pport, ctxp->sid);
1640d613b6a7SJames Smart 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
1641d613b6a7SJames Smart 	    ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
1642d613b6a7SJames Smart 	    (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
1643d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
1644ce1b591cSJames Smart 				"6106 NVMET prep LS wqe: No ndlp: "
1645ce1b591cSJames Smart 				"NPORT x%x oxid x%x ste %d\n",
1646ce1b591cSJames Smart 				ctxp->sid, ctxp->oxid, ctxp->state);
1647d613b6a7SJames Smart 		goto nvme_wqe_free_wqeq_exit;
1648d613b6a7SJames Smart 	}
1649d613b6a7SJames Smart 	ctxp->wqeq = nvmewqe;
1650d613b6a7SJames Smart 
1651d613b6a7SJames Smart 	/* prevent preparing wqe with NULL ndlp reference */
1652d613b6a7SJames Smart 	nvmewqe->context1 = lpfc_nlp_get(ndlp);
1653d613b6a7SJames Smart 	if (nvmewqe->context1 == NULL)
1654d613b6a7SJames Smart 		goto nvme_wqe_free_wqeq_exit;
1655d613b6a7SJames Smart 	nvmewqe->context2 = ctxp;
1656d613b6a7SJames Smart 
1657d613b6a7SJames Smart 	wqe = &nvmewqe->wqe;
1658d613b6a7SJames Smart 	memset(wqe, 0, sizeof(union lpfc_wqe));
1659d613b6a7SJames Smart 
1660d613b6a7SJames Smart 	/* Words 0 - 2 */
1661d613b6a7SJames Smart 	wqe->xmit_sequence.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
1662d613b6a7SJames Smart 	wqe->xmit_sequence.bde.tus.f.bdeSize = rspsize;
1663d613b6a7SJames Smart 	wqe->xmit_sequence.bde.addrLow = le32_to_cpu(putPaddrLow(rspbuf));
1664d613b6a7SJames Smart 	wqe->xmit_sequence.bde.addrHigh = le32_to_cpu(putPaddrHigh(rspbuf));
1665d613b6a7SJames Smart 
1666d613b6a7SJames Smart 	/* Word 3 */
1667d613b6a7SJames Smart 
1668d613b6a7SJames Smart 	/* Word 4 */
1669d613b6a7SJames Smart 
1670d613b6a7SJames Smart 	/* Word 5 */
1671d613b6a7SJames Smart 	bf_set(wqe_dfctl, &wqe->xmit_sequence.wge_ctl, 0);
1672d613b6a7SJames Smart 	bf_set(wqe_ls, &wqe->xmit_sequence.wge_ctl, 1);
1673d613b6a7SJames Smart 	bf_set(wqe_la, &wqe->xmit_sequence.wge_ctl, 0);
16748b361639SJames Smart 	bf_set(wqe_rctl, &wqe->xmit_sequence.wge_ctl, FC_RCTL_ELS4_REP);
1675d613b6a7SJames Smart 	bf_set(wqe_type, &wqe->xmit_sequence.wge_ctl, FC_TYPE_NVME);
1676d613b6a7SJames Smart 
1677d613b6a7SJames Smart 	/* Word 6 */
1678d613b6a7SJames Smart 	bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com,
1679d613b6a7SJames Smart 	       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
1680d613b6a7SJames Smart 	bf_set(wqe_xri_tag, &wqe->xmit_sequence.wqe_com, nvmewqe->sli4_xritag);
1681d613b6a7SJames Smart 
1682d613b6a7SJames Smart 	/* Word 7 */
1683d613b6a7SJames Smart 	bf_set(wqe_cmnd, &wqe->xmit_sequence.wqe_com,
1684d613b6a7SJames Smart 	       CMD_XMIT_SEQUENCE64_WQE);
1685d613b6a7SJames Smart 	bf_set(wqe_ct, &wqe->xmit_sequence.wqe_com, SLI4_CT_RPI);
1686d613b6a7SJames Smart 	bf_set(wqe_class, &wqe->xmit_sequence.wqe_com, CLASS3);
1687d613b6a7SJames Smart 	bf_set(wqe_pu, &wqe->xmit_sequence.wqe_com, 0);
1688d613b6a7SJames Smart 
1689d613b6a7SJames Smart 	/* Word 8 */
1690d613b6a7SJames Smart 	wqe->xmit_sequence.wqe_com.abort_tag = nvmewqe->iotag;
1691d613b6a7SJames Smart 
1692d613b6a7SJames Smart 	/* Word 9 */
1693d613b6a7SJames Smart 	bf_set(wqe_reqtag, &wqe->xmit_sequence.wqe_com, nvmewqe->iotag);
1694d613b6a7SJames Smart 	/* Needs to be set by caller */
1695d613b6a7SJames Smart 	bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, ctxp->oxid);
1696d613b6a7SJames Smart 
1697d613b6a7SJames Smart 	/* Word 10 */
1698d613b6a7SJames Smart 	bf_set(wqe_dbde, &wqe->xmit_sequence.wqe_com, 1);
1699d613b6a7SJames Smart 	bf_set(wqe_iod, &wqe->xmit_sequence.wqe_com, LPFC_WQE_IOD_WRITE);
1700d613b6a7SJames Smart 	bf_set(wqe_lenloc, &wqe->xmit_sequence.wqe_com,
1701d613b6a7SJames Smart 	       LPFC_WQE_LENLOC_WORD12);
1702d613b6a7SJames Smart 	bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0);
1703d613b6a7SJames Smart 
1704d613b6a7SJames Smart 	/* Word 11 */
1705d613b6a7SJames Smart 	bf_set(wqe_cqid, &wqe->xmit_sequence.wqe_com,
1706d613b6a7SJames Smart 	       LPFC_WQE_CQ_ID_DEFAULT);
1707d613b6a7SJames Smart 	bf_set(wqe_cmd_type, &wqe->xmit_sequence.wqe_com,
1708d613b6a7SJames Smart 	       OTHER_COMMAND);
1709d613b6a7SJames Smart 
1710d613b6a7SJames Smart 	/* Word 12 */
1711d613b6a7SJames Smart 	wqe->xmit_sequence.xmit_len = rspsize;
1712d613b6a7SJames Smart 
1713d613b6a7SJames Smart 	nvmewqe->retry = 1;
1714d613b6a7SJames Smart 	nvmewqe->vport = phba->pport;
1715d613b6a7SJames Smart 	nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT;
1716d613b6a7SJames Smart 	nvmewqe->iocb_flag |= LPFC_IO_NVME_LS;
1717d613b6a7SJames Smart 
1718ce1b591cSJames Smart 	/* Xmit NVMET response to remote NPORT <did> */
1719d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
1720ce1b591cSJames Smart 			"6039 Xmit NVMET LS response to remote "
1721d613b6a7SJames Smart 			"NPORT x%x iotag:x%x oxid:x%x size:x%x\n",
1722d613b6a7SJames Smart 			ndlp->nlp_DID, nvmewqe->iotag, ctxp->oxid,
1723d613b6a7SJames Smart 			rspsize);
1724d613b6a7SJames Smart 	return nvmewqe;
1725d613b6a7SJames Smart 
1726d613b6a7SJames Smart nvme_wqe_free_wqeq_exit:
1727d613b6a7SJames Smart 	nvmewqe->context2 = NULL;
1728d613b6a7SJames Smart 	nvmewqe->context3 = NULL;
1729d613b6a7SJames Smart 	lpfc_sli_release_iocbq(phba, nvmewqe);
1730d613b6a7SJames Smart 	return NULL;
1731d613b6a7SJames Smart }
1732d613b6a7SJames Smart 
1733d613b6a7SJames Smart 
1734d613b6a7SJames Smart static struct lpfc_iocbq *
1735d613b6a7SJames Smart lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
1736d613b6a7SJames Smart 			struct lpfc_nvmet_rcv_ctx *ctxp)
1737d613b6a7SJames Smart {
1738d613b6a7SJames Smart 	struct nvmefc_tgt_fcp_req *rsp = &ctxp->ctx.fcp_req;
1739d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
1740d613b6a7SJames Smart 	struct sli4_sge *sgl;
1741d613b6a7SJames Smart 	struct lpfc_nodelist *ndlp;
1742d613b6a7SJames Smart 	struct lpfc_iocbq *nvmewqe;
1743d613b6a7SJames Smart 	struct scatterlist *sgel;
1744d613b6a7SJames Smart 	union lpfc_wqe128 *wqe;
1745d613b6a7SJames Smart 	uint32_t *txrdy;
1746d613b6a7SJames Smart 	dma_addr_t physaddr;
1747d613b6a7SJames Smart 	int i, cnt;
1748d613b6a7SJames Smart 	int xc = 1;
1749d613b6a7SJames Smart 
1750d613b6a7SJames Smart 	if (!lpfc_is_link_up(phba)) {
1751d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1752ce1b591cSJames Smart 				"6107 NVMET prep FCP wqe: link err:"
1753ce1b591cSJames Smart 				"NPORT x%x oxid x%x ste %d\n",
1754ce1b591cSJames Smart 				ctxp->sid, ctxp->oxid, ctxp->state);
1755d613b6a7SJames Smart 		return NULL;
1756d613b6a7SJames Smart 	}
1757d613b6a7SJames Smart 
1758d613b6a7SJames Smart 	ndlp = lpfc_findnode_did(phba->pport, ctxp->sid);
1759d613b6a7SJames Smart 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
1760d613b6a7SJames Smart 	    ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
1761d613b6a7SJames Smart 	     (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
1762d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1763ce1b591cSJames Smart 				"6108 NVMET prep FCP wqe: no ndlp: "
1764ce1b591cSJames Smart 				"NPORT x%x oxid x%x ste %d\n",
1765ce1b591cSJames Smart 				ctxp->sid, ctxp->oxid, ctxp->state);
1766d613b6a7SJames Smart 		return NULL;
1767d613b6a7SJames Smart 	}
1768d613b6a7SJames Smart 
17694d4c4a4aSJames Smart 	if (rsp->sg_cnt > phba->cfg_nvme_seg_cnt) {
1770d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1771ce1b591cSJames Smart 				"6109 NVMET prep FCP wqe: seg cnt err: "
1772ce1b591cSJames Smart 				"NPORT x%x oxid x%x ste %d cnt %d\n",
1773ce1b591cSJames Smart 				ctxp->sid, ctxp->oxid, ctxp->state,
1774ce1b591cSJames Smart 				phba->cfg_nvme_seg_cnt);
1775d613b6a7SJames Smart 		return NULL;
1776d613b6a7SJames Smart 	}
1777d613b6a7SJames Smart 
1778d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
1779d613b6a7SJames Smart 	nvmewqe = ctxp->wqeq;
1780d613b6a7SJames Smart 	if (nvmewqe == NULL) {
1781d613b6a7SJames Smart 		/* Allocate buffer for  command wqe */
17826c621a22SJames Smart 		nvmewqe = ctxp->ctxbuf->iocbq;
1783d613b6a7SJames Smart 		if (nvmewqe == NULL) {
1784d613b6a7SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1785ce1b591cSJames Smart 					"6110 NVMET prep FCP wqe: No "
1786ce1b591cSJames Smart 					"WQE: NPORT x%x oxid x%x ste %d\n",
1787ce1b591cSJames Smart 					ctxp->sid, ctxp->oxid, ctxp->state);
1788d613b6a7SJames Smart 			return NULL;
1789d613b6a7SJames Smart 		}
1790d613b6a7SJames Smart 		ctxp->wqeq = nvmewqe;
1791d613b6a7SJames Smart 		xc = 0; /* create new XRI */
1792d613b6a7SJames Smart 		nvmewqe->sli4_lxritag = NO_XRI;
1793d613b6a7SJames Smart 		nvmewqe->sli4_xritag = NO_XRI;
1794d613b6a7SJames Smart 	}
1795d613b6a7SJames Smart 
1796d613b6a7SJames Smart 	/* Sanity check */
1797d613b6a7SJames Smart 	if (((ctxp->state == LPFC_NVMET_STE_RCV) &&
1798d613b6a7SJames Smart 	    (ctxp->entry_cnt == 1)) ||
1799ce1b591cSJames Smart 	    (ctxp->state == LPFC_NVMET_STE_DATA)) {
1800d613b6a7SJames Smart 		wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
1801d613b6a7SJames Smart 	} else {
1802d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1803ce1b591cSJames Smart 				"6111 Wrong state NVMET FCP: %d  cnt %d\n",
1804ce1b591cSJames Smart 				ctxp->state, ctxp->entry_cnt);
1805d613b6a7SJames Smart 		return NULL;
1806d613b6a7SJames Smart 	}
1807d613b6a7SJames Smart 
18086c621a22SJames Smart 	sgl  = (struct sli4_sge *)ctxp->ctxbuf->sglq->sgl;
1809d613b6a7SJames Smart 	switch (rsp->op) {
1810d613b6a7SJames Smart 	case NVMET_FCOP_READDATA:
1811d613b6a7SJames Smart 	case NVMET_FCOP_READDATA_RSP:
1812d613b6a7SJames Smart 		/* Words 0 - 2 : The first sg segment */
1813d613b6a7SJames Smart 		sgel = &rsp->sg[0];
1814d613b6a7SJames Smart 		physaddr = sg_dma_address(sgel);
1815d613b6a7SJames Smart 		wqe->fcp_tsend.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
1816d613b6a7SJames Smart 		wqe->fcp_tsend.bde.tus.f.bdeSize = sg_dma_len(sgel);
1817d613b6a7SJames Smart 		wqe->fcp_tsend.bde.addrLow = cpu_to_le32(putPaddrLow(physaddr));
1818d613b6a7SJames Smart 		wqe->fcp_tsend.bde.addrHigh =
1819d613b6a7SJames Smart 			cpu_to_le32(putPaddrHigh(physaddr));
1820d613b6a7SJames Smart 
1821d613b6a7SJames Smart 		/* Word 3 */
1822d613b6a7SJames Smart 		wqe->fcp_tsend.payload_offset_len = 0;
1823d613b6a7SJames Smart 
1824d613b6a7SJames Smart 		/* Word 4 */
1825d613b6a7SJames Smart 		wqe->fcp_tsend.relative_offset = ctxp->offset;
1826d613b6a7SJames Smart 
1827d613b6a7SJames Smart 		/* Word 5 */
1828d613b6a7SJames Smart 
1829d613b6a7SJames Smart 		/* Word 6 */
1830d613b6a7SJames Smart 		bf_set(wqe_ctxt_tag, &wqe->fcp_tsend.wqe_com,
1831d613b6a7SJames Smart 		       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
1832d613b6a7SJames Smart 		bf_set(wqe_xri_tag, &wqe->fcp_tsend.wqe_com,
1833d613b6a7SJames Smart 		       nvmewqe->sli4_xritag);
1834d613b6a7SJames Smart 
1835d613b6a7SJames Smart 		/* Word 7 */
1836d613b6a7SJames Smart 		bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE);
1837d613b6a7SJames Smart 
1838d613b6a7SJames Smart 		/* Word 8 */
1839d613b6a7SJames Smart 		wqe->fcp_tsend.wqe_com.abort_tag = nvmewqe->iotag;
1840d613b6a7SJames Smart 
1841d613b6a7SJames Smart 		/* Word 9 */
1842d613b6a7SJames Smart 		bf_set(wqe_reqtag, &wqe->fcp_tsend.wqe_com, nvmewqe->iotag);
1843d613b6a7SJames Smart 		bf_set(wqe_rcvoxid, &wqe->fcp_tsend.wqe_com, ctxp->oxid);
1844d613b6a7SJames Smart 
1845d613b6a7SJames Smart 		/* Word 10 */
1846d613b6a7SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
1847d613b6a7SJames Smart 		bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1);
1848d613b6a7SJames Smart 		bf_set(wqe_iod, &wqe->fcp_tsend.wqe_com, LPFC_WQE_IOD_WRITE);
1849d613b6a7SJames Smart 		bf_set(wqe_lenloc, &wqe->fcp_tsend.wqe_com,
1850d613b6a7SJames Smart 		       LPFC_WQE_LENLOC_WORD12);
1851d613b6a7SJames Smart 		bf_set(wqe_ebde_cnt, &wqe->fcp_tsend.wqe_com, 0);
1852d613b6a7SJames Smart 		bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, xc);
1853d613b6a7SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
1854d613b6a7SJames Smart 		if (phba->cfg_nvme_oas)
1855d613b6a7SJames Smart 			bf_set(wqe_oas, &wqe->fcp_tsend.wqe_com, 1);
1856d613b6a7SJames Smart 
1857d613b6a7SJames Smart 		/* Word 11 */
1858d613b6a7SJames Smart 		bf_set(wqe_cqid, &wqe->fcp_tsend.wqe_com,
1859d613b6a7SJames Smart 		       LPFC_WQE_CQ_ID_DEFAULT);
1860d613b6a7SJames Smart 		bf_set(wqe_cmd_type, &wqe->fcp_tsend.wqe_com,
1861d613b6a7SJames Smart 		       FCP_COMMAND_TSEND);
1862d613b6a7SJames Smart 
1863d613b6a7SJames Smart 		/* Word 12 */
1864d613b6a7SJames Smart 		wqe->fcp_tsend.fcp_data_len = rsp->transfer_length;
1865d613b6a7SJames Smart 
1866d613b6a7SJames Smart 		/* Setup 2 SKIP SGEs */
1867d613b6a7SJames Smart 		sgl->addr_hi = 0;
1868d613b6a7SJames Smart 		sgl->addr_lo = 0;
1869d613b6a7SJames Smart 		sgl->word2 = 0;
1870d613b6a7SJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_SKIP);
1871d613b6a7SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
1872d613b6a7SJames Smart 		sgl->sge_len = 0;
1873d613b6a7SJames Smart 		sgl++;
1874d613b6a7SJames Smart 		sgl->addr_hi = 0;
1875d613b6a7SJames Smart 		sgl->addr_lo = 0;
1876d613b6a7SJames Smart 		sgl->word2 = 0;
1877d613b6a7SJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_SKIP);
1878d613b6a7SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
1879d613b6a7SJames Smart 		sgl->sge_len = 0;
1880d613b6a7SJames Smart 		sgl++;
1881d613b6a7SJames Smart 		if (rsp->op == NVMET_FCOP_READDATA_RSP) {
1882d613b6a7SJames Smart 			atomic_inc(&tgtp->xmt_fcp_read_rsp);
1883d613b6a7SJames Smart 			bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1);
1884d613b6a7SJames Smart 			if ((ndlp->nlp_flag & NLP_SUPPRESS_RSP) &&
1885d613b6a7SJames Smart 			    (rsp->rsplen == 12)) {
1886d613b6a7SJames Smart 				bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 1);
1887d613b6a7SJames Smart 				bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0);
1888d613b6a7SJames Smart 				bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0);
1889d613b6a7SJames Smart 				bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0);
1890d613b6a7SJames Smart 			} else {
1891d613b6a7SJames Smart 				bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
1892d613b6a7SJames Smart 				bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 1);
1893d613b6a7SJames Smart 				bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 1);
1894d613b6a7SJames Smart 				bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com,
1895d613b6a7SJames Smart 				       ((rsp->rsplen >> 2) - 1));
1896d613b6a7SJames Smart 				memcpy(&wqe->words[16], rsp->rspaddr,
1897d613b6a7SJames Smart 				       rsp->rsplen);
1898d613b6a7SJames Smart 			}
1899d613b6a7SJames Smart 		} else {
1900d613b6a7SJames Smart 			atomic_inc(&tgtp->xmt_fcp_read);
1901d613b6a7SJames Smart 
1902d613b6a7SJames Smart 			bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
1903d613b6a7SJames Smart 			bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0);
1904d613b6a7SJames Smart 			bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0);
1905d613b6a7SJames Smart 			bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 0);
1906d613b6a7SJames Smart 			bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0);
1907d613b6a7SJames Smart 		}
1908d613b6a7SJames Smart 		break;
1909d613b6a7SJames Smart 
1910d613b6a7SJames Smart 	case NVMET_FCOP_WRITEDATA:
1911d613b6a7SJames Smart 		/* Words 0 - 2 : The first sg segment */
1912771db5c0SRomain Perier 		txrdy = dma_pool_alloc(phba->txrdy_payload_pool,
1913d613b6a7SJames Smart 				       GFP_KERNEL, &physaddr);
1914d613b6a7SJames Smart 		if (!txrdy) {
1915d613b6a7SJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
1916d613b6a7SJames Smart 					"6041 Bad txrdy buffer: oxid x%x\n",
1917d613b6a7SJames Smart 					ctxp->oxid);
1918d613b6a7SJames Smart 			return NULL;
1919d613b6a7SJames Smart 		}
1920d613b6a7SJames Smart 		ctxp->txrdy = txrdy;
1921d613b6a7SJames Smart 		ctxp->txrdy_phys = physaddr;
1922d613b6a7SJames Smart 		wqe->fcp_treceive.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
1923d613b6a7SJames Smart 		wqe->fcp_treceive.bde.tus.f.bdeSize = TXRDY_PAYLOAD_LEN;
1924d613b6a7SJames Smart 		wqe->fcp_treceive.bde.addrLow =
1925d613b6a7SJames Smart 			cpu_to_le32(putPaddrLow(physaddr));
1926d613b6a7SJames Smart 		wqe->fcp_treceive.bde.addrHigh =
1927d613b6a7SJames Smart 			cpu_to_le32(putPaddrHigh(physaddr));
1928d613b6a7SJames Smart 
1929d613b6a7SJames Smart 		/* Word 3 */
1930d613b6a7SJames Smart 		wqe->fcp_treceive.payload_offset_len = TXRDY_PAYLOAD_LEN;
1931d613b6a7SJames Smart 
1932d613b6a7SJames Smart 		/* Word 4 */
1933d613b6a7SJames Smart 		wqe->fcp_treceive.relative_offset = ctxp->offset;
1934d613b6a7SJames Smart 
1935d613b6a7SJames Smart 		/* Word 5 */
1936d613b6a7SJames Smart 
1937d613b6a7SJames Smart 		/* Word 6 */
1938d613b6a7SJames Smart 		bf_set(wqe_ctxt_tag, &wqe->fcp_treceive.wqe_com,
1939d613b6a7SJames Smart 		       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
1940d613b6a7SJames Smart 		bf_set(wqe_xri_tag, &wqe->fcp_treceive.wqe_com,
1941d613b6a7SJames Smart 		       nvmewqe->sli4_xritag);
1942d613b6a7SJames Smart 
1943d613b6a7SJames Smart 		/* Word 7 */
1944d613b6a7SJames Smart 		bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0);
1945d613b6a7SJames Smart 		bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com,
1946d613b6a7SJames Smart 		       CMD_FCP_TRECEIVE64_WQE);
1947d613b6a7SJames Smart 
1948d613b6a7SJames Smart 		/* Word 8 */
1949d613b6a7SJames Smart 		wqe->fcp_treceive.wqe_com.abort_tag = nvmewqe->iotag;
1950d613b6a7SJames Smart 
1951d613b6a7SJames Smart 		/* Word 9 */
1952d613b6a7SJames Smart 		bf_set(wqe_reqtag, &wqe->fcp_treceive.wqe_com, nvmewqe->iotag);
1953d613b6a7SJames Smart 		bf_set(wqe_rcvoxid, &wqe->fcp_treceive.wqe_com, ctxp->oxid);
1954d613b6a7SJames Smart 
1955d613b6a7SJames Smart 		/* Word 10 */
1956d613b6a7SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1);
1957d613b6a7SJames Smart 		bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1);
1958d613b6a7SJames Smart 		bf_set(wqe_iod, &wqe->fcp_treceive.wqe_com, LPFC_WQE_IOD_READ);
1959d613b6a7SJames Smart 		bf_set(wqe_lenloc, &wqe->fcp_treceive.wqe_com,
1960d613b6a7SJames Smart 		       LPFC_WQE_LENLOC_WORD12);
1961d613b6a7SJames Smart 		bf_set(wqe_xc, &wqe->fcp_treceive.wqe_com, xc);
1962d613b6a7SJames Smart 		bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0);
1963d613b6a7SJames Smart 		bf_set(wqe_irsp, &wqe->fcp_treceive.wqe_com, 0);
1964d613b6a7SJames Smart 		bf_set(wqe_irsplen, &wqe->fcp_treceive.wqe_com, 0);
1965d613b6a7SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1);
1966d613b6a7SJames Smart 		if (phba->cfg_nvme_oas)
1967d613b6a7SJames Smart 			bf_set(wqe_oas, &wqe->fcp_treceive.wqe_com, 1);
1968d613b6a7SJames Smart 
1969d613b6a7SJames Smart 		/* Word 11 */
1970d613b6a7SJames Smart 		bf_set(wqe_cqid, &wqe->fcp_treceive.wqe_com,
1971d613b6a7SJames Smart 		       LPFC_WQE_CQ_ID_DEFAULT);
1972d613b6a7SJames Smart 		bf_set(wqe_cmd_type, &wqe->fcp_treceive.wqe_com,
1973d613b6a7SJames Smart 		       FCP_COMMAND_TRECEIVE);
1974d613b6a7SJames Smart 		bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
1975d613b6a7SJames Smart 
1976d613b6a7SJames Smart 		/* Word 12 */
1977d613b6a7SJames Smart 		wqe->fcp_tsend.fcp_data_len = rsp->transfer_length;
1978d613b6a7SJames Smart 
1979d613b6a7SJames Smart 		/* Setup 1 TXRDY and 1 SKIP SGE */
1980d613b6a7SJames Smart 		txrdy[0] = 0;
1981d613b6a7SJames Smart 		txrdy[1] = cpu_to_be32(rsp->transfer_length);
1982d613b6a7SJames Smart 		txrdy[2] = 0;
1983d613b6a7SJames Smart 
1984d613b6a7SJames Smart 		sgl->addr_hi = putPaddrHigh(physaddr);
1985d613b6a7SJames Smart 		sgl->addr_lo = putPaddrLow(physaddr);
1986d613b6a7SJames Smart 		sgl->word2 = 0;
1987d613b6a7SJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
1988d613b6a7SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
1989d613b6a7SJames Smart 		sgl->sge_len = cpu_to_le32(TXRDY_PAYLOAD_LEN);
1990d613b6a7SJames Smart 		sgl++;
1991d613b6a7SJames Smart 		sgl->addr_hi = 0;
1992d613b6a7SJames Smart 		sgl->addr_lo = 0;
1993d613b6a7SJames Smart 		sgl->word2 = 0;
1994d613b6a7SJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_SKIP);
1995d613b6a7SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
1996d613b6a7SJames Smart 		sgl->sge_len = 0;
1997d613b6a7SJames Smart 		sgl++;
1998d613b6a7SJames Smart 		atomic_inc(&tgtp->xmt_fcp_write);
1999d613b6a7SJames Smart 		break;
2000d613b6a7SJames Smart 
2001d613b6a7SJames Smart 	case NVMET_FCOP_RSP:
2002d613b6a7SJames Smart 		/* Words 0 - 2 */
2003d613b6a7SJames Smart 		physaddr = rsp->rspdma;
2004d613b6a7SJames Smart 		wqe->fcp_trsp.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
2005d613b6a7SJames Smart 		wqe->fcp_trsp.bde.tus.f.bdeSize = rsp->rsplen;
2006d613b6a7SJames Smart 		wqe->fcp_trsp.bde.addrLow =
2007d613b6a7SJames Smart 			cpu_to_le32(putPaddrLow(physaddr));
2008d613b6a7SJames Smart 		wqe->fcp_trsp.bde.addrHigh =
2009d613b6a7SJames Smart 			cpu_to_le32(putPaddrHigh(physaddr));
2010d613b6a7SJames Smart 
2011d613b6a7SJames Smart 		/* Word 3 */
2012d613b6a7SJames Smart 		wqe->fcp_trsp.response_len = rsp->rsplen;
2013d613b6a7SJames Smart 
2014d613b6a7SJames Smart 		/* Word 4 */
2015d613b6a7SJames Smart 		wqe->fcp_trsp.rsvd_4_5[0] = 0;
2016d613b6a7SJames Smart 
2017d613b6a7SJames Smart 
2018d613b6a7SJames Smart 		/* Word 5 */
2019d613b6a7SJames Smart 
2020d613b6a7SJames Smart 		/* Word 6 */
2021d613b6a7SJames Smart 		bf_set(wqe_ctxt_tag, &wqe->fcp_trsp.wqe_com,
2022d613b6a7SJames Smart 		       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
2023d613b6a7SJames Smart 		bf_set(wqe_xri_tag, &wqe->fcp_trsp.wqe_com,
2024d613b6a7SJames Smart 		       nvmewqe->sli4_xritag);
2025d613b6a7SJames Smart 
2026d613b6a7SJames Smart 		/* Word 7 */
2027d613b6a7SJames Smart 		bf_set(wqe_ag, &wqe->fcp_trsp.wqe_com, 1);
2028d613b6a7SJames Smart 		bf_set(wqe_cmnd, &wqe->fcp_trsp.wqe_com, CMD_FCP_TRSP64_WQE);
2029d613b6a7SJames Smart 
2030d613b6a7SJames Smart 		/* Word 8 */
2031d613b6a7SJames Smart 		wqe->fcp_trsp.wqe_com.abort_tag = nvmewqe->iotag;
2032d613b6a7SJames Smart 
2033d613b6a7SJames Smart 		/* Word 9 */
2034d613b6a7SJames Smart 		bf_set(wqe_reqtag, &wqe->fcp_trsp.wqe_com, nvmewqe->iotag);
2035d613b6a7SJames Smart 		bf_set(wqe_rcvoxid, &wqe->fcp_trsp.wqe_com, ctxp->oxid);
2036d613b6a7SJames Smart 
2037d613b6a7SJames Smart 		/* Word 10 */
2038d613b6a7SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1);
2039d613b6a7SJames Smart 		bf_set(wqe_dbde, &wqe->fcp_trsp.wqe_com, 0);
2040d613b6a7SJames Smart 		bf_set(wqe_iod, &wqe->fcp_trsp.wqe_com, LPFC_WQE_IOD_WRITE);
2041d613b6a7SJames Smart 		bf_set(wqe_lenloc, &wqe->fcp_trsp.wqe_com,
2042d613b6a7SJames Smart 		       LPFC_WQE_LENLOC_WORD3);
2043d613b6a7SJames Smart 		bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, xc);
2044d613b6a7SJames Smart 		bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1);
2045d613b6a7SJames Smart 		if (phba->cfg_nvme_oas)
2046d613b6a7SJames Smart 			bf_set(wqe_oas, &wqe->fcp_trsp.wqe_com, 1);
2047d613b6a7SJames Smart 
2048d613b6a7SJames Smart 		/* Word 11 */
2049d613b6a7SJames Smart 		bf_set(wqe_cqid, &wqe->fcp_trsp.wqe_com,
2050d613b6a7SJames Smart 		       LPFC_WQE_CQ_ID_DEFAULT);
2051d613b6a7SJames Smart 		bf_set(wqe_cmd_type, &wqe->fcp_trsp.wqe_com,
2052d613b6a7SJames Smart 		       FCP_COMMAND_TRSP);
2053d613b6a7SJames Smart 		bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
2054d613b6a7SJames Smart 
2055d613b6a7SJames Smart 		if (rsp->rsplen == LPFC_NVMET_SUCCESS_LEN) {
2056d613b6a7SJames Smart 			/* Good response - all zero's on wire */
2057d613b6a7SJames Smart 			bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 0);
2058d613b6a7SJames Smart 			bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 0);
2059d613b6a7SJames Smart 			bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com, 0);
2060d613b6a7SJames Smart 		} else {
2061d613b6a7SJames Smart 			bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 1);
2062d613b6a7SJames Smart 			bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 1);
2063d613b6a7SJames Smart 			bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com,
2064d613b6a7SJames Smart 			       ((rsp->rsplen >> 2) - 1));
2065d613b6a7SJames Smart 			memcpy(&wqe->words[16], rsp->rspaddr, rsp->rsplen);
2066d613b6a7SJames Smart 		}
2067d613b6a7SJames Smart 
2068d613b6a7SJames Smart 		/* Use rspbuf, NOT sg list */
2069d613b6a7SJames Smart 		rsp->sg_cnt = 0;
2070d613b6a7SJames Smart 		sgl->word2 = 0;
2071d613b6a7SJames Smart 		atomic_inc(&tgtp->xmt_fcp_rsp);
2072d613b6a7SJames Smart 		break;
2073d613b6a7SJames Smart 
2074d613b6a7SJames Smart 	default:
2075d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
2076d613b6a7SJames Smart 				"6064 Unknown Rsp Op %d\n",
2077d613b6a7SJames Smart 				rsp->op);
2078d613b6a7SJames Smart 		return NULL;
2079d613b6a7SJames Smart 	}
2080d613b6a7SJames Smart 
2081d613b6a7SJames Smart 	nvmewqe->retry = 1;
2082d613b6a7SJames Smart 	nvmewqe->vport = phba->pport;
2083d613b6a7SJames Smart 	nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT;
2084d613b6a7SJames Smart 	nvmewqe->context1 = ndlp;
2085d613b6a7SJames Smart 
2086d613b6a7SJames Smart 	for (i = 0; i < rsp->sg_cnt; i++) {
2087d613b6a7SJames Smart 		sgel = &rsp->sg[i];
2088d613b6a7SJames Smart 		physaddr = sg_dma_address(sgel);
2089d613b6a7SJames Smart 		cnt = sg_dma_len(sgel);
2090d613b6a7SJames Smart 		sgl->addr_hi = putPaddrHigh(physaddr);
2091d613b6a7SJames Smart 		sgl->addr_lo = putPaddrLow(physaddr);
2092d613b6a7SJames Smart 		sgl->word2 = 0;
2093d613b6a7SJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
2094d613b6a7SJames Smart 		bf_set(lpfc_sli4_sge_offset, sgl, ctxp->offset);
2095d613b6a7SJames Smart 		if ((i+1) == rsp->sg_cnt)
2096d613b6a7SJames Smart 			bf_set(lpfc_sli4_sge_last, sgl, 1);
2097d613b6a7SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
2098d613b6a7SJames Smart 		sgl->sge_len = cpu_to_le32(cnt);
2099d613b6a7SJames Smart 		sgl++;
2100d613b6a7SJames Smart 		ctxp->offset += cnt;
2101d613b6a7SJames Smart 	}
2102ce1b591cSJames Smart 	ctxp->state = LPFC_NVMET_STE_DATA;
2103ce1b591cSJames Smart 	ctxp->entry_cnt++;
2104d613b6a7SJames Smart 	return nvmewqe;
2105d613b6a7SJames Smart }
2106d613b6a7SJames Smart 
2107d613b6a7SJames Smart /**
2108d613b6a7SJames Smart  * lpfc_nvmet_sol_fcp_abort_cmp - Completion handler for ABTS
2109d613b6a7SJames Smart  * @phba: Pointer to HBA context object.
2110d613b6a7SJames Smart  * @cmdwqe: Pointer to driver command WQE object.
2111d613b6a7SJames Smart  * @wcqe: Pointer to driver response CQE object.
2112d613b6a7SJames Smart  *
2113d613b6a7SJames Smart  * The function is called from SLI ring event handler with no
2114d613b6a7SJames Smart  * lock held. This function is the completion handler for NVME ABTS for FCP cmds
2115d613b6a7SJames Smart  * The function frees memory resources used for the NVME commands.
2116d613b6a7SJames Smart  **/
2117d613b6a7SJames Smart static void
2118d613b6a7SJames Smart lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
2119d613b6a7SJames Smart 			     struct lpfc_wcqe_complete *wcqe)
2120d613b6a7SJames Smart {
2121d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
2122d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
2123d613b6a7SJames Smart 	uint32_t status, result;
212419b58d94SJames Smart 	unsigned long flags;
212519b58d94SJames Smart 	bool released = false;
2126d613b6a7SJames Smart 
2127d613b6a7SJames Smart 	ctxp = cmdwqe->context2;
2128d613b6a7SJames Smart 	status = bf_get(lpfc_wcqe_c_status, wcqe);
2129d613b6a7SJames Smart 	result = wcqe->parameter;
2130d613b6a7SJames Smart 
2131d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2132547077a4SJames Smart 	if (ctxp->flag & LPFC_NVMET_ABORT_OP)
2133547077a4SJames Smart 		atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
2134d613b6a7SJames Smart 
2135d613b6a7SJames Smart 	ctxp->state = LPFC_NVMET_STE_DONE;
213686c67379SJames Smart 
213786c67379SJames Smart 	/* Check if we already received a free context call
213886c67379SJames Smart 	 * and we have completed processing an abort situation.
213986c67379SJames Smart 	 */
214019b58d94SJames Smart 	spin_lock_irqsave(&ctxp->ctxlock, flags);
214186c67379SJames Smart 	if ((ctxp->flag & LPFC_NVMET_CTX_RLS) &&
214286c67379SJames Smart 	    !(ctxp->flag & LPFC_NVMET_XBUSY)) {
214386c67379SJames Smart 		list_del(&ctxp->list);
214419b58d94SJames Smart 		released = true;
214586c67379SJames Smart 	}
214619b58d94SJames Smart 	ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
214719b58d94SJames Smart 	spin_unlock_irqrestore(&ctxp->ctxlock, flags);
2148547077a4SJames Smart 	atomic_inc(&tgtp->xmt_abort_rsp);
214919b58d94SJames Smart 
215086c67379SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
215186c67379SJames Smart 			"6165 ABORT cmpl: xri x%x flg x%x (%d) "
215286c67379SJames Smart 			"WCQE: %08x %08x %08x %08x\n",
215386c67379SJames Smart 			ctxp->oxid, ctxp->flag, released,
215486c67379SJames Smart 			wcqe->word0, wcqe->total_data_placed,
215586c67379SJames Smart 			result, wcqe->word3);
215686c67379SJames Smart 
21576c621a22SJames Smart 	cmdwqe->context2 = NULL;
21586c621a22SJames Smart 	cmdwqe->context3 = NULL;
215919b58d94SJames Smart 	/*
216019b58d94SJames Smart 	 * if transport has released ctx, then can reuse it. Otherwise,
216119b58d94SJames Smart 	 * will be recycled by transport release call.
216219b58d94SJames Smart 	 */
216319b58d94SJames Smart 	if (released)
21646c621a22SJames Smart 		lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
2165d613b6a7SJames Smart 
21666c621a22SJames Smart 	/* This is the iocbq for the abort, not the command */
2167d613b6a7SJames Smart 	lpfc_sli_release_iocbq(phba, cmdwqe);
216886c67379SJames Smart 
216986c67379SJames Smart 	/* Since iaab/iaar are NOT set, there is no work left.
217086c67379SJames Smart 	 * For LPFC_NVMET_XBUSY, lpfc_sli4_nvmet_xri_aborted
217186c67379SJames Smart 	 * should have been called already.
217286c67379SJames Smart 	 */
2173d613b6a7SJames Smart }
2174d613b6a7SJames Smart 
2175d613b6a7SJames Smart /**
217686c67379SJames Smart  * lpfc_nvmet_unsol_fcp_abort_cmp - Completion handler for ABTS
2177d613b6a7SJames Smart  * @phba: Pointer to HBA context object.
2178d613b6a7SJames Smart  * @cmdwqe: Pointer to driver command WQE object.
2179d613b6a7SJames Smart  * @wcqe: Pointer to driver response CQE object.
2180d613b6a7SJames Smart  *
2181d613b6a7SJames Smart  * The function is called from SLI ring event handler with no
2182d613b6a7SJames Smart  * lock held. This function is the completion handler for NVME ABTS for FCP cmds
2183d613b6a7SJames Smart  * The function frees memory resources used for the NVME commands.
2184d613b6a7SJames Smart  **/
2185d613b6a7SJames Smart static void
218686c67379SJames Smart lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
2187d613b6a7SJames Smart 			       struct lpfc_wcqe_complete *wcqe)
2188d613b6a7SJames Smart {
2189d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
2190d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
219119b58d94SJames Smart 	unsigned long flags;
2192d613b6a7SJames Smart 	uint32_t status, result;
219319b58d94SJames Smart 	bool released = false;
2194d613b6a7SJames Smart 
2195d613b6a7SJames Smart 	ctxp = cmdwqe->context2;
2196d613b6a7SJames Smart 	status = bf_get(lpfc_wcqe_c_status, wcqe);
2197d613b6a7SJames Smart 	result = wcqe->parameter;
2198d613b6a7SJames Smart 
219986c67379SJames Smart 	if (!ctxp) {
220086c67379SJames Smart 		/* if context is clear, related io alrady complete */
2201d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
220286c67379SJames Smart 				"6070 ABTS cmpl: WCQE: %08x %08x %08x %08x\n",
220386c67379SJames Smart 				wcqe->word0, wcqe->total_data_placed,
2204d613b6a7SJames Smart 				result, wcqe->word3);
220586c67379SJames Smart 		return;
220686c67379SJames Smart 	}
2207d613b6a7SJames Smart 
220878e1d200SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
220978e1d200SJames Smart 	if (ctxp->flag & LPFC_NVMET_ABORT_OP)
221078e1d200SJames Smart 		atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
221178e1d200SJames Smart 
2212d613b6a7SJames Smart 	/* Sanity check */
2213d613b6a7SJames Smart 	if (ctxp->state != LPFC_NVMET_STE_ABORT) {
2214d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
221586c67379SJames Smart 				"6112 ABTS Wrong state:%d oxid x%x\n",
2216d613b6a7SJames Smart 				ctxp->state, ctxp->oxid);
2217d613b6a7SJames Smart 	}
221886c67379SJames Smart 
221986c67379SJames Smart 	/* Check if we already received a free context call
222086c67379SJames Smart 	 * and we have completed processing an abort situation.
222186c67379SJames Smart 	 */
2222d613b6a7SJames Smart 	ctxp->state = LPFC_NVMET_STE_DONE;
222319b58d94SJames Smart 	spin_lock_irqsave(&ctxp->ctxlock, flags);
222486c67379SJames Smart 	if ((ctxp->flag & LPFC_NVMET_CTX_RLS) &&
222586c67379SJames Smart 	    !(ctxp->flag & LPFC_NVMET_XBUSY)) {
222686c67379SJames Smart 		list_del(&ctxp->list);
222719b58d94SJames Smart 		released = true;
222886c67379SJames Smart 	}
222919b58d94SJames Smart 	ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
223019b58d94SJames Smart 	spin_unlock_irqrestore(&ctxp->ctxlock, flags);
2231547077a4SJames Smart 	atomic_inc(&tgtp->xmt_abort_rsp);
223219b58d94SJames Smart 
223386c67379SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
223486c67379SJames Smart 			"6316 ABTS cmpl xri x%x flg x%x (%x) "
223586c67379SJames Smart 			"WCQE: %08x %08x %08x %08x\n",
223686c67379SJames Smart 			ctxp->oxid, ctxp->flag, released,
223786c67379SJames Smart 			wcqe->word0, wcqe->total_data_placed,
223886c67379SJames Smart 			result, wcqe->word3);
22396c621a22SJames Smart 
22406c621a22SJames Smart 	cmdwqe->context2 = NULL;
22416c621a22SJames Smart 	cmdwqe->context3 = NULL;
224219b58d94SJames Smart 	/*
224319b58d94SJames Smart 	 * if transport has released ctx, then can reuse it. Otherwise,
224419b58d94SJames Smart 	 * will be recycled by transport release call.
224519b58d94SJames Smart 	 */
224619b58d94SJames Smart 	if (released)
22476c621a22SJames Smart 		lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
224886c67379SJames Smart 
224986c67379SJames Smart 	/* Since iaab/iaar are NOT set, there is no work left.
225086c67379SJames Smart 	 * For LPFC_NVMET_XBUSY, lpfc_sli4_nvmet_xri_aborted
225186c67379SJames Smart 	 * should have been called already.
225286c67379SJames Smart 	 */
2253d613b6a7SJames Smart }
2254d613b6a7SJames Smart 
2255d613b6a7SJames Smart /**
2256d613b6a7SJames Smart  * lpfc_nvmet_xmt_ls_abort_cmp - Completion handler for ABTS
2257d613b6a7SJames Smart  * @phba: Pointer to HBA context object.
2258d613b6a7SJames Smart  * @cmdwqe: Pointer to driver command WQE object.
2259d613b6a7SJames Smart  * @wcqe: Pointer to driver response CQE object.
2260d613b6a7SJames Smart  *
2261d613b6a7SJames Smart  * The function is called from SLI ring event handler with no
2262d613b6a7SJames Smart  * lock held. This function is the completion handler for NVME ABTS for LS cmds
2263d613b6a7SJames Smart  * The function frees memory resources used for the NVME commands.
2264d613b6a7SJames Smart  **/
2265d613b6a7SJames Smart static void
2266d613b6a7SJames Smart lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
2267d613b6a7SJames Smart 			    struct lpfc_wcqe_complete *wcqe)
2268d613b6a7SJames Smart {
2269d613b6a7SJames Smart 	struct lpfc_nvmet_rcv_ctx *ctxp;
2270d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
2271d613b6a7SJames Smart 	uint32_t status, result;
2272d613b6a7SJames Smart 
2273d613b6a7SJames Smart 	ctxp = cmdwqe->context2;
2274d613b6a7SJames Smart 	status = bf_get(lpfc_wcqe_c_status, wcqe);
2275d613b6a7SJames Smart 	result = wcqe->parameter;
2276d613b6a7SJames Smart 
2277d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2278547077a4SJames Smart 	atomic_inc(&tgtp->xmt_ls_abort_cmpl);
2279d613b6a7SJames Smart 
2280d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
2281d613b6a7SJames Smart 			"6083 Abort cmpl: ctx %p WCQE:%08x %08x %08x %08x\n",
2282d613b6a7SJames Smart 			ctxp, wcqe->word0, wcqe->total_data_placed,
2283d613b6a7SJames Smart 			result, wcqe->word3);
2284d613b6a7SJames Smart 
2285ce1b591cSJames Smart 	if (!ctxp) {
2286ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
2287ce1b591cSJames Smart 				"6415 NVMET LS Abort No ctx: WCQE: "
2288ce1b591cSJames Smart 				 "%08x %08x %08x %08x\n",
2289ce1b591cSJames Smart 				wcqe->word0, wcqe->total_data_placed,
2290ce1b591cSJames Smart 				result, wcqe->word3);
2291ce1b591cSJames Smart 
2292ce1b591cSJames Smart 		lpfc_sli_release_iocbq(phba, cmdwqe);
2293ce1b591cSJames Smart 		return;
2294ce1b591cSJames Smart 	}
2295ce1b591cSJames Smart 
2296ce1b591cSJames Smart 	if (ctxp->state != LPFC_NVMET_STE_LS_ABORT) {
2297ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
2298ce1b591cSJames Smart 				"6416 NVMET LS abort cmpl state mismatch: "
2299ce1b591cSJames Smart 				"oxid x%x: %d %d\n",
2300ce1b591cSJames Smart 				ctxp->oxid, ctxp->state, ctxp->entry_cnt);
2301ce1b591cSJames Smart 	}
2302ce1b591cSJames Smart 
2303d613b6a7SJames Smart 	cmdwqe->context2 = NULL;
2304d613b6a7SJames Smart 	cmdwqe->context3 = NULL;
2305d613b6a7SJames Smart 	lpfc_sli_release_iocbq(phba, cmdwqe);
2306d613b6a7SJames Smart 	kfree(ctxp);
2307d613b6a7SJames Smart }
2308d613b6a7SJames Smart 
2309d613b6a7SJames Smart static int
2310d613b6a7SJames Smart lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
2311d613b6a7SJames Smart 			     struct lpfc_nvmet_rcv_ctx *ctxp,
2312d613b6a7SJames Smart 			     uint32_t sid, uint16_t xri)
2313d613b6a7SJames Smart {
2314d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
2315d613b6a7SJames Smart 	struct lpfc_iocbq *abts_wqeq;
2316d613b6a7SJames Smart 	union lpfc_wqe *wqe_abts;
2317d613b6a7SJames Smart 	struct lpfc_nodelist *ndlp;
2318d613b6a7SJames Smart 
2319d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
232086c67379SJames Smart 			"6067 ABTS: sid %x xri x%x/x%x\n",
2321318083adSJames Smart 			sid, xri, ctxp->wqeq->sli4_xritag);
2322d613b6a7SJames Smart 
2323d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2324d613b6a7SJames Smart 
2325d613b6a7SJames Smart 	ndlp = lpfc_findnode_did(phba->pport, sid);
2326d613b6a7SJames Smart 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
2327d613b6a7SJames Smart 	    ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2328d613b6a7SJames Smart 	    (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
2329d613b6a7SJames Smart 		atomic_inc(&tgtp->xmt_abort_rsp_error);
2330ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
2331d613b6a7SJames Smart 				"6134 Drop ABTS - wrong NDLP state x%x.\n",
2332b5ccc7d6SJames Smart 				(ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE);
2333d613b6a7SJames Smart 
2334d613b6a7SJames Smart 		/* No failure to an ABTS request. */
2335d613b6a7SJames Smart 		return 0;
2336d613b6a7SJames Smart 	}
2337d613b6a7SJames Smart 
2338d613b6a7SJames Smart 	abts_wqeq = ctxp->wqeq;
2339d613b6a7SJames Smart 	wqe_abts = &abts_wqeq->wqe;
2340d613b6a7SJames Smart 
2341d613b6a7SJames Smart 	/*
2342d613b6a7SJames Smart 	 * Since we zero the whole WQE, we need to ensure we set the WQE fields
2343d613b6a7SJames Smart 	 * that were initialized in lpfc_sli4_nvmet_alloc.
2344d613b6a7SJames Smart 	 */
2345d613b6a7SJames Smart 	memset(wqe_abts, 0, sizeof(union lpfc_wqe));
2346d613b6a7SJames Smart 
2347d613b6a7SJames Smart 	/* Word 5 */
2348d613b6a7SJames Smart 	bf_set(wqe_dfctl, &wqe_abts->xmit_sequence.wge_ctl, 0);
2349d613b6a7SJames Smart 	bf_set(wqe_ls, &wqe_abts->xmit_sequence.wge_ctl, 1);
2350d613b6a7SJames Smart 	bf_set(wqe_la, &wqe_abts->xmit_sequence.wge_ctl, 0);
2351d613b6a7SJames Smart 	bf_set(wqe_rctl, &wqe_abts->xmit_sequence.wge_ctl, FC_RCTL_BA_ABTS);
2352d613b6a7SJames Smart 	bf_set(wqe_type, &wqe_abts->xmit_sequence.wge_ctl, FC_TYPE_BLS);
2353d613b6a7SJames Smart 
2354d613b6a7SJames Smart 	/* Word 6 */
2355d613b6a7SJames Smart 	bf_set(wqe_ctxt_tag, &wqe_abts->xmit_sequence.wqe_com,
2356d613b6a7SJames Smart 	       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
2357d613b6a7SJames Smart 	bf_set(wqe_xri_tag, &wqe_abts->xmit_sequence.wqe_com,
2358d613b6a7SJames Smart 	       abts_wqeq->sli4_xritag);
2359d613b6a7SJames Smart 
2360d613b6a7SJames Smart 	/* Word 7 */
2361d613b6a7SJames Smart 	bf_set(wqe_cmnd, &wqe_abts->xmit_sequence.wqe_com,
2362d613b6a7SJames Smart 	       CMD_XMIT_SEQUENCE64_WQE);
2363d613b6a7SJames Smart 	bf_set(wqe_ct, &wqe_abts->xmit_sequence.wqe_com, SLI4_CT_RPI);
2364d613b6a7SJames Smart 	bf_set(wqe_class, &wqe_abts->xmit_sequence.wqe_com, CLASS3);
2365d613b6a7SJames Smart 	bf_set(wqe_pu, &wqe_abts->xmit_sequence.wqe_com, 0);
2366d613b6a7SJames Smart 
2367d613b6a7SJames Smart 	/* Word 8 */
2368d613b6a7SJames Smart 	wqe_abts->xmit_sequence.wqe_com.abort_tag = abts_wqeq->iotag;
2369d613b6a7SJames Smart 
2370d613b6a7SJames Smart 	/* Word 9 */
2371d613b6a7SJames Smart 	bf_set(wqe_reqtag, &wqe_abts->xmit_sequence.wqe_com, abts_wqeq->iotag);
2372d613b6a7SJames Smart 	/* Needs to be set by caller */
2373d613b6a7SJames Smart 	bf_set(wqe_rcvoxid, &wqe_abts->xmit_sequence.wqe_com, xri);
2374d613b6a7SJames Smart 
2375d613b6a7SJames Smart 	/* Word 10 */
2376d613b6a7SJames Smart 	bf_set(wqe_dbde, &wqe_abts->xmit_sequence.wqe_com, 1);
2377d613b6a7SJames Smart 	bf_set(wqe_iod, &wqe_abts->xmit_sequence.wqe_com, LPFC_WQE_IOD_WRITE);
2378d613b6a7SJames Smart 	bf_set(wqe_lenloc, &wqe_abts->xmit_sequence.wqe_com,
2379d613b6a7SJames Smart 	       LPFC_WQE_LENLOC_WORD12);
2380d613b6a7SJames Smart 	bf_set(wqe_ebde_cnt, &wqe_abts->xmit_sequence.wqe_com, 0);
2381d613b6a7SJames Smart 	bf_set(wqe_qosd, &wqe_abts->xmit_sequence.wqe_com, 0);
2382d613b6a7SJames Smart 
2383d613b6a7SJames Smart 	/* Word 11 */
2384d613b6a7SJames Smart 	bf_set(wqe_cqid, &wqe_abts->xmit_sequence.wqe_com,
2385d613b6a7SJames Smart 	       LPFC_WQE_CQ_ID_DEFAULT);
2386d613b6a7SJames Smart 	bf_set(wqe_cmd_type, &wqe_abts->xmit_sequence.wqe_com,
2387d613b6a7SJames Smart 	       OTHER_COMMAND);
2388d613b6a7SJames Smart 
2389d613b6a7SJames Smart 	abts_wqeq->vport = phba->pport;
2390d613b6a7SJames Smart 	abts_wqeq->context1 = ndlp;
2391d613b6a7SJames Smart 	abts_wqeq->context2 = ctxp;
2392d613b6a7SJames Smart 	abts_wqeq->context3 = NULL;
2393d613b6a7SJames Smart 	abts_wqeq->rsvd2 = 0;
2394d613b6a7SJames Smart 	/* hba_wqidx should already be setup from command we are aborting */
2395d613b6a7SJames Smart 	abts_wqeq->iocb.ulpCommand = CMD_XMIT_SEQUENCE64_CR;
2396d613b6a7SJames Smart 	abts_wqeq->iocb.ulpLe = 1;
2397d613b6a7SJames Smart 
2398d613b6a7SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
2399d613b6a7SJames Smart 			"6069 Issue ABTS to xri x%x reqtag x%x\n",
2400d613b6a7SJames Smart 			xri, abts_wqeq->iotag);
2401d613b6a7SJames Smart 	return 1;
2402d613b6a7SJames Smart }
2403d613b6a7SJames Smart 
2404d613b6a7SJames Smart static int
2405d613b6a7SJames Smart lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
2406d613b6a7SJames Smart 			       struct lpfc_nvmet_rcv_ctx *ctxp,
2407d613b6a7SJames Smart 			       uint32_t sid, uint16_t xri)
2408d613b6a7SJames Smart {
2409d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
2410d613b6a7SJames Smart 	struct lpfc_iocbq *abts_wqeq;
2411d613b6a7SJames Smart 	union lpfc_wqe *abts_wqe;
2412d613b6a7SJames Smart 	struct lpfc_nodelist *ndlp;
2413d613b6a7SJames Smart 	unsigned long flags;
2414d613b6a7SJames Smart 	int rc;
2415d613b6a7SJames Smart 
2416d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2417d613b6a7SJames Smart 	if (!ctxp->wqeq) {
24186c621a22SJames Smart 		ctxp->wqeq = ctxp->ctxbuf->iocbq;
2419d613b6a7SJames Smart 		ctxp->wqeq->hba_wqidx = 0;
2420d613b6a7SJames Smart 	}
2421d613b6a7SJames Smart 
2422d613b6a7SJames Smart 	ndlp = lpfc_findnode_did(phba->pport, sid);
2423d613b6a7SJames Smart 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
2424d613b6a7SJames Smart 	    ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2425d613b6a7SJames Smart 	    (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
2426d613b6a7SJames Smart 		atomic_inc(&tgtp->xmt_abort_rsp_error);
2427ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
242886c67379SJames Smart 				"6160 Drop ABORT - wrong NDLP state x%x.\n",
2429b5ccc7d6SJames Smart 				(ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE);
2430d613b6a7SJames Smart 
2431d613b6a7SJames Smart 		/* No failure to an ABTS request. */
243286c67379SJames Smart 		ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
2433d613b6a7SJames Smart 		return 0;
2434d613b6a7SJames Smart 	}
2435d613b6a7SJames Smart 
2436d613b6a7SJames Smart 	/* Issue ABTS for this WQE based on iotag */
2437d613b6a7SJames Smart 	ctxp->abort_wqeq = lpfc_sli_get_iocbq(phba);
2438d613b6a7SJames Smart 	if (!ctxp->abort_wqeq) {
2439547077a4SJames Smart 		atomic_inc(&tgtp->xmt_abort_rsp_error);
2440ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
244186c67379SJames Smart 				"6161 ABORT failed: No wqeqs: "
2442d613b6a7SJames Smart 				"xri: x%x\n", ctxp->oxid);
2443d613b6a7SJames Smart 		/* No failure to an ABTS request. */
244486c67379SJames Smart 		ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
2445d613b6a7SJames Smart 		return 0;
2446d613b6a7SJames Smart 	}
2447d613b6a7SJames Smart 	abts_wqeq = ctxp->abort_wqeq;
2448d613b6a7SJames Smart 	abts_wqe = &abts_wqeq->wqe;
2449d613b6a7SJames Smart 	ctxp->state = LPFC_NVMET_STE_ABORT;
2450d613b6a7SJames Smart 
2451d613b6a7SJames Smart 	/* Announce entry to new IO submit field. */
245286c67379SJames Smart 	lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
245386c67379SJames Smart 			"6162 ABORT Request to rport DID x%06x "
2454d613b6a7SJames Smart 			"for xri x%x x%x\n",
2455d613b6a7SJames Smart 			ctxp->sid, ctxp->oxid, ctxp->wqeq->sli4_xritag);
2456d613b6a7SJames Smart 
2457d613b6a7SJames Smart 	/* If the hba is getting reset, this flag is set.  It is
2458d613b6a7SJames Smart 	 * cleared when the reset is complete and rings reestablished.
2459d613b6a7SJames Smart 	 */
2460d613b6a7SJames Smart 	spin_lock_irqsave(&phba->hbalock, flags);
2461d613b6a7SJames Smart 	/* driver queued commands are in process of being flushed */
2462d613b6a7SJames Smart 	if (phba->hba_flag & HBA_NVME_IOQ_FLUSH) {
2463d613b6a7SJames Smart 		spin_unlock_irqrestore(&phba->hbalock, flags);
2464547077a4SJames Smart 		atomic_inc(&tgtp->xmt_abort_rsp_error);
2465d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
2466d613b6a7SJames Smart 				"6163 Driver in reset cleanup - flushing "
2467d613b6a7SJames Smart 				"NVME Req now. hba_flag x%x oxid x%x\n",
2468d613b6a7SJames Smart 				phba->hba_flag, ctxp->oxid);
2469d613b6a7SJames Smart 		lpfc_sli_release_iocbq(phba, abts_wqeq);
247086c67379SJames Smart 		ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
2471d613b6a7SJames Smart 		return 0;
2472d613b6a7SJames Smart 	}
2473d613b6a7SJames Smart 
2474d613b6a7SJames Smart 	/* Outstanding abort is in progress */
2475d613b6a7SJames Smart 	if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) {
2476d613b6a7SJames Smart 		spin_unlock_irqrestore(&phba->hbalock, flags);
2477547077a4SJames Smart 		atomic_inc(&tgtp->xmt_abort_rsp_error);
2478d613b6a7SJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
2479d613b6a7SJames Smart 				"6164 Outstanding NVME I/O Abort Request "
2480d613b6a7SJames Smart 				"still pending on oxid x%x\n",
2481d613b6a7SJames Smart 				ctxp->oxid);
2482d613b6a7SJames Smart 		lpfc_sli_release_iocbq(phba, abts_wqeq);
248386c67379SJames Smart 		ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
2484d613b6a7SJames Smart 		return 0;
2485d613b6a7SJames Smart 	}
2486d613b6a7SJames Smart 
2487d613b6a7SJames Smart 	/* Ready - mark outstanding as aborted by driver. */
2488d613b6a7SJames Smart 	abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED;
2489d613b6a7SJames Smart 
2490d613b6a7SJames Smart 	/* WQEs are reused.  Clear stale data and set key fields to
2491d613b6a7SJames Smart 	 * zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
2492d613b6a7SJames Smart 	 */
2493d613b6a7SJames Smart 	memset(abts_wqe, 0, sizeof(union lpfc_wqe));
2494d613b6a7SJames Smart 
2495d613b6a7SJames Smart 	/* word 3 */
2496d613b6a7SJames Smart 	bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG);
2497d613b6a7SJames Smart 
2498d613b6a7SJames Smart 	/* word 7 */
2499d613b6a7SJames Smart 	bf_set(wqe_ct, &abts_wqe->abort_cmd.wqe_com, 0);
2500d613b6a7SJames Smart 	bf_set(wqe_cmnd, &abts_wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
2501d613b6a7SJames Smart 
2502d613b6a7SJames Smart 	/* word 8 - tell the FW to abort the IO associated with this
2503d613b6a7SJames Smart 	 * outstanding exchange ID.
2504d613b6a7SJames Smart 	 */
2505d613b6a7SJames Smart 	abts_wqe->abort_cmd.wqe_com.abort_tag = ctxp->wqeq->sli4_xritag;
2506d613b6a7SJames Smart 
2507d613b6a7SJames Smart 	/* word 9 - this is the iotag for the abts_wqe completion. */
2508d613b6a7SJames Smart 	bf_set(wqe_reqtag, &abts_wqe->abort_cmd.wqe_com,
2509d613b6a7SJames Smart 	       abts_wqeq->iotag);
2510d613b6a7SJames Smart 
2511d613b6a7SJames Smart 	/* word 10 */
2512d613b6a7SJames Smart 	bf_set(wqe_qosd, &abts_wqe->abort_cmd.wqe_com, 1);
2513d613b6a7SJames Smart 	bf_set(wqe_lenloc, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
2514d613b6a7SJames Smart 
2515d613b6a7SJames Smart 	/* word 11 */
2516d613b6a7SJames Smart 	bf_set(wqe_cmd_type, &abts_wqe->abort_cmd.wqe_com, OTHER_COMMAND);
2517d613b6a7SJames Smart 	bf_set(wqe_wqec, &abts_wqe->abort_cmd.wqe_com, 1);
2518d613b6a7SJames Smart 	bf_set(wqe_cqid, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
2519d613b6a7SJames Smart 
2520d613b6a7SJames Smart 	/* ABTS WQE must go to the same WQ as the WQE to be aborted */
2521d613b6a7SJames Smart 	abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx;
2522d613b6a7SJames Smart 	abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp;
2523d613b6a7SJames Smart 	abts_wqeq->iocb_cmpl = 0;
2524d613b6a7SJames Smart 	abts_wqeq->iocb_flag |= LPFC_IO_NVME;
2525d613b6a7SJames Smart 	abts_wqeq->context2 = ctxp;
25264550f9c7SJames Smart 	abts_wqeq->vport = phba->pport;
2527d613b6a7SJames Smart 	rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, abts_wqeq);
2528d613b6a7SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, flags);
2529547077a4SJames Smart 	if (rc == WQE_SUCCESS) {
2530547077a4SJames Smart 		atomic_inc(&tgtp->xmt_abort_sol);
2531d613b6a7SJames Smart 		return 0;
2532547077a4SJames Smart 	}
2533d613b6a7SJames Smart 
2534547077a4SJames Smart 	atomic_inc(&tgtp->xmt_abort_rsp_error);
253586c67379SJames Smart 	ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
2536d613b6a7SJames Smart 	lpfc_sli_release_iocbq(phba, abts_wqeq);
253786c67379SJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
253886c67379SJames Smart 			"6166 Failed ABORT issue_wqe with status x%x "
2539d613b6a7SJames Smart 			"for oxid x%x.\n",
2540d613b6a7SJames Smart 			rc, ctxp->oxid);
2541d613b6a7SJames Smart 	return 1;
2542d613b6a7SJames Smart }
2543d613b6a7SJames Smart 
2544d613b6a7SJames Smart 
2545d613b6a7SJames Smart static int
2546d613b6a7SJames Smart lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
2547d613b6a7SJames Smart 				 struct lpfc_nvmet_rcv_ctx *ctxp,
2548d613b6a7SJames Smart 				 uint32_t sid, uint16_t xri)
2549d613b6a7SJames Smart {
2550d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
2551d613b6a7SJames Smart 	struct lpfc_iocbq *abts_wqeq;
2552d613b6a7SJames Smart 	unsigned long flags;
2553d613b6a7SJames Smart 	int rc;
2554d613b6a7SJames Smart 
2555d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2556d613b6a7SJames Smart 	if (!ctxp->wqeq) {
25576c621a22SJames Smart 		ctxp->wqeq = ctxp->ctxbuf->iocbq;
2558d613b6a7SJames Smart 		ctxp->wqeq->hba_wqidx = 0;
2559d613b6a7SJames Smart 	}
2560d613b6a7SJames Smart 
2561ce1b591cSJames Smart 	if (ctxp->state == LPFC_NVMET_STE_FREE) {
2562ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
2563ce1b591cSJames Smart 				"6417 NVMET ABORT ctx freed %d %d oxid x%x\n",
2564ce1b591cSJames Smart 				ctxp->state, ctxp->entry_cnt, ctxp->oxid);
2565ce1b591cSJames Smart 		rc = WQE_BUSY;
2566ce1b591cSJames Smart 		goto aerr;
2567ce1b591cSJames Smart 	}
2568ce1b591cSJames Smart 	ctxp->state = LPFC_NVMET_STE_ABORT;
2569ce1b591cSJames Smart 	ctxp->entry_cnt++;
2570d613b6a7SJames Smart 	rc = lpfc_nvmet_unsol_issue_abort(phba, ctxp, sid, xri);
2571d613b6a7SJames Smart 	if (rc == 0)
2572d613b6a7SJames Smart 		goto aerr;
2573d613b6a7SJames Smart 
2574d613b6a7SJames Smart 	spin_lock_irqsave(&phba->hbalock, flags);
2575d613b6a7SJames Smart 	abts_wqeq = ctxp->wqeq;
257686c67379SJames Smart 	abts_wqeq->wqe_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp;
257786c67379SJames Smart 	abts_wqeq->iocb_cmpl = NULL;
2578d613b6a7SJames Smart 	abts_wqeq->iocb_flag |= LPFC_IO_NVMET;
2579d613b6a7SJames Smart 	rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, abts_wqeq);
2580d613b6a7SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, flags);
2581d613b6a7SJames Smart 	if (rc == WQE_SUCCESS) {
2582d613b6a7SJames Smart 		return 0;
2583d613b6a7SJames Smart 	}
2584d613b6a7SJames Smart 
2585d613b6a7SJames Smart aerr:
258686c67379SJames Smart 	ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
2587d613b6a7SJames Smart 	atomic_inc(&tgtp->xmt_abort_rsp_error);
2588ce1b591cSJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
2589d613b6a7SJames Smart 			"6135 Failed to Issue ABTS for oxid x%x. Status x%x\n",
2590d613b6a7SJames Smart 			ctxp->oxid, rc);
2591d613b6a7SJames Smart 	return 1;
2592d613b6a7SJames Smart }
2593d613b6a7SJames Smart 
2594d613b6a7SJames Smart static int
2595d613b6a7SJames Smart lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
2596d613b6a7SJames Smart 				struct lpfc_nvmet_rcv_ctx *ctxp,
2597d613b6a7SJames Smart 				uint32_t sid, uint16_t xri)
2598d613b6a7SJames Smart {
2599d613b6a7SJames Smart 	struct lpfc_nvmet_tgtport *tgtp;
2600d613b6a7SJames Smart 	struct lpfc_iocbq *abts_wqeq;
2601d613b6a7SJames Smart 	union lpfc_wqe *wqe_abts;
2602d613b6a7SJames Smart 	unsigned long flags;
2603d613b6a7SJames Smart 	int rc;
2604d613b6a7SJames Smart 
2605ce1b591cSJames Smart 	if ((ctxp->state == LPFC_NVMET_STE_LS_RCV && ctxp->entry_cnt == 1) ||
2606ce1b591cSJames Smart 	    (ctxp->state == LPFC_NVMET_STE_LS_RSP && ctxp->entry_cnt == 2)) {
2607ce1b591cSJames Smart 		ctxp->state = LPFC_NVMET_STE_LS_ABORT;
2608ce1b591cSJames Smart 		ctxp->entry_cnt++;
2609ce1b591cSJames Smart 	} else {
2610ce1b591cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
2611ce1b591cSJames Smart 				"6418 NVMET LS abort state mismatch "
2612ce1b591cSJames Smart 				"IO x%x: %d %d\n",
2613ce1b591cSJames Smart 				ctxp->oxid, ctxp->state, ctxp->entry_cnt);
2614ce1b591cSJames Smart 		ctxp->state = LPFC_NVMET_STE_LS_ABORT;
2615ce1b591cSJames Smart 	}
2616ce1b591cSJames Smart 
2617d613b6a7SJames Smart 	tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
2618d613b6a7SJames Smart 	if (!ctxp->wqeq) {
2619d613b6a7SJames Smart 		/* Issue ABTS for this WQE based on iotag */
2620d613b6a7SJames Smart 		ctxp->wqeq = lpfc_sli_get_iocbq(phba);
2621d613b6a7SJames Smart 		if (!ctxp->wqeq) {
2622ce1b591cSJames Smart 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
2623d613b6a7SJames Smart 					"6068 Abort failed: No wqeqs: "
2624d613b6a7SJames Smart 					"xri: x%x\n", xri);
2625d613b6a7SJames Smart 			/* No failure to an ABTS request. */
2626d613b6a7SJames Smart 			kfree(ctxp);
2627d613b6a7SJames Smart 			return 0;
2628d613b6a7SJames Smart 		}
2629d613b6a7SJames Smart 	}
2630d613b6a7SJames Smart 	abts_wqeq = ctxp->wqeq;
2631d613b6a7SJames Smart 	wqe_abts = &abts_wqeq->wqe;
26326c621a22SJames Smart 
2633ce1b591cSJames Smart 	if (lpfc_nvmet_unsol_issue_abort(phba, ctxp, sid, xri) == 0) {
2634ce1b591cSJames Smart 		rc = WQE_BUSY;
2635ce1b591cSJames Smart 		goto out;
2636ce1b591cSJames Smart 	}
2637d613b6a7SJames Smart 
2638d613b6a7SJames Smart 	spin_lock_irqsave(&phba->hbalock, flags);
2639d613b6a7SJames Smart 	abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp;
2640d613b6a7SJames Smart 	abts_wqeq->iocb_cmpl = 0;
2641d613b6a7SJames Smart 	abts_wqeq->iocb_flag |=  LPFC_IO_NVME_LS;
2642d613b6a7SJames Smart 	rc = lpfc_sli4_issue_wqe(phba, LPFC_ELS_RING, abts_wqeq);
2643d613b6a7SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, flags);
2644d613b6a7SJames Smart 	if (rc == WQE_SUCCESS) {
2645547077a4SJames Smart 		atomic_inc(&tgtp->xmt_abort_unsol);
2646d613b6a7SJames Smart 		return 0;
2647d613b6a7SJames Smart 	}
2648ce1b591cSJames Smart out:
2649d613b6a7SJames Smart 	atomic_inc(&tgtp->xmt_abort_rsp_error);
2650d613b6a7SJames Smart 	abts_wqeq->context2 = NULL;
2651d613b6a7SJames Smart 	abts_wqeq->context3 = NULL;
2652d613b6a7SJames Smart 	lpfc_sli_release_iocbq(phba, abts_wqeq);
2653d613b6a7SJames Smart 	kfree(ctxp);
2654ce1b591cSJames Smart 	lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
2655d613b6a7SJames Smart 			"6056 Failed to Issue ABTS. Status x%x\n", rc);
2656d613b6a7SJames Smart 	return 0;
2657d613b6a7SJames Smart }
2658