xref: /linux/drivers/scsi/lpfc/lpfc_scsi.c (revision 7ec462100ef9142344ddbf86f2c3008b97acddbe)
1d85296cfSJames Smart /*******************************************************************
2dea3101eS  * This file is part of the Emulex Linux Device Driver for         *
3c44ce173SJames.Smart@Emulex.Com  * Fibre Channel Host Bus Adapters.                                *
4ea4044e4SJustin Tee  * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
53e21d1cbSJames Smart  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
651f4ca3cSJames Smart  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
7c44ce173SJames.Smart@Emulex.Com  * EMULEX and SLI are trademarks of Emulex.                        *
8d080abe0SJames Smart  * www.broadcom.com                                                *
9c44ce173SJames.Smart@Emulex.Com  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
10dea3101eS  *                                                                 *
11dea3101eS  * This program is free software; you can redistribute it and/or   *
12c44ce173SJames.Smart@Emulex.Com  * modify it under the terms of version 2 of the GNU General       *
13c44ce173SJames.Smart@Emulex.Com  * Public License as published by the Free Software Foundation.    *
14c44ce173SJames.Smart@Emulex.Com  * This program is distributed in the hope that it will be useful. *
15c44ce173SJames.Smart@Emulex.Com  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
16c44ce173SJames.Smart@Emulex.Com  * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
17c44ce173SJames.Smart@Emulex.Com  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
18c44ce173SJames.Smart@Emulex.Com  * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
19c44ce173SJames.Smart@Emulex.Com  * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
20c44ce173SJames.Smart@Emulex.Com  * more details, a copy of which can be found in the file COPYING  *
21c44ce173SJames.Smart@Emulex.Com  * included with this package.                                     *
22dea3101eS  *******************************************************************/
23dea3101eS #include <linux/pci.h>
245a0e3ad6STejun Heo #include <linux/slab.h>
25dea3101eS #include <linux/interrupt.h>
2609703660SPaul Gortmaker #include <linux/export.h>
27a90f5684SJames Smart #include <linux/delay.h>
28*5f60d5f6SAl Viro #include <linux/unaligned.h>
29128b6f9fSDmitry Monakhov #include <linux/t10-pi.h>
30737d4248SJames Smart #include <linux/crc-t10dif.h>
31dc50715eSGaurav Srivastava #include <linux/blk-cgroup.h>
32737d4248SJames Smart #include <net/checksum.h>
33dea3101eS 
34dea3101eS #include <scsi/scsi.h>
35dea3101eS #include <scsi/scsi_device.h>
36e2a0a9d6SJames Smart #include <scsi/scsi_eh.h>
37dea3101eS #include <scsi/scsi_host.h>
38dea3101eS #include <scsi/scsi_tcq.h>
39dea3101eS #include <scsi/scsi_transport_fc.h>
40dea3101eS 
41dea3101eS #include "lpfc_version.h"
42da0436e9SJames Smart #include "lpfc_hw4.h"
43dea3101eS #include "lpfc_hw.h"
44dea3101eS #include "lpfc_sli.h"
45da0436e9SJames Smart #include "lpfc_sli4.h"
46ea2151b4SJames Smart #include "lpfc_nl.h"
47dea3101eS #include "lpfc_disc.h"
48dea3101eS #include "lpfc.h"
499a6b09c0SJames Smart #include "lpfc_scsi.h"
50dea3101eS #include "lpfc_logmsg.h"
51dea3101eS #include "lpfc_crtn.h"
5292d7f7b0SJames Smart #include "lpfc_vport.h"
53dea3101eS 
54dea3101eS #define LPFC_RESET_WAIT  2
55dea3101eS #define LPFC_ABORT_WAIT  2
56dea3101eS 
57e2a0a9d6SJames Smart static char *dif_op_str[] = {
589a6b09c0SJames Smart 	"PROT_NORMAL",
599a6b09c0SJames Smart 	"PROT_READ_INSERT",
609a6b09c0SJames Smart 	"PROT_WRITE_STRIP",
619a6b09c0SJames Smart 	"PROT_READ_STRIP",
629a6b09c0SJames Smart 	"PROT_WRITE_INSERT",
639a6b09c0SJames Smart 	"PROT_READ_PASS",
649a6b09c0SJames Smart 	"PROT_WRITE_PASS",
659a6b09c0SJames Smart };
669a6b09c0SJames Smart 
67f9bb2da1SJames Smart struct scsi_dif_tuple {
68f9bb2da1SJames Smart 	__be16 guard_tag;       /* Checksum */
69f9bb2da1SJames Smart 	__be16 app_tag;         /* Opaque storage */
70f9bb2da1SJames Smart 	__be32 ref_tag;         /* Target LBA or indirect LBA */
71f9bb2da1SJames Smart };
72f9bb2da1SJames Smart 
731ba981fdSJames Smart static struct lpfc_rport_data *
lpfc_rport_data_from_scsi_device(struct scsi_device * sdev)741ba981fdSJames Smart lpfc_rport_data_from_scsi_device(struct scsi_device *sdev)
751ba981fdSJames Smart {
761ba981fdSJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *)sdev->host->hostdata;
771ba981fdSJames Smart 
78f38fa0bbSJames Smart 	if (vport->phba->cfg_fof)
791ba981fdSJames Smart 		return ((struct lpfc_device_data *)sdev->hostdata)->rport_data;
801ba981fdSJames Smart 	else
811ba981fdSJames Smart 		return (struct lpfc_rport_data *)sdev->hostdata;
821ba981fdSJames Smart }
831ba981fdSJames Smart 
84da0436e9SJames Smart static void
85c490850aSJames Smart lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *psb);
861c6f4ef5SJames Smart static void
87c490850aSJames Smart lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb);
889c6aa9d7SJames Smart static int
899c6aa9d7SJames Smart lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc);
90e2a0a9d6SJames Smart 
91ea2151b4SJames Smart /**
92f1126688SJames Smart  * lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge.
93f1126688SJames Smart  * @phba: Pointer to HBA object.
94f1126688SJames Smart  * @lpfc_cmd: lpfc scsi command object pointer.
95f1126688SJames Smart  *
96f1126688SJames Smart  * This function is called from the lpfc_prep_task_mgmt_cmd function to
97f1126688SJames Smart  * set the last bit in the response sge entry.
98f1126688SJames Smart  **/
99f1126688SJames Smart static void
lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)100f1126688SJames Smart lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
101c490850aSJames Smart 				struct lpfc_io_buf *lpfc_cmd)
102f1126688SJames Smart {
1030794d601SJames Smart 	struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl;
104f1126688SJames Smart 	if (sgl) {
105f1126688SJames Smart 		sgl += 1;
106f1126688SJames Smart 		sgl->word2 = le32_to_cpu(sgl->word2);
107f1126688SJames Smart 		bf_set(lpfc_sli4_sge_last, sgl, 1);
108f1126688SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
109f1126688SJames Smart 	}
110f1126688SJames Smart }
111f1126688SJames Smart 
112f1126688SJames Smart /**
1133621a710SJames Smart  * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
1149bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
1159bad7671SJames Smart  *
1169bad7671SJames Smart  * This routine is called when there is resource error in driver or firmware.
1179bad7671SJames Smart  * This routine posts WORKER_RAMP_DOWN_QUEUE event for @phba. This routine
1189bad7671SJames Smart  * posts at most 1 event each second. This routine wakes up worker thread of
1199bad7671SJames Smart  * @phba to process WORKER_RAM_DOWN_EVENT event.
1209bad7671SJames Smart  *
1219bad7671SJames Smart  * This routine should be called with no lock held.
1229bad7671SJames Smart  **/
12392d7f7b0SJames Smart void
lpfc_rampdown_queue_depth(struct lpfc_hba * phba)124eaf15d5bSJames Smart lpfc_rampdown_queue_depth(struct lpfc_hba *phba)
12592d7f7b0SJames Smart {
12692d7f7b0SJames Smart 	unsigned long flags;
1275e9d9b82SJames Smart 	uint32_t evt_posted;
1280d4aec13SManuel Schölling 	unsigned long expires;
12992d7f7b0SJames Smart 
13092d7f7b0SJames Smart 	spin_lock_irqsave(&phba->hbalock, flags);
13192d7f7b0SJames Smart 	atomic_inc(&phba->num_rsrc_err);
13292d7f7b0SJames Smart 	phba->last_rsrc_error_time = jiffies;
13392d7f7b0SJames Smart 
1340d4aec13SManuel Schölling 	expires = phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL;
1350d4aec13SManuel Schölling 	if (time_after(expires, jiffies)) {
13692d7f7b0SJames Smart 		spin_unlock_irqrestore(&phba->hbalock, flags);
13792d7f7b0SJames Smart 		return;
13892d7f7b0SJames Smart 	}
13992d7f7b0SJames Smart 
14092d7f7b0SJames Smart 	phba->last_ramp_down_time = jiffies;
14192d7f7b0SJames Smart 
14292d7f7b0SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, flags);
14392d7f7b0SJames Smart 
14492d7f7b0SJames Smart 	spin_lock_irqsave(&phba->pport->work_port_lock, flags);
1455e9d9b82SJames Smart 	evt_posted = phba->pport->work_port_events & WORKER_RAMP_DOWN_QUEUE;
1465e9d9b82SJames Smart 	if (!evt_posted)
14792d7f7b0SJames Smart 		phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE;
14892d7f7b0SJames Smart 	spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
14992d7f7b0SJames Smart 
1505e9d9b82SJames Smart 	if (!evt_posted)
1515e9d9b82SJames Smart 		lpfc_worker_wake_up(phba);
15292d7f7b0SJames Smart 	return;
15392d7f7b0SJames Smart }
15492d7f7b0SJames Smart 
1559bad7671SJames Smart /**
1563621a710SJames Smart  * lpfc_ramp_down_queue_handler - WORKER_RAMP_DOWN_QUEUE event handler
1579bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
1589bad7671SJames Smart  *
1599bad7671SJames Smart  * This routine is called to  process WORKER_RAMP_DOWN_QUEUE event for worker
1609bad7671SJames Smart  * thread.This routine reduces queue depth for all scsi device on each vport
1619bad7671SJames Smart  * associated with @phba.
1629bad7671SJames Smart  **/
16392d7f7b0SJames Smart void
lpfc_ramp_down_queue_handler(struct lpfc_hba * phba)16492d7f7b0SJames Smart lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
16592d7f7b0SJames Smart {
166549e55cdSJames Smart 	struct lpfc_vport **vports;
167549e55cdSJames Smart 	struct Scsi_Host  *shost;
16892d7f7b0SJames Smart 	struct scsi_device *sdev;
1695ffc266eSJames Smart 	unsigned long new_queue_depth;
170bb011631SJustin Tee 	unsigned long num_rsrc_err;
171549e55cdSJames Smart 	int i;
17292d7f7b0SJames Smart 
17392d7f7b0SJames Smart 	num_rsrc_err = atomic_read(&phba->num_rsrc_err);
17492d7f7b0SJames Smart 
17575ad83a4SJames Smart 	/*
17675ad83a4SJames Smart 	 * The error and success command counters are global per
17775ad83a4SJames Smart 	 * driver instance.  If another handler has already
17875ad83a4SJames Smart 	 * operated on this error event, just exit.
17975ad83a4SJames Smart 	 */
18075ad83a4SJames Smart 	if (num_rsrc_err == 0)
18175ad83a4SJames Smart 		return;
18275ad83a4SJames Smart 
183549e55cdSJames Smart 	vports = lpfc_create_vport_work_array(phba);
184549e55cdSJames Smart 	if (vports != NULL)
18521e9a0a5SJames Smart 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
186549e55cdSJames Smart 			shost = lpfc_shost_from_vport(vports[i]);
187549e55cdSJames Smart 			shost_for_each_device(sdev, shost) {
188bb011631SJustin Tee 				if (num_rsrc_err >= sdev->queue_depth)
189bb011631SJustin Tee 					new_queue_depth = 1;
19092d7f7b0SJames Smart 				else
191549e55cdSJames Smart 					new_queue_depth = sdev->queue_depth -
192bb011631SJustin Tee 						num_rsrc_err;
193db5ed4dfSChristoph Hellwig 				scsi_change_queue_depth(sdev, new_queue_depth);
19492d7f7b0SJames Smart 			}
19592d7f7b0SJames Smart 		}
19609372820SJames Smart 	lpfc_destroy_vport_work_array(phba, vports);
19792d7f7b0SJames Smart 	atomic_set(&phba->num_rsrc_err, 0);
19892d7f7b0SJames Smart }
19992d7f7b0SJames Smart 
2009bad7671SJames Smart /**
2013621a710SJames Smart  * lpfc_scsi_dev_block - set all scsi hosts to block state
202a8e497d5SJames Smart  * @phba: Pointer to HBA context object.
203a8e497d5SJames Smart  *
204a8e497d5SJames Smart  * This function walks vport list and set each SCSI host to block state
205a8e497d5SJames Smart  * by invoking fc_remote_port_delete() routine. This function is invoked
206a8e497d5SJames Smart  * with EEH when device's PCI slot has been permanently disabled.
207a8e497d5SJames Smart  **/
208a8e497d5SJames Smart void
lpfc_scsi_dev_block(struct lpfc_hba * phba)209a8e497d5SJames Smart lpfc_scsi_dev_block(struct lpfc_hba *phba)
210a8e497d5SJames Smart {
211a8e497d5SJames Smart 	struct lpfc_vport **vports;
212a8e497d5SJames Smart 	struct Scsi_Host  *shost;
213a8e497d5SJames Smart 	struct scsi_device *sdev;
214a8e497d5SJames Smart 	struct fc_rport *rport;
215a8e497d5SJames Smart 	int i;
216a8e497d5SJames Smart 
217a8e497d5SJames Smart 	vports = lpfc_create_vport_work_array(phba);
218a8e497d5SJames Smart 	if (vports != NULL)
21921e9a0a5SJames Smart 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
220a8e497d5SJames Smart 			shost = lpfc_shost_from_vport(vports[i]);
221a8e497d5SJames Smart 			shost_for_each_device(sdev, shost) {
222a8e497d5SJames Smart 				rport = starget_to_rport(scsi_target(sdev));
223a8e497d5SJames Smart 				fc_remote_port_delete(rport);
224a8e497d5SJames Smart 			}
225a8e497d5SJames Smart 		}
226a8e497d5SJames Smart 	lpfc_destroy_vport_work_array(phba, vports);
227a8e497d5SJames Smart }
228a8e497d5SJames Smart 
2299bad7671SJames Smart /**
2303772a991SJames Smart  * lpfc_new_scsi_buf_s3 - Scsi buffer allocator for HBA with SLI3 IF spec
2319bad7671SJames Smart  * @vport: The virtual port for which this call being executed.
232eceee00eSLee Jones  * @num_to_alloc: The requested number of buffers to allocate.
2339bad7671SJames Smart  *
2343772a991SJames Smart  * This routine allocates a scsi buffer for device with SLI-3 interface spec,
2353772a991SJames Smart  * the scsi buffer contains all the necessary information needed to initiate
2363772a991SJames Smart  * a SCSI I/O. The non-DMAable buffer region contains information to build
2373772a991SJames Smart  * the IOCB. The DMAable region contains memory for the FCP CMND, FCP RSP,
2383772a991SJames Smart  * and the initial BPL. In addition to allocating memory, the FCP CMND and
2393772a991SJames Smart  * FCP RSP BDEs are setup in the BPL and the BPL BDE is setup in the IOCB.
2409bad7671SJames Smart  *
2419bad7671SJames Smart  * Return codes:
2423772a991SJames Smart  *   int - number of scsi buffers that were allocated.
2433772a991SJames Smart  *   0 = failure, less than num_to_alloc is a partial failure.
2449bad7671SJames Smart  **/
2453772a991SJames Smart static int
lpfc_new_scsi_buf_s3(struct lpfc_vport * vport,int num_to_alloc)2463772a991SJames Smart lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
247dea3101eS {
2482e0fef85SJames Smart 	struct lpfc_hba *phba = vport->phba;
249c490850aSJames Smart 	struct lpfc_io_buf *psb;
250dea3101eS 	struct ulp_bde64 *bpl;
251dea3101eS 	IOCB_t *iocb;
25234b02dcdSJames Smart 	dma_addr_t pdma_phys_fcp_cmd;
25334b02dcdSJames Smart 	dma_addr_t pdma_phys_fcp_rsp;
2540794d601SJames Smart 	dma_addr_t pdma_phys_sgl;
255604a3e30SJames Bottomley 	uint16_t iotag;
25696f7077fSJames Smart 	int bcnt, bpl_size;
25796f7077fSJames Smart 
25896f7077fSJames Smart 	bpl_size = phba->cfg_sg_dma_buf_size -
25996f7077fSJames Smart 		(sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
26096f7077fSJames Smart 
26196f7077fSJames Smart 	lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
26296f7077fSJames Smart 			 "9067 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n",
26396f7077fSJames Smart 			 num_to_alloc, phba->cfg_sg_dma_buf_size,
26496f7077fSJames Smart 			 (int)sizeof(struct fcp_cmnd),
26596f7077fSJames Smart 			 (int)sizeof(struct fcp_rsp), bpl_size);
266dea3101eS 
2673772a991SJames Smart 	for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
268c490850aSJames Smart 		psb = kzalloc(sizeof(struct lpfc_io_buf), GFP_KERNEL);
269dea3101eS 		if (!psb)
2703772a991SJames Smart 			break;
271dea3101eS 
272dea3101eS 		/*
2733772a991SJames Smart 		 * Get memory from the pci pool to map the virt space to pci
2743772a991SJames Smart 		 * bus space for an I/O.  The DMA buffer includes space for the
2753772a991SJames Smart 		 * struct fcp_cmnd, struct fcp_rsp and the number of bde's
2763772a991SJames Smart 		 * necessary to support the sg_tablesize.
277dea3101eS 		 */
278771db5c0SRomain Perier 		psb->data = dma_pool_zalloc(phba->lpfc_sg_dma_buf_pool,
2793772a991SJames Smart 					GFP_KERNEL, &psb->dma_handle);
280dea3101eS 		if (!psb->data) {
281dea3101eS 			kfree(psb);
2823772a991SJames Smart 			break;
283dea3101eS 		}
284dea3101eS 
285dea3101eS 
286604a3e30SJames Bottomley 		/* Allocate iotag for psb->cur_iocbq. */
287604a3e30SJames Bottomley 		iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq);
288604a3e30SJames Bottomley 		if (iotag == 0) {
289771db5c0SRomain Perier 			dma_pool_free(phba->lpfc_sg_dma_buf_pool,
290604a3e30SJames Bottomley 				      psb->data, psb->dma_handle);
291604a3e30SJames Bottomley 			kfree(psb);
2923772a991SJames Smart 			break;
293604a3e30SJames Bottomley 		}
294a680a929SJames Smart 		psb->cur_iocbq.cmd_flag |= LPFC_IO_FCP;
295604a3e30SJames Bottomley 
296dea3101eS 		psb->fcp_cmnd = psb->data;
297dea3101eS 		psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd);
2980794d601SJames Smart 		psb->dma_sgl = psb->data + sizeof(struct fcp_cmnd) +
299dea3101eS 			sizeof(struct fcp_rsp);
300dea3101eS 
301dea3101eS 		/* Initialize local short-hand pointers. */
302c490850aSJames Smart 		bpl = (struct ulp_bde64 *)psb->dma_sgl;
30334b02dcdSJames Smart 		pdma_phys_fcp_cmd = psb->dma_handle;
30434b02dcdSJames Smart 		pdma_phys_fcp_rsp = psb->dma_handle + sizeof(struct fcp_cmnd);
3050794d601SJames Smart 		pdma_phys_sgl = psb->dma_handle + sizeof(struct fcp_cmnd) +
30634b02dcdSJames Smart 			sizeof(struct fcp_rsp);
307dea3101eS 
308dea3101eS 		/*
3093772a991SJames Smart 		 * The first two bdes are the FCP_CMD and FCP_RSP. The balance
3103772a991SJames Smart 		 * are sg list bdes.  Initialize the first two and leave the
3113772a991SJames Smart 		 * rest for queuecommand.
312dea3101eS 		 */
31334b02dcdSJames Smart 		bpl[0].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_cmd));
31434b02dcdSJames Smart 		bpl[0].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_cmd));
31534b02dcdSJames Smart 		bpl[0].tus.f.bdeSize = sizeof(struct fcp_cmnd);
31634b02dcdSJames Smart 		bpl[0].tus.f.bdeFlags = BUFF_TYPE_BDE_64;
3179f1e1b50SJames Smart 		bpl[0].tus.w = le32_to_cpu(bpl[0].tus.w);
318dea3101eS 
319dea3101eS 		/* Setup the physical region for the FCP RSP */
32034b02dcdSJames Smart 		bpl[1].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_rsp));
32134b02dcdSJames Smart 		bpl[1].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_rsp));
32234b02dcdSJames Smart 		bpl[1].tus.f.bdeSize = sizeof(struct fcp_rsp);
32334b02dcdSJames Smart 		bpl[1].tus.f.bdeFlags = BUFF_TYPE_BDE_64;
3249f1e1b50SJames Smart 		bpl[1].tus.w = le32_to_cpu(bpl[1].tus.w);
325dea3101eS 
326dea3101eS 		/*
3273772a991SJames Smart 		 * Since the IOCB for the FCP I/O is built into this
3283772a991SJames Smart 		 * lpfc_scsi_buf, initialize it with all known data now.
329dea3101eS 		 */
330dea3101eS 		iocb = &psb->cur_iocbq.iocb;
331dea3101eS 		iocb->un.fcpi64.bdl.ulpIoTag32 = 0;
332e2a0a9d6SJames Smart 		if ((phba->sli_rev == 3) &&
333e2a0a9d6SJames Smart 				!(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) {
33434b02dcdSJames Smart 			/* fill in immediate fcp command BDE */
33534b02dcdSJames Smart 			iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_IMMED;
33634b02dcdSJames Smart 			iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd);
33734b02dcdSJames Smart 			iocb->un.fcpi64.bdl.addrLow = offsetof(IOCB_t,
33834b02dcdSJames Smart 					unsli3.fcp_ext.icd);
33934b02dcdSJames Smart 			iocb->un.fcpi64.bdl.addrHigh = 0;
34034b02dcdSJames Smart 			iocb->ulpBdeCount = 0;
34134b02dcdSJames Smart 			iocb->ulpLe = 0;
34225985edcSLucas De Marchi 			/* fill in response BDE */
3433772a991SJames Smart 			iocb->unsli3.fcp_ext.rbde.tus.f.bdeFlags =
3443772a991SJames Smart 							BUFF_TYPE_BDE_64;
34534b02dcdSJames Smart 			iocb->unsli3.fcp_ext.rbde.tus.f.bdeSize =
34634b02dcdSJames Smart 				sizeof(struct fcp_rsp);
34734b02dcdSJames Smart 			iocb->unsli3.fcp_ext.rbde.addrLow =
34834b02dcdSJames Smart 				putPaddrLow(pdma_phys_fcp_rsp);
34934b02dcdSJames Smart 			iocb->unsli3.fcp_ext.rbde.addrHigh =
35034b02dcdSJames Smart 				putPaddrHigh(pdma_phys_fcp_rsp);
35134b02dcdSJames Smart 		} else {
35234b02dcdSJames Smart 			iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
3533772a991SJames Smart 			iocb->un.fcpi64.bdl.bdeSize =
3543772a991SJames Smart 					(2 * sizeof(struct ulp_bde64));
3553772a991SJames Smart 			iocb->un.fcpi64.bdl.addrLow =
3560794d601SJames Smart 					putPaddrLow(pdma_phys_sgl);
3573772a991SJames Smart 			iocb->un.fcpi64.bdl.addrHigh =
3580794d601SJames Smart 					putPaddrHigh(pdma_phys_sgl);
359dea3101eS 			iocb->ulpBdeCount = 1;
36034b02dcdSJames Smart 			iocb->ulpLe = 1;
36134b02dcdSJames Smart 		}
362dea3101eS 		iocb->ulpClass = CLASS3;
3633772a991SJames Smart 		psb->status = IOSTAT_SUCCESS;
364da0436e9SJames Smart 		/* Put it back into the SCSI buffer list */
365d51cf5bdSJames Smart 		psb->cur_iocbq.io_buf = psb;
366c2017260SJames Smart 		spin_lock_init(&psb->buf_lock);
3671c6f4ef5SJames Smart 		lpfc_release_scsi_buf_s3(phba, psb);
368dea3101eS 
3693772a991SJames Smart 	}
3703772a991SJames Smart 
3713772a991SJames Smart 	return bcnt;
372dea3101eS }
373dea3101eS 
3749bad7671SJames Smart /**
3751151e3ecSJames Smart  * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport
3761151e3ecSJames Smart  * @vport: pointer to lpfc vport data structure.
3771151e3ecSJames Smart  *
3781151e3ecSJames Smart  * This routine is invoked by the vport cleanup for deletions and the cleanup
3791151e3ecSJames Smart  * for an ndlp on removal.
3801151e3ecSJames Smart  **/
3811151e3ecSJames Smart void
lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport * vport)3821151e3ecSJames Smart lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
3831151e3ecSJames Smart {
3841151e3ecSJames Smart 	struct lpfc_hba *phba = vport->phba;
385c490850aSJames Smart 	struct lpfc_io_buf *psb, *next_psb;
3865e5b511dSJames Smart 	struct lpfc_sli4_hdw_queue *qp;
3871151e3ecSJames Smart 	unsigned long iflag = 0;
3885e5b511dSJames Smart 	int idx;
3891151e3ecSJames Smart 
390f6e84790SJames Smart 	if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
391895427bdSJames Smart 		return;
3925e5b511dSJames Smart 
3931151e3ecSJames Smart 	spin_lock_irqsave(&phba->hbalock, iflag);
3945e5b511dSJames Smart 	for (idx = 0; idx < phba->cfg_hdw_queue; idx++) {
3955e5b511dSJames Smart 		qp = &phba->sli4_hba.hdwq[idx];
3965e5b511dSJames Smart 
397c00f62e6SJames Smart 		spin_lock(&qp->abts_io_buf_list_lock);
3981151e3ecSJames Smart 		list_for_each_entry_safe(psb, next_psb,
399c00f62e6SJames Smart 					 &qp->lpfc_abts_io_buf_list, list) {
400a680a929SJames Smart 			if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME)
401c00f62e6SJames Smart 				continue;
402c00f62e6SJames Smart 
4035e5b511dSJames Smart 			if (psb->rdata && psb->rdata->pnode &&
4045e5b511dSJames Smart 			    psb->rdata->pnode->vport == vport)
4051151e3ecSJames Smart 				psb->rdata = NULL;
4061151e3ecSJames Smart 		}
407c00f62e6SJames Smart 		spin_unlock(&qp->abts_io_buf_list_lock);
4085e5b511dSJames Smart 	}
4091151e3ecSJames Smart 	spin_unlock_irqrestore(&phba->hbalock, iflag);
4101151e3ecSJames Smart }
4111151e3ecSJames Smart 
4121151e3ecSJames Smart /**
413c00f62e6SJames Smart  * lpfc_sli4_io_xri_aborted - Fast-path process of fcp xri abort
414da0436e9SJames Smart  * @phba: pointer to lpfc hba data structure.
415da0436e9SJames Smart  * @axri: pointer to the fcp xri abort wcqe structure.
416eceee00eSLee Jones  * @idx: index into hdwq
417da0436e9SJames Smart  *
418da0436e9SJames Smart  * This routine is invoked by the worker thread to process a SLI4 fast-path
419c00f62e6SJames Smart  * FCP or NVME aborted xri.
420da0436e9SJames Smart  **/
421da0436e9SJames Smart void
lpfc_sli4_io_xri_aborted(struct lpfc_hba * phba,struct sli4_wcqe_xri_aborted * axri,int idx)422c00f62e6SJames Smart lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
4235e5b511dSJames Smart 			 struct sli4_wcqe_xri_aborted *axri, int idx)
424da0436e9SJames Smart {
42525ac2c97SJames Smart 	u16 xri = 0;
42625ac2c97SJames Smart 	u16 rxid = 0;
427c490850aSJames Smart 	struct lpfc_io_buf *psb, *next_psb;
4285e5b511dSJames Smart 	struct lpfc_sli4_hdw_queue *qp;
429da0436e9SJames Smart 	unsigned long iflag = 0;
4300f65ff68SJames Smart 	struct lpfc_iocbq *iocbq;
4310f65ff68SJames Smart 	int i;
43219ca7609SJames Smart 	struct lpfc_nodelist *ndlp;
43319ca7609SJames Smart 	int rrq_empty = 0;
434895427bdSJames Smart 	struct lpfc_sli_ring *pring = phba->sli4_hba.els_wq->pring;
4353e49af93SJames Smart 	struct scsi_cmnd *cmd;
43625ac2c97SJames Smart 	int offline = 0;
437da0436e9SJames Smart 
438895427bdSJames Smart 	if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
439895427bdSJames Smart 		return;
44025ac2c97SJames Smart 	offline = pci_channel_offline(phba->pcidev);
44125ac2c97SJames Smart 	if (!offline) {
44225ac2c97SJames Smart 		xri = bf_get(lpfc_wcqe_xa_xri, axri);
44325ac2c97SJames Smart 		rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
44425ac2c97SJames Smart 	}
4455e5b511dSJames Smart 	qp = &phba->sli4_hba.hdwq[idx];
4460f65ff68SJames Smart 	spin_lock_irqsave(&phba->hbalock, iflag);
447c00f62e6SJames Smart 	spin_lock(&qp->abts_io_buf_list_lock);
448da0436e9SJames Smart 	list_for_each_entry_safe(psb, next_psb,
449c00f62e6SJames Smart 		&qp->lpfc_abts_io_buf_list, list) {
45025ac2c97SJames Smart 		if (offline)
45125ac2c97SJames Smart 			xri = psb->cur_iocbq.sli4_xritag;
452da0436e9SJames Smart 		if (psb->cur_iocbq.sli4_xritag == xri) {
453c00f62e6SJames Smart 			list_del_init(&psb->list);
454324e1c40SJames Smart 			psb->flags &= ~LPFC_SBUF_XBUSY;
455da0436e9SJames Smart 			psb->status = IOSTAT_SUCCESS;
456a680a929SJames Smart 			if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) {
457c00f62e6SJames Smart 				qp->abts_nvme_io_bufs--;
458c00f62e6SJames Smart 				spin_unlock(&qp->abts_io_buf_list_lock);
459c00f62e6SJames Smart 				spin_unlock_irqrestore(&phba->hbalock, iflag);
46025ac2c97SJames Smart 				if (!offline) {
46125ac2c97SJames Smart 					lpfc_sli4_nvme_xri_aborted(phba, axri,
46225ac2c97SJames Smart 								   psb);
463c00f62e6SJames Smart 					return;
464c00f62e6SJames Smart 				}
46525ac2c97SJames Smart 				lpfc_sli4_nvme_pci_offline_aborted(phba, psb);
46625ac2c97SJames Smart 				spin_lock_irqsave(&phba->hbalock, iflag);
46725ac2c97SJames Smart 				spin_lock(&qp->abts_io_buf_list_lock);
46825ac2c97SJames Smart 				continue;
46925ac2c97SJames Smart 			}
470c00f62e6SJames Smart 			qp->abts_scsi_io_bufs--;
471c00f62e6SJames Smart 			spin_unlock(&qp->abts_io_buf_list_lock);
472c00f62e6SJames Smart 
4731151e3ecSJames Smart 			if (psb->rdata && psb->rdata->pnode)
47419ca7609SJames Smart 				ndlp = psb->rdata->pnode;
4751151e3ecSJames Smart 			else
4761151e3ecSJames Smart 				ndlp = NULL;
4770f65ff68SJames Smart 			spin_unlock_irqrestore(&phba->hbalock, iflag);
4785f800d72SJustin Tee 
4795f800d72SJustin Tee 			spin_lock_irqsave(&phba->rrq_list_lock, iflag);
4805f800d72SJustin Tee 			rrq_empty = list_empty(&phba->active_rrq_list);
4815f800d72SJustin Tee 			spin_unlock_irqrestore(&phba->rrq_list_lock, iflag);
48225ac2c97SJames Smart 			if (ndlp && !offline) {
483ee0f4fe1SJames Smart 				lpfc_set_rrq_active(phba, ndlp,
484ee0f4fe1SJames Smart 					psb->cur_iocbq.sli4_lxritag, rxid, 1);
485cb69f7deSJames Smart 				lpfc_sli4_abts_err_handler(phba, ndlp, axri);
486cb69f7deSJames Smart 			}
4873e49af93SJames Smart 
48825ac2c97SJames Smart 			if (phba->cfg_fcp_wait_abts_rsp || offline) {
4893e49af93SJames Smart 				spin_lock_irqsave(&psb->buf_lock, iflag);
4903e49af93SJames Smart 				cmd = psb->pCmd;
4913e49af93SJames Smart 				psb->pCmd = NULL;
4923e49af93SJames Smart 				spin_unlock_irqrestore(&psb->buf_lock, iflag);
4933e49af93SJames Smart 
4943e49af93SJames Smart 				/* The sdev is not guaranteed to be valid post
4953e49af93SJames Smart 				 * scsi_done upcall.
4963e49af93SJames Smart 				 */
4973e49af93SJames Smart 				if (cmd)
498ca068c2cSBart Van Assche 					scsi_done(cmd);
4993e49af93SJames Smart 
5003e49af93SJames Smart 				/*
5013e49af93SJames Smart 				 * We expect there is an abort thread waiting
5023e49af93SJames Smart 				 * for command completion wake up the thread.
5033e49af93SJames Smart 				 */
5043e49af93SJames Smart 				spin_lock_irqsave(&psb->buf_lock, iflag);
505a680a929SJames Smart 				psb->cur_iocbq.cmd_flag &=
5063e49af93SJames Smart 					~LPFC_DRIVER_ABORTED;
5073e49af93SJames Smart 				if (psb->waitq)
5083e49af93SJames Smart 					wake_up(psb->waitq);
5093e49af93SJames Smart 				spin_unlock_irqrestore(&psb->buf_lock, iflag);
5103e49af93SJames Smart 			}
5113e49af93SJames Smart 
512da0436e9SJames Smart 			lpfc_release_scsi_buf_s4(phba, psb);
51319ca7609SJames Smart 			if (rrq_empty)
51419ca7609SJames Smart 				lpfc_worker_wake_up(phba);
51525ac2c97SJames Smart 			if (!offline)
516da0436e9SJames Smart 				return;
51725ac2c97SJames Smart 			spin_lock_irqsave(&phba->hbalock, iflag);
51825ac2c97SJames Smart 			spin_lock(&qp->abts_io_buf_list_lock);
51925ac2c97SJames Smart 			continue;
520da0436e9SJames Smart 		}
521da0436e9SJames Smart 	}
522c00f62e6SJames Smart 	spin_unlock(&qp->abts_io_buf_list_lock);
52325ac2c97SJames Smart 	if (!offline) {
5240f65ff68SJames Smart 		for (i = 1; i <= phba->sli.last_iotag; i++) {
5250f65ff68SJames Smart 			iocbq = phba->sli.iocbq_lookup[i];
5260f65ff68SJames Smart 
527a680a929SJames Smart 			if (!(iocbq->cmd_flag & LPFC_IO_FCP) ||
528a680a929SJames Smart 			    (iocbq->cmd_flag & LPFC_IO_LIBDFC))
5290f65ff68SJames Smart 				continue;
5300f65ff68SJames Smart 			if (iocbq->sli4_xritag != xri)
5310f65ff68SJames Smart 				continue;
532c490850aSJames Smart 			psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
533324e1c40SJames Smart 			psb->flags &= ~LPFC_SBUF_XBUSY;
5340f65ff68SJames Smart 			spin_unlock_irqrestore(&phba->hbalock, iflag);
5350e9bb8d7SJames Smart 			if (!list_empty(&pring->txq))
536589a52d6SJames Smart 				lpfc_worker_wake_up(phba);
5370f65ff68SJames Smart 			return;
53825ac2c97SJames Smart 		}
5390f65ff68SJames Smart 	}
5400f65ff68SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, iflag);
541da0436e9SJames Smart }
542da0436e9SJames Smart 
543da0436e9SJames Smart /**
54419ca7609SJames Smart  * lpfc_get_scsi_buf_s3 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
5453772a991SJames Smart  * @phba: The HBA for which this call is being executed.
546eceee00eSLee Jones  * @ndlp: pointer to a node-list data structure.
547eceee00eSLee Jones  * @cmnd: Pointer to scsi_cmnd data structure.
5489bad7671SJames Smart  *
5499bad7671SJames Smart  * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
5509bad7671SJames Smart  * and returns to caller.
5519bad7671SJames Smart  *
5529bad7671SJames Smart  * Return codes:
5539bad7671SJames Smart  *   NULL - Error
5549bad7671SJames Smart  *   Pointer to lpfc_scsi_buf - Success
5559bad7671SJames Smart  **/
556c490850aSJames Smart static struct lpfc_io_buf *
lpfc_get_scsi_buf_s3(struct lpfc_hba * phba,struct lpfc_nodelist * ndlp,struct scsi_cmnd * cmnd)557ace44e48SJames Smart lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
558ace44e48SJames Smart 		     struct scsi_cmnd *cmnd)
559dea3101eS {
560c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd = NULL;
561a40fc5f0SJames Smart 	struct list_head *scsi_buf_list_get = &phba->lpfc_scsi_buf_list_get;
562164cecd1SJames Smart 	unsigned long iflag = 0;
563dea3101eS 
564164cecd1SJames Smart 	spin_lock_irqsave(&phba->scsi_buf_list_get_lock, iflag);
565c490850aSJames Smart 	list_remove_head(scsi_buf_list_get, lpfc_cmd, struct lpfc_io_buf,
566a40fc5f0SJames Smart 			 list);
567a40fc5f0SJames Smart 	if (!lpfc_cmd) {
568164cecd1SJames Smart 		spin_lock(&phba->scsi_buf_list_put_lock);
569a40fc5f0SJames Smart 		list_splice(&phba->lpfc_scsi_buf_list_put,
570a40fc5f0SJames Smart 			    &phba->lpfc_scsi_buf_list_get);
571a40fc5f0SJames Smart 		INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
572a40fc5f0SJames Smart 		list_remove_head(scsi_buf_list_get, lpfc_cmd,
573c490850aSJames Smart 				 struct lpfc_io_buf, list);
574164cecd1SJames Smart 		spin_unlock(&phba->scsi_buf_list_put_lock);
5751dcb58e5SJames Smart 	}
576164cecd1SJames Smart 	spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, iflag);
5772a5b7d62SJames Smart 
5782a5b7d62SJames Smart 	if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_cmd) {
5792a5b7d62SJames Smart 		atomic_inc(&ndlp->cmd_pending);
5802a5b7d62SJames Smart 		lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH;
5812a5b7d62SJames Smart 	}
5820bd4ca25SJames.Smart@Emulex.Com 	return  lpfc_cmd;
5830bd4ca25SJames.Smart@Emulex.Com }
58419ca7609SJames Smart /**
5855e5b511dSJames Smart  * lpfc_get_scsi_buf_s4 - Get a scsi buffer from io_buf_list of the HBA
58619ca7609SJames Smart  * @phba: The HBA for which this call is being executed.
587eceee00eSLee Jones  * @ndlp: pointer to a node-list data structure.
588eceee00eSLee Jones  * @cmnd: Pointer to scsi_cmnd data structure.
58919ca7609SJames Smart  *
5905e5b511dSJames Smart  * This routine removes a scsi buffer from head of @hdwq io_buf_list
59119ca7609SJames Smart  * and returns to caller.
59219ca7609SJames Smart  *
59319ca7609SJames Smart  * Return codes:
59419ca7609SJames Smart  *   NULL - Error
59519ca7609SJames Smart  *   Pointer to lpfc_scsi_buf - Success
59619ca7609SJames Smart  **/
597c490850aSJames Smart static struct lpfc_io_buf *
lpfc_get_scsi_buf_s4(struct lpfc_hba * phba,struct lpfc_nodelist * ndlp,struct scsi_cmnd * cmnd)598ace44e48SJames Smart lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
599ace44e48SJames Smart 		     struct scsi_cmnd *cmnd)
60019ca7609SJames Smart {
601c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd;
6025e5b511dSJames Smart 	struct lpfc_sli4_hdw_queue *qp;
603af20bb73SJustin Tee 	struct sli4_sge_le *sgl;
6040794d601SJames Smart 	dma_addr_t pdma_phys_fcp_rsp;
6050794d601SJames Smart 	dma_addr_t pdma_phys_fcp_cmd;
606d79c9e9dSJames Smart 	uint32_t cpu, idx;
607ace44e48SJames Smart 	int tag;
608d79c9e9dSJames Smart 	struct fcp_cmd_rsp_buf *tmp = NULL;
60919ca7609SJames Smart 
610d6d189ceSBart Van Assche 	cpu = raw_smp_processor_id();
61145aa312eSJames Smart 	if (cmnd && phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ) {
6124221c8a4SBart Van Assche 		tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmnd));
613ace44e48SJames Smart 		idx = blk_mq_unique_tag_to_hwq(tag);
614ace44e48SJames Smart 	} else {
6156a828b0fSJames Smart 		idx = phba->sli4_hba.cpu_map[cpu].hdwq;
616ace44e48SJames Smart 	}
6175e5b511dSJames Smart 
618c490850aSJames Smart 	lpfc_cmd = lpfc_get_io_buf(phba, ndlp, idx,
619c490850aSJames Smart 				   !phba->cfg_xri_rebalancing);
620c490850aSJames Smart 	if (!lpfc_cmd) {
6215e5b511dSJames Smart 		qp = &phba->sli4_hba.hdwq[idx];
6225e5b511dSJames Smart 		qp->empty_io_bufs++;
6231151e3ecSJames Smart 		return NULL;
6245e5b511dSJames Smart 	}
6252a5b7d62SJames Smart 
6260794d601SJames Smart 	/* Setup key fields in buffer that may have been changed
6270794d601SJames Smart 	 * if other protocols used this buffer.
6280794d601SJames Smart 	 */
629a680a929SJames Smart 	lpfc_cmd->cur_iocbq.cmd_flag = LPFC_IO_FCP;
6300794d601SJames Smart 	lpfc_cmd->prot_seg_cnt = 0;
6310794d601SJames Smart 	lpfc_cmd->seg_cnt = 0;
6320794d601SJames Smart 	lpfc_cmd->timeout = 0;
6330794d601SJames Smart 	lpfc_cmd->flags = 0;
6340794d601SJames Smart 	lpfc_cmd->start_time = jiffies;
6350794d601SJames Smart 	lpfc_cmd->waitq = NULL;
6365e5b511dSJames Smart 	lpfc_cmd->cpu = cpu;
6370794d601SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
6380794d601SJames Smart 	lpfc_cmd->prot_data_type = 0;
6390794d601SJames Smart #endif
640d79c9e9dSJames Smart 	tmp = lpfc_get_cmd_rsp_buf_per_hdwq(phba, lpfc_cmd);
6410ab384a4SJames Smart 	if (!tmp) {
6420ab384a4SJames Smart 		lpfc_release_io_buf(phba, lpfc_cmd, lpfc_cmd->hdwq);
643d79c9e9dSJames Smart 		return NULL;
6440ab384a4SJames Smart 	}
645d79c9e9dSJames Smart 
646d79c9e9dSJames Smart 	lpfc_cmd->fcp_cmnd = tmp->fcp_cmnd;
647d79c9e9dSJames Smart 	lpfc_cmd->fcp_rsp = tmp->fcp_rsp;
6480794d601SJames Smart 
6490794d601SJames Smart 	/*
6500794d601SJames Smart 	 * The first two SGEs are the FCP_CMD and FCP_RSP.
6510794d601SJames Smart 	 * The balance are sg list bdes. Initialize the
6520794d601SJames Smart 	 * first two and leave the rest for queuecommand.
6530794d601SJames Smart 	 */
654af20bb73SJustin Tee 	sgl = (struct sli4_sge_le *)lpfc_cmd->dma_sgl;
655d79c9e9dSJames Smart 	pdma_phys_fcp_cmd = tmp->fcp_cmd_rsp_dma_handle;
6560794d601SJames Smart 	sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd));
6570794d601SJames Smart 	sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd));
658af20bb73SJustin Tee 	bf_set_le32(lpfc_sli4_sge_last, sgl, 0);
659af20bb73SJustin Tee 	if (cmnd && cmnd->cmd_len > LPFC_FCP_CDB_LEN)
660af20bb73SJustin Tee 		sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd32));
661af20bb73SJustin Tee 	else
6620794d601SJames Smart 		sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd));
663af20bb73SJustin Tee 
6640794d601SJames Smart 	sgl++;
6650794d601SJames Smart 
6660794d601SJames Smart 	/* Setup the physical region for the FCP RSP */
667af20bb73SJustin Tee 	pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd32);
6680794d601SJames Smart 	sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp));
6690794d601SJames Smart 	sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp));
670af20bb73SJustin Tee 	bf_set_le32(lpfc_sli4_sge_last, sgl, 1);
6710794d601SJames Smart 	sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp));
6720794d601SJames Smart 
67326c724a6SDan Carpenter 	if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
6742a5b7d62SJames Smart 		atomic_inc(&ndlp->cmd_pending);
6752a5b7d62SJames Smart 		lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH;
6762a5b7d62SJames Smart 	}
67719ca7609SJames Smart 	return  lpfc_cmd;
67819ca7609SJames Smart }
67919ca7609SJames Smart /**
68019ca7609SJames Smart  * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
68119ca7609SJames Smart  * @phba: The HBA for which this call is being executed.
682eceee00eSLee Jones  * @ndlp: pointer to a node-list data structure.
683eceee00eSLee Jones  * @cmnd: Pointer to scsi_cmnd data structure.
68419ca7609SJames Smart  *
68519ca7609SJames Smart  * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
68619ca7609SJames Smart  * and returns to caller.
68719ca7609SJames Smart  *
68819ca7609SJames Smart  * Return codes:
68919ca7609SJames Smart  *   NULL - Error
69019ca7609SJames Smart  *   Pointer to lpfc_scsi_buf - Success
69119ca7609SJames Smart  **/
692c490850aSJames Smart static struct lpfc_io_buf*
lpfc_get_scsi_buf(struct lpfc_hba * phba,struct lpfc_nodelist * ndlp,struct scsi_cmnd * cmnd)693ace44e48SJames Smart lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
694ace44e48SJames Smart 		  struct scsi_cmnd *cmnd)
69519ca7609SJames Smart {
696ace44e48SJames Smart 	return  phba->lpfc_get_scsi_buf(phba, ndlp, cmnd);
69719ca7609SJames Smart }
6980bd4ca25SJames.Smart@Emulex.Com 
6999bad7671SJames Smart /**
7000bb87e01SLee Jones  * lpfc_release_scsi_buf_s3 - Return a scsi buffer back to hba scsi buf list
7019bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
7029bad7671SJames Smart  * @psb: The scsi buffer which is being released.
7039bad7671SJames Smart  *
7049bad7671SJames Smart  * This routine releases @psb scsi buffer by adding it to tail of @phba
7059bad7671SJames Smart  * lpfc_scsi_buf_list list.
7069bad7671SJames Smart  **/
7070bd4ca25SJames.Smart@Emulex.Com static void
lpfc_release_scsi_buf_s3(struct lpfc_hba * phba,struct lpfc_io_buf * psb)708c490850aSJames Smart lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
7090bd4ca25SJames.Smart@Emulex.Com {
710875fbdfeSJames.Smart@Emulex.Com 	unsigned long iflag = 0;
711dea3101eS 
712a40fc5f0SJames Smart 	psb->seg_cnt = 0;
713a40fc5f0SJames Smart 	psb->prot_seg_cnt = 0;
714a40fc5f0SJames Smart 
715a40fc5f0SJames Smart 	spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
7160bd4ca25SJames.Smart@Emulex.Com 	psb->pCmd = NULL;
717a680a929SJames Smart 	psb->cur_iocbq.cmd_flag = LPFC_IO_FCP;
718a40fc5f0SJames Smart 	list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
719a40fc5f0SJames Smart 	spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
720dea3101eS }
721dea3101eS 
7229bad7671SJames Smart /**
723da0436e9SJames Smart  * lpfc_release_scsi_buf_s4: Return a scsi buffer back to hba scsi buf list.
724da0436e9SJames Smart  * @phba: The Hba for which this call is being executed.
725da0436e9SJames Smart  * @psb: The scsi buffer which is being released.
726da0436e9SJames Smart  *
7275e5b511dSJames Smart  * This routine releases @psb scsi buffer by adding it to tail of @hdwq
7285e5b511dSJames Smart  * io_buf_list list. For SLI4 XRI's are tied to the scsi buffer
729da0436e9SJames Smart  * and cannot be reused for at least RA_TOV amount of time if it was
730da0436e9SJames Smart  * aborted.
731da0436e9SJames Smart  **/
732da0436e9SJames Smart static void
lpfc_release_scsi_buf_s4(struct lpfc_hba * phba,struct lpfc_io_buf * psb)733c490850aSJames Smart lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
734da0436e9SJames Smart {
7355e5b511dSJames Smart 	struct lpfc_sli4_hdw_queue *qp;
736da0436e9SJames Smart 	unsigned long iflag = 0;
737da0436e9SJames Smart 
738a40fc5f0SJames Smart 	psb->seg_cnt = 0;
739a40fc5f0SJames Smart 	psb->prot_seg_cnt = 0;
740a40fc5f0SJames Smart 
7411fbf9742SJames Smart 	qp = psb->hdwq;
742324e1c40SJames Smart 	if (psb->flags & LPFC_SBUF_XBUSY) {
743c00f62e6SJames Smart 		spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag);
7443e49af93SJames Smart 		if (!phba->cfg_fcp_wait_abts_rsp)
745da0436e9SJames Smart 			psb->pCmd = NULL;
746c00f62e6SJames Smart 		list_add_tail(&psb->list, &qp->lpfc_abts_io_buf_list);
7475e5b511dSJames Smart 		qp->abts_scsi_io_bufs++;
748c00f62e6SJames Smart 		spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag);
749da0436e9SJames Smart 	} else {
750c490850aSJames Smart 		lpfc_release_io_buf(phba, (struct lpfc_io_buf *)psb, qp);
751da0436e9SJames Smart 	}
752da0436e9SJames Smart }
753da0436e9SJames Smart 
754da0436e9SJames Smart /**
7553772a991SJames Smart  * lpfc_release_scsi_buf: Return a scsi buffer back to hba scsi buf list.
7563772a991SJames Smart  * @phba: The Hba for which this call is being executed.
7573772a991SJames Smart  * @psb: The scsi buffer which is being released.
7583772a991SJames Smart  *
7593772a991SJames Smart  * This routine releases @psb scsi buffer by adding it to tail of @phba
7603772a991SJames Smart  * lpfc_scsi_buf_list list.
7613772a991SJames Smart  **/
7623772a991SJames Smart static void
lpfc_release_scsi_buf(struct lpfc_hba * phba,struct lpfc_io_buf * psb)763c490850aSJames Smart lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
7643772a991SJames Smart {
7652a5b7d62SJames Smart 	if ((psb->flags & LPFC_SBUF_BUMP_QDEPTH) && psb->ndlp)
7662a5b7d62SJames Smart 		atomic_dec(&psb->ndlp->cmd_pending);
7673772a991SJames Smart 
7682a5b7d62SJames Smart 	psb->flags &= ~LPFC_SBUF_BUMP_QDEPTH;
7693772a991SJames Smart 	phba->lpfc_release_scsi_buf(phba, psb);
7703772a991SJames Smart }
7713772a991SJames Smart 
7723772a991SJames Smart /**
773da255e2eSJames Smart  * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB
774da255e2eSJames Smart  * @data: A pointer to the immediate command data portion of the IOCB.
775da255e2eSJames Smart  * @fcp_cmnd: The FCP Command that is provided by the SCSI layer.
776da255e2eSJames Smart  *
777da255e2eSJames Smart  * The routine copies the entire FCP command from @fcp_cmnd to @data while
778da255e2eSJames Smart  * byte swapping the data to big endian format for transmission on the wire.
779da255e2eSJames Smart  **/
780da255e2eSJames Smart static void
lpfc_fcpcmd_to_iocb(u8 * data,struct fcp_cmnd * fcp_cmnd)781da255e2eSJames Smart lpfc_fcpcmd_to_iocb(u8 *data, struct fcp_cmnd *fcp_cmnd)
782da255e2eSJames Smart {
783da255e2eSJames Smart 	int i, j;
784da255e2eSJames Smart 
785da255e2eSJames Smart 	for (i = 0, j = 0; i < sizeof(struct fcp_cmnd);
786da255e2eSJames Smart 	     i += sizeof(uint32_t), j++) {
787da255e2eSJames Smart 		((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]);
788da255e2eSJames Smart 	}
789da255e2eSJames Smart }
790da255e2eSJames Smart 
791da255e2eSJames Smart /**
7923772a991SJames Smart  * lpfc_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec
7939bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
7949bad7671SJames Smart  * @lpfc_cmd: The scsi buffer which is going to be mapped.
7959bad7671SJames Smart  *
7969bad7671SJames Smart  * This routine does the pci dma mapping for scatter-gather list of scsi cmnd
7973772a991SJames Smart  * field of @lpfc_cmd for device with SLI-3 interface spec. This routine scans
7984b160ae8SMilan P. Gandhi  * through sg elements and format the bde. This routine also initializes all
7993772a991SJames Smart  * IOCB fields which are dependent on scsi command request buffer.
8009bad7671SJames Smart  *
8019bad7671SJames Smart  * Return codes:
8029bad7671SJames Smart  *   1 - Error
8039bad7671SJames Smart  *   0 - Success
8049bad7671SJames Smart  **/
805dea3101eS static int
lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)806c490850aSJames Smart lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
807dea3101eS {
808dea3101eS 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
809dea3101eS 	struct scatterlist *sgel = NULL;
810dea3101eS 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
811c490850aSJames Smart 	struct ulp_bde64 *bpl = (struct ulp_bde64 *)lpfc_cmd->dma_sgl;
8120f65ff68SJames Smart 	struct lpfc_iocbq *iocbq = &lpfc_cmd->cur_iocbq;
813dea3101eS 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
81434b02dcdSJames Smart 	struct ulp_bde64 *data_bde = iocb_cmd->unsli3.fcp_ext.dbde;
815dea3101eS 	dma_addr_t physaddr;
81634b02dcdSJames Smart 	uint32_t num_bde = 0;
817a0b4f78fSFUJITA Tomonori 	int nseg, datadir = scsi_cmnd->sc_data_direction;
818dea3101eS 
819dea3101eS 	/*
820dea3101eS 	 * There are three possibilities here - use scatter-gather segment, use
821dea3101eS 	 * the single mapping, or neither.  Start the lpfc command prep by
822dea3101eS 	 * bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
823dea3101eS 	 * data bde entry.
824dea3101eS 	 */
825dea3101eS 	bpl += 2;
826c59fd9ebSFUJITA Tomonori 	if (scsi_sg_count(scsi_cmnd)) {
827dea3101eS 		/*
8288d807a06SCai Huoqing 		 * The driver stores the segment count returned from dma_map_sg
829dea3101eS 		 * because this a count of dma-mappings used to map the use_sg
830dea3101eS 		 * pages.  They are not guaranteed to be the same for those
831dea3101eS 		 * architectures that implement an IOMMU.
832dea3101eS 		 */
833dea3101eS 
834c59fd9ebSFUJITA Tomonori 		nseg = dma_map_sg(&phba->pcidev->dev, scsi_sglist(scsi_cmnd),
835c59fd9ebSFUJITA Tomonori 				  scsi_sg_count(scsi_cmnd), datadir);
836c59fd9ebSFUJITA Tomonori 		if (unlikely(!nseg))
837c59fd9ebSFUJITA Tomonori 			return 1;
838c59fd9ebSFUJITA Tomonori 
839a0b4f78fSFUJITA Tomonori 		lpfc_cmd->seg_cnt = nseg;
840dea3101eS 		if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
841372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
842372c187bSDick Kennedy 					"9064 BLKGRD: %s: Too many sg segments"
843372c187bSDick Kennedy 					" from dma_map_sg.  Config %d, seg_cnt"
844372c187bSDick Kennedy 					" %d\n", __func__, phba->cfg_sg_seg_cnt,
845dea3101eS 					lpfc_cmd->seg_cnt);
8465e0e2318SJames Smart 			WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt);
84796f7077fSJames Smart 			lpfc_cmd->seg_cnt = 0;
848a0b4f78fSFUJITA Tomonori 			scsi_dma_unmap(scsi_cmnd);
8495e0e2318SJames Smart 			return 2;
850dea3101eS 		}
851dea3101eS 
852dea3101eS 		/*
853dea3101eS 		 * The driver established a maximum scatter-gather segment count
854dea3101eS 		 * during probe that limits the number of sg elements in any
855dea3101eS 		 * single scsi command.  Just run through the seg_cnt and format
856dea3101eS 		 * the bde's.
85734b02dcdSJames Smart 		 * When using SLI-3 the driver will try to fit all the BDEs into
85834b02dcdSJames Smart 		 * the IOCB. If it can't then the BDEs get added to a BPL as it
85934b02dcdSJames Smart 		 * does for SLI-2 mode.
860dea3101eS 		 */
86134b02dcdSJames Smart 		scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) {
862dea3101eS 			physaddr = sg_dma_address(sgel);
86334b02dcdSJames Smart 			if (phba->sli_rev == 3 &&
864e2a0a9d6SJames Smart 			    !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
865a680a929SJames Smart 			    !(iocbq->cmd_flag & DSS_SECURITY_OP) &&
86634b02dcdSJames Smart 			    nseg <= LPFC_EXT_DATA_BDE_COUNT) {
86734b02dcdSJames Smart 				data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
86834b02dcdSJames Smart 				data_bde->tus.f.bdeSize = sg_dma_len(sgel);
86934b02dcdSJames Smart 				data_bde->addrLow = putPaddrLow(physaddr);
87034b02dcdSJames Smart 				data_bde->addrHigh = putPaddrHigh(physaddr);
87134b02dcdSJames Smart 				data_bde++;
87234b02dcdSJames Smart 			} else {
87334b02dcdSJames Smart 				bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
874dea3101eS 				bpl->tus.f.bdeSize = sg_dma_len(sgel);
875dea3101eS 				bpl->tus.w = le32_to_cpu(bpl->tus.w);
87634b02dcdSJames Smart 				bpl->addrLow =
87734b02dcdSJames Smart 					le32_to_cpu(putPaddrLow(physaddr));
87834b02dcdSJames Smart 				bpl->addrHigh =
87934b02dcdSJames Smart 					le32_to_cpu(putPaddrHigh(physaddr));
880dea3101eS 				bpl++;
88134b02dcdSJames Smart 			}
882dea3101eS 		}
883c59fd9ebSFUJITA Tomonori 	}
884dea3101eS 
885dea3101eS 	/*
886dea3101eS 	 * Finish initializing those IOCB fields that are dependent on the
88734b02dcdSJames Smart 	 * scsi_cmnd request_buffer.  Note that for SLI-2 the bdeSize is
88834b02dcdSJames Smart 	 * explicitly reinitialized and for SLI-3 the extended bde count is
88934b02dcdSJames Smart 	 * explicitly reinitialized since all iocb memory resources are reused.
890dea3101eS 	 */
891e2a0a9d6SJames Smart 	if (phba->sli_rev == 3 &&
8920f65ff68SJames Smart 	    !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
893a680a929SJames Smart 	    !(iocbq->cmd_flag & DSS_SECURITY_OP)) {
89434b02dcdSJames Smart 		if (num_bde > LPFC_EXT_DATA_BDE_COUNT) {
89534b02dcdSJames Smart 			/*
89634b02dcdSJames Smart 			 * The extended IOCB format can only fit 3 BDE or a BPL.
89734b02dcdSJames Smart 			 * This I/O has more than 3 BDE so the 1st data bde will
89834b02dcdSJames Smart 			 * be a BPL that is filled in here.
89934b02dcdSJames Smart 			 */
90034b02dcdSJames Smart 			physaddr = lpfc_cmd->dma_handle;
90134b02dcdSJames Smart 			data_bde->tus.f.bdeFlags = BUFF_TYPE_BLP_64;
90234b02dcdSJames Smart 			data_bde->tus.f.bdeSize = (num_bde *
90334b02dcdSJames Smart 						   sizeof(struct ulp_bde64));
90434b02dcdSJames Smart 			physaddr += (sizeof(struct fcp_cmnd) +
90534b02dcdSJames Smart 				     sizeof(struct fcp_rsp) +
90634b02dcdSJames Smart 				     (2 * sizeof(struct ulp_bde64)));
90734b02dcdSJames Smart 			data_bde->addrHigh = putPaddrHigh(physaddr);
90834b02dcdSJames Smart 			data_bde->addrLow = putPaddrLow(physaddr);
90925985edcSLucas De Marchi 			/* ebde count includes the response bde and data bpl */
91034b02dcdSJames Smart 			iocb_cmd->unsli3.fcp_ext.ebde_count = 2;
91134b02dcdSJames Smart 		} else {
91225985edcSLucas De Marchi 			/* ebde count includes the response bde and data bdes */
91334b02dcdSJames Smart 			iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1);
91434b02dcdSJames Smart 		}
91534b02dcdSJames Smart 	} else {
91634b02dcdSJames Smart 		iocb_cmd->un.fcpi64.bdl.bdeSize =
91734b02dcdSJames Smart 			((num_bde + 2) * sizeof(struct ulp_bde64));
9180f65ff68SJames Smart 		iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1);
91934b02dcdSJames Smart 	}
92009372820SJames Smart 	fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
921e2a0a9d6SJames Smart 
922e2a0a9d6SJames Smart 	/*
923e2a0a9d6SJames Smart 	 * Due to difference in data length between DIF/non-DIF paths,
924e2a0a9d6SJames Smart 	 * we need to set word 4 of IOCB here
925e2a0a9d6SJames Smart 	 */
926a257bf90SJames Smart 	iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
927da255e2eSJames Smart 	lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd);
928dea3101eS 	return 0;
929dea3101eS }
930dea3101eS 
931f9bb2da1SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
932acd6859bSJames Smart 
9334b160ae8SMilan P. Gandhi /* Return BG_ERR_INIT if error injection is detected by Initiator */
9349a6b09c0SJames Smart #define BG_ERR_INIT	0x1
9354b160ae8SMilan P. Gandhi /* Return BG_ERR_TGT if error injection is detected by Target */
9369a6b09c0SJames Smart #define BG_ERR_TGT	0x2
9374b160ae8SMilan P. Gandhi /* Return BG_ERR_SWAP if swapping CSUM<-->CRC is required for error injection */
9389a6b09c0SJames Smart #define BG_ERR_SWAP	0x10
9390bb87e01SLee Jones /*
9404b160ae8SMilan P. Gandhi  * Return BG_ERR_CHECK if disabling Guard/Ref/App checking is required for
9414b160ae8SMilan P. Gandhi  * error injection
9420bb87e01SLee Jones  */
9439a6b09c0SJames Smart #define BG_ERR_CHECK	0x20
944acd6859bSJames Smart 
945acd6859bSJames Smart /**
946acd6859bSJames Smart  * lpfc_bg_err_inject - Determine if we should inject an error
947acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
948f9bb2da1SJames Smart  * @sc: The SCSI command to examine
949f9bb2da1SJames Smart  * @reftag: (out) BlockGuard reference tag for transmitted data
950f9bb2da1SJames Smart  * @apptag: (out) BlockGuard application tag for transmitted data
951eceee00eSLee Jones  * @new_guard: (in) Value to replace CRC with if needed
952f9bb2da1SJames Smart  *
9539a6b09c0SJames Smart  * Returns BG_ERR_* bit mask or 0 if request ignored
954acd6859bSJames Smart  **/
955f9bb2da1SJames Smart static int
lpfc_bg_err_inject(struct lpfc_hba * phba,struct scsi_cmnd * sc,uint32_t * reftag,uint16_t * apptag,uint32_t new_guard)956f9bb2da1SJames Smart lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
957f9bb2da1SJames Smart 		uint32_t *reftag, uint16_t *apptag, uint32_t new_guard)
958f9bb2da1SJames Smart {
959f9bb2da1SJames Smart 	struct scatterlist *sgpe; /* s/g prot entry */
960c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd = NULL;
961acd6859bSJames Smart 	struct scsi_dif_tuple *src = NULL;
9624ac9b226SJames Smart 	struct lpfc_nodelist *ndlp;
9634ac9b226SJames Smart 	struct lpfc_rport_data *rdata;
964f9bb2da1SJames Smart 	uint32_t op = scsi_get_prot_op(sc);
965f9bb2da1SJames Smart 	uint32_t blksize;
966f9bb2da1SJames Smart 	uint32_t numblks;
96768a6a66cSJames Smart 	u32 lba;
968f9bb2da1SJames Smart 	int rc = 0;
969acd6859bSJames Smart 	int blockoff = 0;
970f9bb2da1SJames Smart 
971f9bb2da1SJames Smart 	if (op == SCSI_PROT_NORMAL)
972f9bb2da1SJames Smart 		return 0;
973f9bb2da1SJames Smart 
974acd6859bSJames Smart 	sgpe = scsi_prot_sglist(sc);
975125c12f7SMartin K. Petersen 	lba = scsi_prot_ref_tag(sc);
9764ac9b226SJames Smart 
9774ac9b226SJames Smart 	/* First check if we need to match the LBA */
978f9bb2da1SJames Smart 	if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
979125c12f7SMartin K. Petersen 		blksize = scsi_prot_interval(sc);
980f9bb2da1SJames Smart 		numblks = (scsi_bufflen(sc) + blksize - 1) / blksize;
981f9bb2da1SJames Smart 
982f9bb2da1SJames Smart 		/* Make sure we have the right LBA if one is specified */
98368a6a66cSJames Smart 		if (phba->lpfc_injerr_lba < (u64)lba ||
98468a6a66cSJames Smart 		    (phba->lpfc_injerr_lba >= (u64)(lba + numblks)))
985f9bb2da1SJames Smart 			return 0;
986acd6859bSJames Smart 		if (sgpe) {
98768a6a66cSJames Smart 			blockoff = phba->lpfc_injerr_lba - (u64)lba;
988acd6859bSJames Smart 			numblks = sg_dma_len(sgpe) /
989acd6859bSJames Smart 				sizeof(struct scsi_dif_tuple);
990acd6859bSJames Smart 			if (numblks < blockoff)
991acd6859bSJames Smart 				blockoff = numblks;
9924ac9b226SJames Smart 		}
9934ac9b226SJames Smart 	}
9944ac9b226SJames Smart 
9954ac9b226SJames Smart 	/* Next check if we need to match the remote NPortID or WWPN */
9961ba981fdSJames Smart 	rdata = lpfc_rport_data_from_scsi_device(sc->device);
9974ac9b226SJames Smart 	if (rdata && rdata->pnode) {
9984ac9b226SJames Smart 		ndlp = rdata->pnode;
9994ac9b226SJames Smart 
10004ac9b226SJames Smart 		/* Make sure we have the right NPortID if one is specified */
10014ac9b226SJames Smart 		if (phba->lpfc_injerr_nportid  &&
10024ac9b226SJames Smart 			(phba->lpfc_injerr_nportid != ndlp->nlp_DID))
10034ac9b226SJames Smart 			return 0;
10044ac9b226SJames Smart 
10054ac9b226SJames Smart 		/*
10064ac9b226SJames Smart 		 * Make sure we have the right WWPN if one is specified.
10074ac9b226SJames Smart 		 * wwn[0] should be a non-zero NAA in a good WWPN.
10084ac9b226SJames Smart 		 */
10094ac9b226SJames Smart 		if (phba->lpfc_injerr_wwpn.u.wwn[0]  &&
10104ac9b226SJames Smart 			(memcmp(&ndlp->nlp_portname, &phba->lpfc_injerr_wwpn,
10114ac9b226SJames Smart 				sizeof(struct lpfc_name)) != 0))
10124ac9b226SJames Smart 			return 0;
10134ac9b226SJames Smart 	}
10144ac9b226SJames Smart 
10154ac9b226SJames Smart 	/* Setup a ptr to the protection data if the SCSI host provides it */
10164ac9b226SJames Smart 	if (sgpe) {
1017acd6859bSJames Smart 		src = (struct scsi_dif_tuple *)sg_virt(sgpe);
1018acd6859bSJames Smart 		src += blockoff;
1019c490850aSJames Smart 		lpfc_cmd = (struct lpfc_io_buf *)sc->host_scribble;
1020f9bb2da1SJames Smart 	}
1021f9bb2da1SJames Smart 
1022f9bb2da1SJames Smart 	/* Should we change the Reference Tag */
1023f9bb2da1SJames Smart 	if (reftag) {
1024f9bb2da1SJames Smart 		if (phba->lpfc_injerr_wref_cnt) {
1025acd6859bSJames Smart 			switch (op) {
1026acd6859bSJames Smart 			case SCSI_PROT_WRITE_PASS:
10279a6b09c0SJames Smart 				if (src) {
10289a6b09c0SJames Smart 					/*
10299a6b09c0SJames Smart 					 * For WRITE_PASS, force the error
10309a6b09c0SJames Smart 					 * to be sent on the wire. It should
10319a6b09c0SJames Smart 					 * be detected by the Target.
10329a6b09c0SJames Smart 					 * If blockoff != 0 error will be
10339a6b09c0SJames Smart 					 * inserted in middle of the IO.
10349a6b09c0SJames Smart 					 */
1035f9bb2da1SJames Smart 
1036372c187bSDick Kennedy 					lpfc_printf_log(phba, KERN_ERR,
1037372c187bSDick Kennedy 							LOG_TRACE_EVENT,
1038acd6859bSJames Smart 					"9076 BLKGRD: Injecting reftag error: "
1039acd6859bSJames Smart 					"write lba x%lx + x%x oldrefTag x%x\n",
1040acd6859bSJames Smart 					(unsigned long)lba, blockoff,
10419a6b09c0SJames Smart 					be32_to_cpu(src->ref_tag));
1042acd6859bSJames Smart 
1043acd6859bSJames Smart 					/*
10449a6b09c0SJames Smart 					 * Save the old ref_tag so we can
10459a6b09c0SJames Smart 					 * restore it on completion.
1046acd6859bSJames Smart 					 */
10479a6b09c0SJames Smart 					if (lpfc_cmd) {
10489a6b09c0SJames Smart 						lpfc_cmd->prot_data_type =
10499a6b09c0SJames Smart 							LPFC_INJERR_REFTAG;
10509a6b09c0SJames Smart 						lpfc_cmd->prot_data_segment =
10519a6b09c0SJames Smart 							src;
10529a6b09c0SJames Smart 						lpfc_cmd->prot_data =
10539a6b09c0SJames Smart 							src->ref_tag;
10549a6b09c0SJames Smart 					}
10559a6b09c0SJames Smart 					src->ref_tag = cpu_to_be32(0xDEADBEEF);
1056acd6859bSJames Smart 					phba->lpfc_injerr_wref_cnt--;
10574ac9b226SJames Smart 					if (phba->lpfc_injerr_wref_cnt == 0) {
10584ac9b226SJames Smart 						phba->lpfc_injerr_nportid = 0;
1059acd6859bSJames Smart 						phba->lpfc_injerr_lba =
1060acd6859bSJames Smart 							LPFC_INJERR_LBA_OFF;
10614ac9b226SJames Smart 						memset(&phba->lpfc_injerr_wwpn,
10624ac9b226SJames Smart 						  0, sizeof(struct lpfc_name));
10634ac9b226SJames Smart 					}
10649a6b09c0SJames Smart 					rc = BG_ERR_TGT | BG_ERR_CHECK;
10659a6b09c0SJames Smart 
1066acd6859bSJames Smart 					break;
1067acd6859bSJames Smart 				}
1068df561f66SGustavo A. R. Silva 				fallthrough;
10699a6b09c0SJames Smart 			case SCSI_PROT_WRITE_INSERT:
10709a6b09c0SJames Smart 				/*
10719a6b09c0SJames Smart 				 * For WRITE_INSERT, force the error
10729a6b09c0SJames Smart 				 * to be sent on the wire. It should be
10739a6b09c0SJames Smart 				 * detected by the Target.
10749a6b09c0SJames Smart 				 */
10759a6b09c0SJames Smart 				/* DEADBEEF will be the reftag on the wire */
10769a6b09c0SJames Smart 				*reftag = 0xDEADBEEF;
10779a6b09c0SJames Smart 				phba->lpfc_injerr_wref_cnt--;
10784ac9b226SJames Smart 				if (phba->lpfc_injerr_wref_cnt == 0) {
10794ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
10804ac9b226SJames Smart 					phba->lpfc_injerr_lba =
10814ac9b226SJames Smart 					LPFC_INJERR_LBA_OFF;
10824ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
10834ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
10844ac9b226SJames Smart 				}
10859a6b09c0SJames Smart 				rc = BG_ERR_TGT | BG_ERR_CHECK;
10869a6b09c0SJames Smart 
1087372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
10889a6b09c0SJames Smart 					"9078 BLKGRD: Injecting reftag error: "
10899a6b09c0SJames Smart 					"write lba x%lx\n", (unsigned long)lba);
10909a6b09c0SJames Smart 				break;
1091acd6859bSJames Smart 			case SCSI_PROT_WRITE_STRIP:
1092acd6859bSJames Smart 				/*
1093acd6859bSJames Smart 				 * For WRITE_STRIP and WRITE_PASS,
1094acd6859bSJames Smart 				 * force the error on data
1095acd6859bSJames Smart 				 * being copied from SLI-Host to SLI-Port.
1096acd6859bSJames Smart 				 */
1097acd6859bSJames Smart 				*reftag = 0xDEADBEEF;
1098acd6859bSJames Smart 				phba->lpfc_injerr_wref_cnt--;
10994ac9b226SJames Smart 				if (phba->lpfc_injerr_wref_cnt == 0) {
11004ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
11014ac9b226SJames Smart 					phba->lpfc_injerr_lba =
11024ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
11034ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
11044ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
11054ac9b226SJames Smart 				}
1106acd6859bSJames Smart 				rc = BG_ERR_INIT;
1107acd6859bSJames Smart 
1108372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
1109acd6859bSJames Smart 					"9077 BLKGRD: Injecting reftag error: "
1110acd6859bSJames Smart 					"write lba x%lx\n", (unsigned long)lba);
1111acd6859bSJames Smart 				break;
1112f9bb2da1SJames Smart 			}
1113acd6859bSJames Smart 		}
1114f9bb2da1SJames Smart 		if (phba->lpfc_injerr_rref_cnt) {
1115acd6859bSJames Smart 			switch (op) {
1116acd6859bSJames Smart 			case SCSI_PROT_READ_INSERT:
1117acd6859bSJames Smart 			case SCSI_PROT_READ_STRIP:
1118acd6859bSJames Smart 			case SCSI_PROT_READ_PASS:
1119acd6859bSJames Smart 				/*
1120acd6859bSJames Smart 				 * For READ_STRIP and READ_PASS, force the
1121acd6859bSJames Smart 				 * error on data being read off the wire. It
1122acd6859bSJames Smart 				 * should force an IO error to the driver.
1123acd6859bSJames Smart 				 */
1124f9bb2da1SJames Smart 				*reftag = 0xDEADBEEF;
1125f9bb2da1SJames Smart 				phba->lpfc_injerr_rref_cnt--;
11264ac9b226SJames Smart 				if (phba->lpfc_injerr_rref_cnt == 0) {
11274ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
11284ac9b226SJames Smart 					phba->lpfc_injerr_lba =
11294ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
11304ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
11314ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
11324ac9b226SJames Smart 				}
1133acd6859bSJames Smart 				rc = BG_ERR_INIT;
1134f9bb2da1SJames Smart 
1135372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
1136acd6859bSJames Smart 					"9079 BLKGRD: Injecting reftag error: "
1137f9bb2da1SJames Smart 					"read lba x%lx\n", (unsigned long)lba);
1138acd6859bSJames Smart 				break;
1139f9bb2da1SJames Smart 			}
1140f9bb2da1SJames Smart 		}
1141f9bb2da1SJames Smart 	}
1142f9bb2da1SJames Smart 
1143f9bb2da1SJames Smart 	/* Should we change the Application Tag */
1144f9bb2da1SJames Smart 	if (apptag) {
1145f9bb2da1SJames Smart 		if (phba->lpfc_injerr_wapp_cnt) {
1146acd6859bSJames Smart 			switch (op) {
1147acd6859bSJames Smart 			case SCSI_PROT_WRITE_PASS:
11484ac9b226SJames Smart 				if (src) {
11499a6b09c0SJames Smart 					/*
11509a6b09c0SJames Smart 					 * For WRITE_PASS, force the error
11519a6b09c0SJames Smart 					 * to be sent on the wire. It should
11529a6b09c0SJames Smart 					 * be detected by the Target.
11539a6b09c0SJames Smart 					 * If blockoff != 0 error will be
11549a6b09c0SJames Smart 					 * inserted in middle of the IO.
11559a6b09c0SJames Smart 					 */
11569a6b09c0SJames Smart 
1157372c187bSDick Kennedy 					lpfc_printf_log(phba, KERN_ERR,
1158372c187bSDick Kennedy 							LOG_TRACE_EVENT,
1159acd6859bSJames Smart 					"9080 BLKGRD: Injecting apptag error: "
1160acd6859bSJames Smart 					"write lba x%lx + x%x oldappTag x%x\n",
1161acd6859bSJames Smart 					(unsigned long)lba, blockoff,
11629a6b09c0SJames Smart 					be16_to_cpu(src->app_tag));
1163acd6859bSJames Smart 
1164acd6859bSJames Smart 					/*
11659a6b09c0SJames Smart 					 * Save the old app_tag so we can
11669a6b09c0SJames Smart 					 * restore it on completion.
1167acd6859bSJames Smart 					 */
11689a6b09c0SJames Smart 					if (lpfc_cmd) {
11699a6b09c0SJames Smart 						lpfc_cmd->prot_data_type =
11709a6b09c0SJames Smart 							LPFC_INJERR_APPTAG;
11719a6b09c0SJames Smart 						lpfc_cmd->prot_data_segment =
11729a6b09c0SJames Smart 							src;
11739a6b09c0SJames Smart 						lpfc_cmd->prot_data =
11749a6b09c0SJames Smart 							src->app_tag;
11759a6b09c0SJames Smart 					}
11769a6b09c0SJames Smart 					src->app_tag = cpu_to_be16(0xDEAD);
1177acd6859bSJames Smart 					phba->lpfc_injerr_wapp_cnt--;
11784ac9b226SJames Smart 					if (phba->lpfc_injerr_wapp_cnt == 0) {
11794ac9b226SJames Smart 						phba->lpfc_injerr_nportid = 0;
1180acd6859bSJames Smart 						phba->lpfc_injerr_lba =
1181acd6859bSJames Smart 							LPFC_INJERR_LBA_OFF;
11824ac9b226SJames Smart 						memset(&phba->lpfc_injerr_wwpn,
11834ac9b226SJames Smart 						  0, sizeof(struct lpfc_name));
11844ac9b226SJames Smart 					}
11859a6b09c0SJames Smart 					rc = BG_ERR_TGT | BG_ERR_CHECK;
1186acd6859bSJames Smart 					break;
1187acd6859bSJames Smart 				}
1188df561f66SGustavo A. R. Silva 				fallthrough;
11899a6b09c0SJames Smart 			case SCSI_PROT_WRITE_INSERT:
11909a6b09c0SJames Smart 				/*
11919a6b09c0SJames Smart 				 * For WRITE_INSERT, force the
11929a6b09c0SJames Smart 				 * error to be sent on the wire. It should be
11939a6b09c0SJames Smart 				 * detected by the Target.
11949a6b09c0SJames Smart 				 */
11959a6b09c0SJames Smart 				/* DEAD will be the apptag on the wire */
11969a6b09c0SJames Smart 				*apptag = 0xDEAD;
11979a6b09c0SJames Smart 				phba->lpfc_injerr_wapp_cnt--;
11984ac9b226SJames Smart 				if (phba->lpfc_injerr_wapp_cnt == 0) {
11994ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
12004ac9b226SJames Smart 					phba->lpfc_injerr_lba =
12014ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
12024ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
12034ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
12044ac9b226SJames Smart 				}
12059a6b09c0SJames Smart 				rc = BG_ERR_TGT | BG_ERR_CHECK;
12069a6b09c0SJames Smart 
1207372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
12089a6b09c0SJames Smart 					"0813 BLKGRD: Injecting apptag error: "
12099a6b09c0SJames Smart 					"write lba x%lx\n", (unsigned long)lba);
12109a6b09c0SJames Smart 				break;
1211acd6859bSJames Smart 			case SCSI_PROT_WRITE_STRIP:
1212acd6859bSJames Smart 				/*
1213acd6859bSJames Smart 				 * For WRITE_STRIP and WRITE_PASS,
1214acd6859bSJames Smart 				 * force the error on data
1215acd6859bSJames Smart 				 * being copied from SLI-Host to SLI-Port.
1216acd6859bSJames Smart 				 */
1217acd6859bSJames Smart 				*apptag = 0xDEAD;
1218acd6859bSJames Smart 				phba->lpfc_injerr_wapp_cnt--;
12194ac9b226SJames Smart 				if (phba->lpfc_injerr_wapp_cnt == 0) {
12204ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
12214ac9b226SJames Smart 					phba->lpfc_injerr_lba =
12224ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
12234ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
12244ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
12254ac9b226SJames Smart 				}
1226acd6859bSJames Smart 				rc = BG_ERR_INIT;
1227acd6859bSJames Smart 
1228372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
1229acd6859bSJames Smart 					"0812 BLKGRD: Injecting apptag error: "
1230acd6859bSJames Smart 					"write lba x%lx\n", (unsigned long)lba);
1231acd6859bSJames Smart 				break;
1232f9bb2da1SJames Smart 			}
1233acd6859bSJames Smart 		}
1234f9bb2da1SJames Smart 		if (phba->lpfc_injerr_rapp_cnt) {
1235acd6859bSJames Smart 			switch (op) {
1236acd6859bSJames Smart 			case SCSI_PROT_READ_INSERT:
1237acd6859bSJames Smart 			case SCSI_PROT_READ_STRIP:
1238acd6859bSJames Smart 			case SCSI_PROT_READ_PASS:
1239acd6859bSJames Smart 				/*
1240acd6859bSJames Smart 				 * For READ_STRIP and READ_PASS, force the
1241acd6859bSJames Smart 				 * error on data being read off the wire. It
1242acd6859bSJames Smart 				 * should force an IO error to the driver.
1243acd6859bSJames Smart 				 */
1244f9bb2da1SJames Smart 				*apptag = 0xDEAD;
1245f9bb2da1SJames Smart 				phba->lpfc_injerr_rapp_cnt--;
12464ac9b226SJames Smart 				if (phba->lpfc_injerr_rapp_cnt == 0) {
12474ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
12484ac9b226SJames Smart 					phba->lpfc_injerr_lba =
12494ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
12504ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
12514ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
12524ac9b226SJames Smart 				}
1253acd6859bSJames Smart 				rc = BG_ERR_INIT;
1254f9bb2da1SJames Smart 
1255372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
1256acd6859bSJames Smart 					"0814 BLKGRD: Injecting apptag error: "
1257acd6859bSJames Smart 					"read lba x%lx\n", (unsigned long)lba);
1258acd6859bSJames Smart 				break;
1259acd6859bSJames Smart 			}
1260acd6859bSJames Smart 		}
1261acd6859bSJames Smart 	}
1262acd6859bSJames Smart 
1263acd6859bSJames Smart 
1264acd6859bSJames Smart 	/* Should we change the Guard Tag */
1265acd6859bSJames Smart 	if (new_guard) {
1266acd6859bSJames Smart 		if (phba->lpfc_injerr_wgrd_cnt) {
1267acd6859bSJames Smart 			switch (op) {
1268acd6859bSJames Smart 			case SCSI_PROT_WRITE_PASS:
1269acd6859bSJames Smart 				rc = BG_ERR_CHECK;
1270df561f66SGustavo A. R. Silva 				fallthrough;
1271acd6859bSJames Smart 
1272acd6859bSJames Smart 			case SCSI_PROT_WRITE_INSERT:
1273acd6859bSJames Smart 				/*
1274acd6859bSJames Smart 				 * For WRITE_INSERT, force the
1275acd6859bSJames Smart 				 * error to be sent on the wire. It should be
1276acd6859bSJames Smart 				 * detected by the Target.
1277acd6859bSJames Smart 				 */
1278acd6859bSJames Smart 				phba->lpfc_injerr_wgrd_cnt--;
12794ac9b226SJames Smart 				if (phba->lpfc_injerr_wgrd_cnt == 0) {
12804ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
12814ac9b226SJames Smart 					phba->lpfc_injerr_lba =
12824ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
12834ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
12844ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
12854ac9b226SJames Smart 				}
1286acd6859bSJames Smart 
12879a6b09c0SJames Smart 				rc |= BG_ERR_TGT | BG_ERR_SWAP;
1288acd6859bSJames Smart 				/* Signals the caller to swap CRC->CSUM */
1289acd6859bSJames Smart 
1290372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
1291acd6859bSJames Smart 					"0817 BLKGRD: Injecting guard error: "
1292acd6859bSJames Smart 					"write lba x%lx\n", (unsigned long)lba);
1293acd6859bSJames Smart 				break;
12949a6b09c0SJames Smart 			case SCSI_PROT_WRITE_STRIP:
12959a6b09c0SJames Smart 				/*
12969a6b09c0SJames Smart 				 * For WRITE_STRIP and WRITE_PASS,
12979a6b09c0SJames Smart 				 * force the error on data
12989a6b09c0SJames Smart 				 * being copied from SLI-Host to SLI-Port.
12999a6b09c0SJames Smart 				 */
13009a6b09c0SJames Smart 				phba->lpfc_injerr_wgrd_cnt--;
13014ac9b226SJames Smart 				if (phba->lpfc_injerr_wgrd_cnt == 0) {
13024ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
13034ac9b226SJames Smart 					phba->lpfc_injerr_lba =
13044ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
13054ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
13064ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
13074ac9b226SJames Smart 				}
13089a6b09c0SJames Smart 
13099a6b09c0SJames Smart 				rc = BG_ERR_INIT | BG_ERR_SWAP;
13109a6b09c0SJames Smart 				/* Signals the caller to swap CRC->CSUM */
13119a6b09c0SJames Smart 
1312372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
13139a6b09c0SJames Smart 					"0816 BLKGRD: Injecting guard error: "
13149a6b09c0SJames Smart 					"write lba x%lx\n", (unsigned long)lba);
13159a6b09c0SJames Smart 				break;
1316acd6859bSJames Smart 			}
1317acd6859bSJames Smart 		}
1318acd6859bSJames Smart 		if (phba->lpfc_injerr_rgrd_cnt) {
1319acd6859bSJames Smart 			switch (op) {
1320acd6859bSJames Smart 			case SCSI_PROT_READ_INSERT:
1321acd6859bSJames Smart 			case SCSI_PROT_READ_STRIP:
1322acd6859bSJames Smart 			case SCSI_PROT_READ_PASS:
1323acd6859bSJames Smart 				/*
1324acd6859bSJames Smart 				 * For READ_STRIP and READ_PASS, force the
1325acd6859bSJames Smart 				 * error on data being read off the wire. It
1326acd6859bSJames Smart 				 * should force an IO error to the driver.
1327acd6859bSJames Smart 				 */
1328acd6859bSJames Smart 				phba->lpfc_injerr_rgrd_cnt--;
13294ac9b226SJames Smart 				if (phba->lpfc_injerr_rgrd_cnt == 0) {
13304ac9b226SJames Smart 					phba->lpfc_injerr_nportid = 0;
13314ac9b226SJames Smart 					phba->lpfc_injerr_lba =
13324ac9b226SJames Smart 						LPFC_INJERR_LBA_OFF;
13334ac9b226SJames Smart 					memset(&phba->lpfc_injerr_wwpn,
13344ac9b226SJames Smart 						0, sizeof(struct lpfc_name));
13354ac9b226SJames Smart 				}
1336acd6859bSJames Smart 
13379a6b09c0SJames Smart 				rc = BG_ERR_INIT | BG_ERR_SWAP;
1338acd6859bSJames Smart 				/* Signals the caller to swap CRC->CSUM */
1339acd6859bSJames Smart 
1340372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
1341acd6859bSJames Smart 					"0818 BLKGRD: Injecting guard error: "
1342f9bb2da1SJames Smart 					"read lba x%lx\n", (unsigned long)lba);
1343f9bb2da1SJames Smart 			}
1344f9bb2da1SJames Smart 		}
1345f9bb2da1SJames Smart 	}
1346f9bb2da1SJames Smart 
1347f9bb2da1SJames Smart 	return rc;
1348f9bb2da1SJames Smart }
1349f9bb2da1SJames Smart #endif
1350f9bb2da1SJames Smart 
1351acd6859bSJames Smart /**
1352acd6859bSJames Smart  * lpfc_sc_to_bg_opcodes - Determine the BlockGuard opcodes to be used with
1353acd6859bSJames Smart  * the specified SCSI command.
1354acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
13556c8eea54SJames Smart  * @sc: The SCSI command to examine
1356eceee00eSLee Jones  * @txop: (out) BlockGuard operation for transmitted data
1357eceee00eSLee Jones  * @rxop: (out) BlockGuard operation for received data
13586c8eea54SJames Smart  *
13596c8eea54SJames Smart  * Returns: zero on success; non-zero if tx and/or rx op cannot be determined
13606c8eea54SJames Smart  *
1361acd6859bSJames Smart  **/
1362e2a0a9d6SJames Smart static int
lpfc_sc_to_bg_opcodes(struct lpfc_hba * phba,struct scsi_cmnd * sc,uint8_t * txop,uint8_t * rxop)13636c8eea54SJames Smart lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
13646c8eea54SJames Smart 		uint8_t *txop, uint8_t *rxop)
1365e2a0a9d6SJames Smart {
13666c8eea54SJames Smart 	uint8_t ret = 0;
1367e2a0a9d6SJames Smart 
1368125c12f7SMartin K. Petersen 	if (sc->prot_flags & SCSI_PROT_IP_CHECKSUM) {
1369e2a0a9d6SJames Smart 		switch (scsi_get_prot_op(sc)) {
1370e2a0a9d6SJames Smart 		case SCSI_PROT_READ_INSERT:
1371e2a0a9d6SJames Smart 		case SCSI_PROT_WRITE_STRIP:
13726c8eea54SJames Smart 			*rxop = BG_OP_IN_NODIF_OUT_CSUM;
13734ac9b226SJames Smart 			*txop = BG_OP_IN_CSUM_OUT_NODIF;
1374e2a0a9d6SJames Smart 			break;
1375e2a0a9d6SJames Smart 
1376e2a0a9d6SJames Smart 		case SCSI_PROT_READ_STRIP:
1377e2a0a9d6SJames Smart 		case SCSI_PROT_WRITE_INSERT:
13786c8eea54SJames Smart 			*rxop = BG_OP_IN_CRC_OUT_NODIF;
13794ac9b226SJames Smart 			*txop = BG_OP_IN_NODIF_OUT_CRC;
1380e2a0a9d6SJames Smart 			break;
1381e2a0a9d6SJames Smart 
1382c6af4042SMartin K. Petersen 		case SCSI_PROT_READ_PASS:
1383c6af4042SMartin K. Petersen 		case SCSI_PROT_WRITE_PASS:
13846c8eea54SJames Smart 			*rxop = BG_OP_IN_CRC_OUT_CSUM;
13854ac9b226SJames Smart 			*txop = BG_OP_IN_CSUM_OUT_CRC;
1386e2a0a9d6SJames Smart 			break;
1387e2a0a9d6SJames Smart 
1388e2a0a9d6SJames Smart 		case SCSI_PROT_NORMAL:
1389e2a0a9d6SJames Smart 		default:
1390372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
13917c56b9fdSJames Smart 				"9063 BLKGRD: Bad op/guard:%d/IP combination\n",
13927c56b9fdSJames Smart 					scsi_get_prot_op(sc));
13936c8eea54SJames Smart 			ret = 1;
1394e2a0a9d6SJames Smart 			break;
1395e2a0a9d6SJames Smart 
1396e2a0a9d6SJames Smart 		}
13977c56b9fdSJames Smart 	} else {
1398e2a0a9d6SJames Smart 		switch (scsi_get_prot_op(sc)) {
1399e2a0a9d6SJames Smart 		case SCSI_PROT_READ_STRIP:
1400e2a0a9d6SJames Smart 		case SCSI_PROT_WRITE_INSERT:
14016c8eea54SJames Smart 			*rxop = BG_OP_IN_CRC_OUT_NODIF;
14024ac9b226SJames Smart 			*txop = BG_OP_IN_NODIF_OUT_CRC;
1403e2a0a9d6SJames Smart 			break;
1404e2a0a9d6SJames Smart 
1405e2a0a9d6SJames Smart 		case SCSI_PROT_READ_PASS:
1406e2a0a9d6SJames Smart 		case SCSI_PROT_WRITE_PASS:
14076c8eea54SJames Smart 			*rxop = BG_OP_IN_CRC_OUT_CRC;
14084ac9b226SJames Smart 			*txop = BG_OP_IN_CRC_OUT_CRC;
1409e2a0a9d6SJames Smart 			break;
1410e2a0a9d6SJames Smart 
1411e2a0a9d6SJames Smart 		case SCSI_PROT_READ_INSERT:
1412e2a0a9d6SJames Smart 		case SCSI_PROT_WRITE_STRIP:
14137c56b9fdSJames Smart 			*rxop = BG_OP_IN_NODIF_OUT_CRC;
14144ac9b226SJames Smart 			*txop = BG_OP_IN_CRC_OUT_NODIF;
14157c56b9fdSJames Smart 			break;
14167c56b9fdSJames Smart 
1417e2a0a9d6SJames Smart 		case SCSI_PROT_NORMAL:
1418e2a0a9d6SJames Smart 		default:
1419372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
14207c56b9fdSJames Smart 				"9075 BLKGRD: Bad op/guard:%d/CRC combination\n",
14217c56b9fdSJames Smart 					scsi_get_prot_op(sc));
14226c8eea54SJames Smart 			ret = 1;
1423e2a0a9d6SJames Smart 			break;
1424e2a0a9d6SJames Smart 		}
1425e2a0a9d6SJames Smart 	}
1426e2a0a9d6SJames Smart 
14276c8eea54SJames Smart 	return ret;
1428e2a0a9d6SJames Smart }
1429e2a0a9d6SJames Smart 
1430acd6859bSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1431acd6859bSJames Smart /**
1432acd6859bSJames Smart  * lpfc_bg_err_opcodes - reDetermine the BlockGuard opcodes to be used with
1433acd6859bSJames Smart  * the specified SCSI command in order to force a guard tag error.
1434acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
1435acd6859bSJames Smart  * @sc: The SCSI command to examine
1436eceee00eSLee Jones  * @txop: (out) BlockGuard operation for transmitted data
1437eceee00eSLee Jones  * @rxop: (out) BlockGuard operation for received data
1438acd6859bSJames Smart  *
1439acd6859bSJames Smart  * Returns: zero on success; non-zero if tx and/or rx op cannot be determined
1440acd6859bSJames Smart  *
1441acd6859bSJames Smart  **/
1442acd6859bSJames Smart static int
lpfc_bg_err_opcodes(struct lpfc_hba * phba,struct scsi_cmnd * sc,uint8_t * txop,uint8_t * rxop)1443acd6859bSJames Smart lpfc_bg_err_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
1444acd6859bSJames Smart 		uint8_t *txop, uint8_t *rxop)
1445acd6859bSJames Smart {
1446acd6859bSJames Smart 
1447125c12f7SMartin K. Petersen 	if (sc->prot_flags & SCSI_PROT_IP_CHECKSUM) {
1448acd6859bSJames Smart 		switch (scsi_get_prot_op(sc)) {
1449acd6859bSJames Smart 		case SCSI_PROT_READ_INSERT:
1450acd6859bSJames Smart 		case SCSI_PROT_WRITE_STRIP:
1451acd6859bSJames Smart 			*rxop = BG_OP_IN_NODIF_OUT_CRC;
14524ac9b226SJames Smart 			*txop = BG_OP_IN_CRC_OUT_NODIF;
1453acd6859bSJames Smart 			break;
1454acd6859bSJames Smart 
1455acd6859bSJames Smart 		case SCSI_PROT_READ_STRIP:
1456acd6859bSJames Smart 		case SCSI_PROT_WRITE_INSERT:
1457acd6859bSJames Smart 			*rxop = BG_OP_IN_CSUM_OUT_NODIF;
14584ac9b226SJames Smart 			*txop = BG_OP_IN_NODIF_OUT_CSUM;
1459acd6859bSJames Smart 			break;
1460acd6859bSJames Smart 
1461acd6859bSJames Smart 		case SCSI_PROT_READ_PASS:
1462acd6859bSJames Smart 		case SCSI_PROT_WRITE_PASS:
14634ac9b226SJames Smart 			*rxop = BG_OP_IN_CSUM_OUT_CRC;
14649a6b09c0SJames Smart 			*txop = BG_OP_IN_CRC_OUT_CSUM;
1465acd6859bSJames Smart 			break;
1466acd6859bSJames Smart 
1467acd6859bSJames Smart 		case SCSI_PROT_NORMAL:
1468acd6859bSJames Smart 		default:
1469acd6859bSJames Smart 			break;
1470acd6859bSJames Smart 
1471acd6859bSJames Smart 		}
1472acd6859bSJames Smart 	} else {
1473acd6859bSJames Smart 		switch (scsi_get_prot_op(sc)) {
1474acd6859bSJames Smart 		case SCSI_PROT_READ_STRIP:
1475acd6859bSJames Smart 		case SCSI_PROT_WRITE_INSERT:
1476acd6859bSJames Smart 			*rxop = BG_OP_IN_CSUM_OUT_NODIF;
14774ac9b226SJames Smart 			*txop = BG_OP_IN_NODIF_OUT_CSUM;
1478acd6859bSJames Smart 			break;
1479acd6859bSJames Smart 
1480acd6859bSJames Smart 		case SCSI_PROT_READ_PASS:
1481acd6859bSJames Smart 		case SCSI_PROT_WRITE_PASS:
14824ac9b226SJames Smart 			*rxop = BG_OP_IN_CSUM_OUT_CSUM;
14839a6b09c0SJames Smart 			*txop = BG_OP_IN_CSUM_OUT_CSUM;
1484acd6859bSJames Smart 			break;
1485acd6859bSJames Smart 
1486acd6859bSJames Smart 		case SCSI_PROT_READ_INSERT:
1487acd6859bSJames Smart 		case SCSI_PROT_WRITE_STRIP:
1488acd6859bSJames Smart 			*rxop = BG_OP_IN_NODIF_OUT_CSUM;
14894ac9b226SJames Smart 			*txop = BG_OP_IN_CSUM_OUT_NODIF;
1490acd6859bSJames Smart 			break;
1491acd6859bSJames Smart 
1492acd6859bSJames Smart 		case SCSI_PROT_NORMAL:
1493acd6859bSJames Smart 		default:
1494acd6859bSJames Smart 			break;
1495acd6859bSJames Smart 		}
1496acd6859bSJames Smart 	}
1497acd6859bSJames Smart 
14985d1e1510SChi Minghao 	return 0;
1499acd6859bSJames Smart }
1500acd6859bSJames Smart #endif
1501acd6859bSJames Smart 
1502acd6859bSJames Smart /**
1503acd6859bSJames Smart  * lpfc_bg_setup_bpl - Setup BlockGuard BPL with no protection data
1504acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
1505acd6859bSJames Smart  * @sc: pointer to scsi command we're working on
1506acd6859bSJames Smart  * @bpl: pointer to buffer list for protection groups
1507eceee00eSLee Jones  * @datasegcnt: number of segments of data that have been dma mapped
1508acd6859bSJames Smart  *
1509acd6859bSJames Smart  * This function sets up BPL buffer list for protection groups of
1510e2a0a9d6SJames Smart  * type LPFC_PG_TYPE_NO_DIF
1511e2a0a9d6SJames Smart  *
1512e2a0a9d6SJames Smart  * This is usually used when the HBA is instructed to generate
1513e2a0a9d6SJames Smart  * DIFs and insert them into data stream (or strip DIF from
1514e2a0a9d6SJames Smart  * incoming data stream)
1515e2a0a9d6SJames Smart  *
1516e2a0a9d6SJames Smart  * The buffer list consists of just one protection group described
1517e2a0a9d6SJames Smart  * below:
1518e2a0a9d6SJames Smart  *                                +-------------------------+
15196c8eea54SJames Smart  *   start of prot group  -->     |          PDE_5          |
15206c8eea54SJames Smart  *                                +-------------------------+
15216c8eea54SJames Smart  *                                |          PDE_6          |
1522e2a0a9d6SJames Smart  *                                +-------------------------+
1523e2a0a9d6SJames Smart  *                                |         Data BDE        |
1524e2a0a9d6SJames Smart  *                                +-------------------------+
1525e2a0a9d6SJames Smart  *                                |more Data BDE's ... (opt)|
1526e2a0a9d6SJames Smart  *                                +-------------------------+
1527e2a0a9d6SJames Smart  *
1528e2a0a9d6SJames Smart  *
1529e2a0a9d6SJames Smart  * Note: Data s/g buffers have been dma mapped
1530acd6859bSJames Smart  *
1531acd6859bSJames Smart  * Returns the number of BDEs added to the BPL.
1532acd6859bSJames Smart  **/
1533e2a0a9d6SJames Smart static int
lpfc_bg_setup_bpl(struct lpfc_hba * phba,struct scsi_cmnd * sc,struct ulp_bde64 * bpl,int datasegcnt)1534e2a0a9d6SJames Smart lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
1535e2a0a9d6SJames Smart 		struct ulp_bde64 *bpl, int datasegcnt)
1536e2a0a9d6SJames Smart {
1537e2a0a9d6SJames Smart 	struct scatterlist *sgde = NULL; /* s/g data entry */
15386c8eea54SJames Smart 	struct lpfc_pde5 *pde5 = NULL;
15396c8eea54SJames Smart 	struct lpfc_pde6 *pde6 = NULL;
1540e2a0a9d6SJames Smart 	dma_addr_t physaddr;
15416c8eea54SJames Smart 	int i = 0, num_bde = 0, status;
1542e2a0a9d6SJames Smart 	int datadir = sc->sc_data_direction;
15430829a19aSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1544acd6859bSJames Smart 	uint32_t rc;
15450829a19aSJames Smart #endif
1546acd6859bSJames Smart 	uint32_t checking = 1;
1547e2a0a9d6SJames Smart 	uint32_t reftag;
15486c8eea54SJames Smart 	uint8_t txop, rxop;
1549e2a0a9d6SJames Smart 
15506c8eea54SJames Smart 	status  = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
15516c8eea54SJames Smart 	if (status)
1552e2a0a9d6SJames Smart 		goto out;
1553e2a0a9d6SJames Smart 
15546c8eea54SJames Smart 	/* extract some info from the scsi command for pde*/
1555125c12f7SMartin K. Petersen 	reftag = scsi_prot_ref_tag(sc);
1556e2a0a9d6SJames Smart 
1557f9bb2da1SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
15584ac9b226SJames Smart 	rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
1559acd6859bSJames Smart 	if (rc) {
15609a6b09c0SJames Smart 		if (rc & BG_ERR_SWAP)
1561acd6859bSJames Smart 			lpfc_bg_err_opcodes(phba, sc, &txop, &rxop);
15629a6b09c0SJames Smart 		if (rc & BG_ERR_CHECK)
1563acd6859bSJames Smart 			checking = 0;
1564acd6859bSJames Smart 	}
1565f9bb2da1SJames Smart #endif
1566f9bb2da1SJames Smart 
15676c8eea54SJames Smart 	/* setup PDE5 with what we have */
15686c8eea54SJames Smart 	pde5 = (struct lpfc_pde5 *) bpl;
15696c8eea54SJames Smart 	memset(pde5, 0, sizeof(struct lpfc_pde5));
15706c8eea54SJames Smart 	bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR);
1571e2a0a9d6SJames Smart 
1572bc73905aSJames Smart 	/* Endianness conversion if necessary for PDE5 */
1573589a52d6SJames Smart 	pde5->word0 = cpu_to_le32(pde5->word0);
15747c56b9fdSJames Smart 	pde5->reftag = cpu_to_le32(reftag);
1575589a52d6SJames Smart 
15766c8eea54SJames Smart 	/* advance bpl and increment bde count */
15776c8eea54SJames Smart 	num_bde++;
15786c8eea54SJames Smart 	bpl++;
15796c8eea54SJames Smart 	pde6 = (struct lpfc_pde6 *) bpl;
15806c8eea54SJames Smart 
15816c8eea54SJames Smart 	/* setup PDE6 with the rest of the info */
15826c8eea54SJames Smart 	memset(pde6, 0, sizeof(struct lpfc_pde6));
15836c8eea54SJames Smart 	bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR);
15846c8eea54SJames Smart 	bf_set(pde6_optx, pde6, txop);
15856c8eea54SJames Smart 	bf_set(pde6_oprx, pde6, rxop);
1586a6887e28SJames Smart 
1587a6887e28SJames Smart 	/*
1588a6887e28SJames Smart 	 * We only need to check the data on READs, for WRITEs
1589a6887e28SJames Smart 	 * protection data is automatically generated, not checked.
1590a6887e28SJames Smart 	 */
15916c8eea54SJames Smart 	if (datadir == DMA_FROM_DEVICE) {
1592125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
1593acd6859bSJames Smart 			bf_set(pde6_ce, pde6, checking);
1594a6887e28SJames Smart 		else
1595a6887e28SJames Smart 			bf_set(pde6_ce, pde6, 0);
1596a6887e28SJames Smart 
1597125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_REF_CHECK)
1598acd6859bSJames Smart 			bf_set(pde6_re, pde6, checking);
1599a6887e28SJames Smart 		else
1600a6887e28SJames Smart 			bf_set(pde6_re, pde6, 0);
16016c8eea54SJames Smart 	}
16026c8eea54SJames Smart 	bf_set(pde6_ai, pde6, 1);
16037c56b9fdSJames Smart 	bf_set(pde6_ae, pde6, 0);
16047c56b9fdSJames Smart 	bf_set(pde6_apptagval, pde6, 0);
16056c8eea54SJames Smart 
1606bc73905aSJames Smart 	/* Endianness conversion if necessary for PDE6 */
1607589a52d6SJames Smart 	pde6->word0 = cpu_to_le32(pde6->word0);
1608589a52d6SJames Smart 	pde6->word1 = cpu_to_le32(pde6->word1);
1609589a52d6SJames Smart 	pde6->word2 = cpu_to_le32(pde6->word2);
1610589a52d6SJames Smart 
16116c8eea54SJames Smart 	/* advance bpl and increment bde count */
1612e2a0a9d6SJames Smart 	num_bde++;
1613e2a0a9d6SJames Smart 	bpl++;
1614e2a0a9d6SJames Smart 
1615e2a0a9d6SJames Smart 	/* assumption: caller has already run dma_map_sg on command data */
1616e2a0a9d6SJames Smart 	scsi_for_each_sg(sc, sgde, datasegcnt, i) {
1617e2a0a9d6SJames Smart 		physaddr = sg_dma_address(sgde);
1618e2a0a9d6SJames Smart 		bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
1619e2a0a9d6SJames Smart 		bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
1620e2a0a9d6SJames Smart 		bpl->tus.f.bdeSize = sg_dma_len(sgde);
1621e2a0a9d6SJames Smart 		if (datadir == DMA_TO_DEVICE)
1622e2a0a9d6SJames Smart 			bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
1623e2a0a9d6SJames Smart 		else
1624e2a0a9d6SJames Smart 			bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
1625e2a0a9d6SJames Smart 		bpl->tus.w = le32_to_cpu(bpl->tus.w);
1626e2a0a9d6SJames Smart 		bpl++;
1627e2a0a9d6SJames Smart 		num_bde++;
1628e2a0a9d6SJames Smart 	}
1629e2a0a9d6SJames Smart 
1630e2a0a9d6SJames Smart out:
1631e2a0a9d6SJames Smart 	return num_bde;
1632e2a0a9d6SJames Smart }
1633e2a0a9d6SJames Smart 
1634acd6859bSJames Smart /**
1635acd6859bSJames Smart  * lpfc_bg_setup_bpl_prot - Setup BlockGuard BPL with protection data
1636acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
1637acd6859bSJames Smart  * @sc: pointer to scsi command we're working on
1638acd6859bSJames Smart  * @bpl: pointer to buffer list for protection groups
1639acd6859bSJames Smart  * @datacnt: number of segments of data that have been dma mapped
1640acd6859bSJames Smart  * @protcnt: number of segment of protection data that have been dma mapped
1641acd6859bSJames Smart  *
1642acd6859bSJames Smart  * This function sets up BPL buffer list for protection groups of
1643acd6859bSJames Smart  * type LPFC_PG_TYPE_DIF
1644e2a0a9d6SJames Smart  *
1645e2a0a9d6SJames Smart  * This is usually used when DIFs are in their own buffers,
1646e2a0a9d6SJames Smart  * separate from the data. The HBA can then by instructed
1647e2a0a9d6SJames Smart  * to place the DIFs in the outgoing stream.  For read operations,
1648e2a0a9d6SJames Smart  * The HBA could extract the DIFs and place it in DIF buffers.
1649e2a0a9d6SJames Smart  *
1650e2a0a9d6SJames Smart  * The buffer list for this type consists of one or more of the
1651e2a0a9d6SJames Smart  * protection groups described below:
1652e2a0a9d6SJames Smart  *                                    +-------------------------+
16536c8eea54SJames Smart  *   start of first prot group  -->   |          PDE_5          |
1654e2a0a9d6SJames Smart  *                                    +-------------------------+
16556c8eea54SJames Smart  *                                    |          PDE_6          |
16566c8eea54SJames Smart  *                                    +-------------------------+
16576c8eea54SJames Smart  *                                    |      PDE_7 (Prot BDE)   |
1658e2a0a9d6SJames Smart  *                                    +-------------------------+
1659e2a0a9d6SJames Smart  *                                    |        Data BDE         |
1660e2a0a9d6SJames Smart  *                                    +-------------------------+
1661e2a0a9d6SJames Smart  *                                    |more Data BDE's ... (opt)|
1662e2a0a9d6SJames Smart  *                                    +-------------------------+
16636c8eea54SJames Smart  *   start of new  prot group  -->    |          PDE_5          |
1664e2a0a9d6SJames Smart  *                                    +-------------------------+
1665e2a0a9d6SJames Smart  *                                    |          ...            |
1666e2a0a9d6SJames Smart  *                                    +-------------------------+
1667e2a0a9d6SJames Smart  *
1668e2a0a9d6SJames Smart  * Note: It is assumed that both data and protection s/g buffers have been
1669e2a0a9d6SJames Smart  *       mapped for DMA
1670acd6859bSJames Smart  *
1671acd6859bSJames Smart  * Returns the number of BDEs added to the BPL.
1672acd6859bSJames Smart  **/
1673e2a0a9d6SJames Smart static int
lpfc_bg_setup_bpl_prot(struct lpfc_hba * phba,struct scsi_cmnd * sc,struct ulp_bde64 * bpl,int datacnt,int protcnt)1674e2a0a9d6SJames Smart lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
1675e2a0a9d6SJames Smart 		struct ulp_bde64 *bpl, int datacnt, int protcnt)
1676e2a0a9d6SJames Smart {
1677e2a0a9d6SJames Smart 	struct scatterlist *sgde = NULL; /* s/g data entry */
1678e2a0a9d6SJames Smart 	struct scatterlist *sgpe = NULL; /* s/g prot entry */
16796c8eea54SJames Smart 	struct lpfc_pde5 *pde5 = NULL;
16806c8eea54SJames Smart 	struct lpfc_pde6 *pde6 = NULL;
16817f86059aSJames Smart 	struct lpfc_pde7 *pde7 = NULL;
1682e2a0a9d6SJames Smart 	dma_addr_t dataphysaddr, protphysaddr;
16837ab07683SJustin Tee 	unsigned short curr_prot = 0;
16847f86059aSJames Smart 	unsigned int split_offset;
16857f86059aSJames Smart 	unsigned int protgroup_len, protgroup_offset = 0, protgroup_remainder;
1686e2a0a9d6SJames Smart 	unsigned int protgrp_blks, protgrp_bytes;
1687e2a0a9d6SJames Smart 	unsigned int remainder, subtotal;
16886c8eea54SJames Smart 	int status;
1689e2a0a9d6SJames Smart 	int datadir = sc->sc_data_direction;
1690e2a0a9d6SJames Smart 	unsigned char pgdone = 0, alldone = 0;
1691e2a0a9d6SJames Smart 	unsigned blksize;
16920829a19aSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1693acd6859bSJames Smart 	uint32_t rc;
16940829a19aSJames Smart #endif
1695acd6859bSJames Smart 	uint32_t checking = 1;
1696e2a0a9d6SJames Smart 	uint32_t reftag;
16976c8eea54SJames Smart 	uint8_t txop, rxop;
1698e2a0a9d6SJames Smart 	int num_bde = 0;
1699e2a0a9d6SJames Smart 
1700e2a0a9d6SJames Smart 	sgpe = scsi_prot_sglist(sc);
1701e2a0a9d6SJames Smart 	sgde = scsi_sglist(sc);
1702e2a0a9d6SJames Smart 
1703e2a0a9d6SJames Smart 	if (!sgpe || !sgde) {
1704372c187bSDick Kennedy 		lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
170532350664SJames Smart 				"9020 Invalid s/g entry: data=x%px prot=x%px\n",
1706e2a0a9d6SJames Smart 				sgpe, sgde);
1707e2a0a9d6SJames Smart 		return 0;
1708e2a0a9d6SJames Smart 	}
1709e2a0a9d6SJames Smart 
17106c8eea54SJames Smart 	status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
17116c8eea54SJames Smart 	if (status)
1712e2a0a9d6SJames Smart 		goto out;
1713e2a0a9d6SJames Smart 
17146c8eea54SJames Smart 	/* extract some info from the scsi command */
1715125c12f7SMartin K. Petersen 	blksize = scsi_prot_interval(sc);
1716125c12f7SMartin K. Petersen 	reftag = scsi_prot_ref_tag(sc);
1717e2a0a9d6SJames Smart 
1718f9bb2da1SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
17194ac9b226SJames Smart 	rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
1720acd6859bSJames Smart 	if (rc) {
17219a6b09c0SJames Smart 		if (rc & BG_ERR_SWAP)
1722acd6859bSJames Smart 			lpfc_bg_err_opcodes(phba, sc, &txop, &rxop);
17239a6b09c0SJames Smart 		if (rc & BG_ERR_CHECK)
1724acd6859bSJames Smart 			checking = 0;
1725acd6859bSJames Smart 	}
1726f9bb2da1SJames Smart #endif
1727f9bb2da1SJames Smart 
1728e2a0a9d6SJames Smart 	split_offset = 0;
1729e2a0a9d6SJames Smart 	do {
173096f7077fSJames Smart 		/* Check to see if we ran out of space */
173196f7077fSJames Smart 		if (num_bde >= (phba->cfg_total_seg_cnt - 2))
173296f7077fSJames Smart 			return num_bde + 3;
173396f7077fSJames Smart 
17346c8eea54SJames Smart 		/* setup PDE5 with what we have */
17356c8eea54SJames Smart 		pde5 = (struct lpfc_pde5 *) bpl;
17366c8eea54SJames Smart 		memset(pde5, 0, sizeof(struct lpfc_pde5));
17376c8eea54SJames Smart 		bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR);
1738e2a0a9d6SJames Smart 
1739bc73905aSJames Smart 		/* Endianness conversion if necessary for PDE5 */
1740589a52d6SJames Smart 		pde5->word0 = cpu_to_le32(pde5->word0);
17417c56b9fdSJames Smart 		pde5->reftag = cpu_to_le32(reftag);
1742589a52d6SJames Smart 
17436c8eea54SJames Smart 		/* advance bpl and increment bde count */
17446c8eea54SJames Smart 		num_bde++;
17456c8eea54SJames Smart 		bpl++;
17466c8eea54SJames Smart 		pde6 = (struct lpfc_pde6 *) bpl;
1747e2a0a9d6SJames Smart 
17486c8eea54SJames Smart 		/* setup PDE6 with the rest of the info */
17496c8eea54SJames Smart 		memset(pde6, 0, sizeof(struct lpfc_pde6));
17506c8eea54SJames Smart 		bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR);
17516c8eea54SJames Smart 		bf_set(pde6_optx, pde6, txop);
17526c8eea54SJames Smart 		bf_set(pde6_oprx, pde6, rxop);
1753a6887e28SJames Smart 
1754125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
1755acd6859bSJames Smart 			bf_set(pde6_ce, pde6, checking);
1756a6887e28SJames Smart 		else
1757a6887e28SJames Smart 			bf_set(pde6_ce, pde6, 0);
1758a6887e28SJames Smart 
1759125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_REF_CHECK)
1760acd6859bSJames Smart 			bf_set(pde6_re, pde6, checking);
1761a6887e28SJames Smart 		else
1762a6887e28SJames Smart 			bf_set(pde6_re, pde6, 0);
1763a6887e28SJames Smart 
17646c8eea54SJames Smart 		bf_set(pde6_ai, pde6, 1);
17657c56b9fdSJames Smart 		bf_set(pde6_ae, pde6, 0);
17667c56b9fdSJames Smart 		bf_set(pde6_apptagval, pde6, 0);
17676c8eea54SJames Smart 
1768bc73905aSJames Smart 		/* Endianness conversion if necessary for PDE6 */
1769589a52d6SJames Smart 		pde6->word0 = cpu_to_le32(pde6->word0);
1770589a52d6SJames Smart 		pde6->word1 = cpu_to_le32(pde6->word1);
1771589a52d6SJames Smart 		pde6->word2 = cpu_to_le32(pde6->word2);
1772589a52d6SJames Smart 
17736c8eea54SJames Smart 		/* advance bpl and increment bde count */
1774e2a0a9d6SJames Smart 		num_bde++;
1775e2a0a9d6SJames Smart 		bpl++;
1776e2a0a9d6SJames Smart 
1777e2a0a9d6SJames Smart 		/* setup the first BDE that points to protection buffer */
17787f86059aSJames Smart 		protphysaddr = sg_dma_address(sgpe) + protgroup_offset;
17797f86059aSJames Smart 		protgroup_len = sg_dma_len(sgpe) - protgroup_offset;
1780e2a0a9d6SJames Smart 
1781e2a0a9d6SJames Smart 		/* must be integer multiple of the DIF block length */
1782e2a0a9d6SJames Smart 		BUG_ON(protgroup_len % 8);
1783e2a0a9d6SJames Smart 
17847f86059aSJames Smart 		pde7 = (struct lpfc_pde7 *) bpl;
17857f86059aSJames Smart 		memset(pde7, 0, sizeof(struct lpfc_pde7));
17867f86059aSJames Smart 		bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR);
17877f86059aSJames Smart 
17887c56b9fdSJames Smart 		pde7->addrHigh = le32_to_cpu(putPaddrHigh(protphysaddr));
17897c56b9fdSJames Smart 		pde7->addrLow = le32_to_cpu(putPaddrLow(protphysaddr));
17907f86059aSJames Smart 
1791e2a0a9d6SJames Smart 		protgrp_blks = protgroup_len / 8;
1792e2a0a9d6SJames Smart 		protgrp_bytes = protgrp_blks * blksize;
1793e2a0a9d6SJames Smart 
17947f86059aSJames Smart 		/* check if this pde is crossing the 4K boundary; if so split */
17957f86059aSJames Smart 		if ((pde7->addrLow & 0xfff) + protgroup_len > 0x1000) {
17967f86059aSJames Smart 			protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff);
17977f86059aSJames Smart 			protgroup_offset += protgroup_remainder;
17987f86059aSJames Smart 			protgrp_blks = protgroup_remainder / 8;
17997c56b9fdSJames Smart 			protgrp_bytes = protgrp_blks * blksize;
18007f86059aSJames Smart 		} else {
18017f86059aSJames Smart 			protgroup_offset = 0;
1802e2a0a9d6SJames Smart 			curr_prot++;
18037f86059aSJames Smart 		}
18047f86059aSJames Smart 
1805e2a0a9d6SJames Smart 		num_bde++;
1806e2a0a9d6SJames Smart 
1807e2a0a9d6SJames Smart 		/* setup BDE's for data blocks associated with DIF data */
1808e2a0a9d6SJames Smart 		pgdone = 0;
1809e2a0a9d6SJames Smart 		subtotal = 0; /* total bytes processed for current prot grp */
1810e2a0a9d6SJames Smart 		while (!pgdone) {
181196f7077fSJames Smart 			/* Check to see if we ran out of space */
181296f7077fSJames Smart 			if (num_bde >= phba->cfg_total_seg_cnt)
181396f7077fSJames Smart 				return num_bde + 1;
181496f7077fSJames Smart 
1815e2a0a9d6SJames Smart 			if (!sgde) {
1816372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
18176a9c52cfSJames Smart 					"9065 BLKGRD:%s Invalid data segment\n",
1818e2a0a9d6SJames Smart 						__func__);
1819e2a0a9d6SJames Smart 				return 0;
1820e2a0a9d6SJames Smart 			}
1821e2a0a9d6SJames Smart 			bpl++;
1822e2a0a9d6SJames Smart 			dataphysaddr = sg_dma_address(sgde) + split_offset;
1823e2a0a9d6SJames Smart 			bpl->addrLow = le32_to_cpu(putPaddrLow(dataphysaddr));
1824e2a0a9d6SJames Smart 			bpl->addrHigh = le32_to_cpu(putPaddrHigh(dataphysaddr));
1825e2a0a9d6SJames Smart 
1826e2a0a9d6SJames Smart 			remainder = sg_dma_len(sgde) - split_offset;
1827e2a0a9d6SJames Smart 
1828e2a0a9d6SJames Smart 			if ((subtotal + remainder) <= protgrp_bytes) {
1829e2a0a9d6SJames Smart 				/* we can use this whole buffer */
1830e2a0a9d6SJames Smart 				bpl->tus.f.bdeSize = remainder;
1831e2a0a9d6SJames Smart 				split_offset = 0;
1832e2a0a9d6SJames Smart 
1833e2a0a9d6SJames Smart 				if ((subtotal + remainder) == protgrp_bytes)
1834e2a0a9d6SJames Smart 					pgdone = 1;
1835e2a0a9d6SJames Smart 			} else {
1836e2a0a9d6SJames Smart 				/* must split this buffer with next prot grp */
1837e2a0a9d6SJames Smart 				bpl->tus.f.bdeSize = protgrp_bytes - subtotal;
1838e2a0a9d6SJames Smart 				split_offset += bpl->tus.f.bdeSize;
1839e2a0a9d6SJames Smart 			}
1840e2a0a9d6SJames Smart 
1841e2a0a9d6SJames Smart 			subtotal += bpl->tus.f.bdeSize;
1842e2a0a9d6SJames Smart 
1843e2a0a9d6SJames Smart 			if (datadir == DMA_TO_DEVICE)
1844e2a0a9d6SJames Smart 				bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
1845e2a0a9d6SJames Smart 			else
1846e2a0a9d6SJames Smart 				bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
1847e2a0a9d6SJames Smart 			bpl->tus.w = le32_to_cpu(bpl->tus.w);
1848e2a0a9d6SJames Smart 
1849e2a0a9d6SJames Smart 			num_bde++;
1850e2a0a9d6SJames Smart 
1851e2a0a9d6SJames Smart 			if (split_offset)
1852e2a0a9d6SJames Smart 				break;
1853e2a0a9d6SJames Smart 
1854e2a0a9d6SJames Smart 			/* Move to the next s/g segment if possible */
1855e2a0a9d6SJames Smart 			sgde = sg_next(sgde);
18566c8eea54SJames Smart 
1857e2a0a9d6SJames Smart 		}
1858e2a0a9d6SJames Smart 
18597f86059aSJames Smart 		if (protgroup_offset) {
18607f86059aSJames Smart 			/* update the reference tag */
18617f86059aSJames Smart 			reftag += protgrp_blks;
18627f86059aSJames Smart 			bpl++;
18637f86059aSJames Smart 			continue;
18647f86059aSJames Smart 		}
18657f86059aSJames Smart 
1866e2a0a9d6SJames Smart 		/* are we done ? */
1867e2a0a9d6SJames Smart 		if (curr_prot == protcnt) {
1868e2a0a9d6SJames Smart 			alldone = 1;
1869e2a0a9d6SJames Smart 		} else if (curr_prot < protcnt) {
1870e2a0a9d6SJames Smart 			/* advance to next prot buffer */
1871e2a0a9d6SJames Smart 			sgpe = sg_next(sgpe);
1872e2a0a9d6SJames Smart 			bpl++;
1873e2a0a9d6SJames Smart 
1874e2a0a9d6SJames Smart 			/* update the reference tag */
1875e2a0a9d6SJames Smart 			reftag += protgrp_blks;
1876e2a0a9d6SJames Smart 		} else {
1877e2a0a9d6SJames Smart 			/* if we're here, we have a bug */
1878372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
18796a9c52cfSJames Smart 					"9054 BLKGRD: bug in %s\n", __func__);
1880e2a0a9d6SJames Smart 		}
1881e2a0a9d6SJames Smart 
1882e2a0a9d6SJames Smart 	} while (!alldone);
1883e2a0a9d6SJames Smart out:
1884e2a0a9d6SJames Smart 
1885e2a0a9d6SJames Smart 	return num_bde;
1886e2a0a9d6SJames Smart }
18877f86059aSJames Smart 
1888acd6859bSJames Smart /**
1889acd6859bSJames Smart  * lpfc_bg_setup_sgl - Setup BlockGuard SGL with no protection data
1890acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
1891acd6859bSJames Smart  * @sc: pointer to scsi command we're working on
1892acd6859bSJames Smart  * @sgl: pointer to buffer list for protection groups
1893eceee00eSLee Jones  * @datasegcnt: number of segments of data that have been dma mapped
1894eceee00eSLee Jones  * @lpfc_cmd: lpfc scsi command object pointer.
1895acd6859bSJames Smart  *
1896acd6859bSJames Smart  * This function sets up SGL buffer list for protection groups of
1897acd6859bSJames Smart  * type LPFC_PG_TYPE_NO_DIF
1898acd6859bSJames Smart  *
1899acd6859bSJames Smart  * This is usually used when the HBA is instructed to generate
1900acd6859bSJames Smart  * DIFs and insert them into data stream (or strip DIF from
1901acd6859bSJames Smart  * incoming data stream)
1902acd6859bSJames Smart  *
1903acd6859bSJames Smart  * The buffer list consists of just one protection group described
1904acd6859bSJames Smart  * below:
1905acd6859bSJames Smart  *                                +-------------------------+
1906acd6859bSJames Smart  *   start of prot group  -->     |         DI_SEED         |
1907acd6859bSJames Smart  *                                +-------------------------+
1908acd6859bSJames Smart  *                                |         Data SGE        |
1909acd6859bSJames Smart  *                                +-------------------------+
1910acd6859bSJames Smart  *                                |more Data SGE's ... (opt)|
1911acd6859bSJames Smart  *                                +-------------------------+
1912acd6859bSJames Smart  *
1913acd6859bSJames Smart  *
1914acd6859bSJames Smart  * Note: Data s/g buffers have been dma mapped
1915acd6859bSJames Smart  *
1916acd6859bSJames Smart  * Returns the number of SGEs added to the SGL.
1917acd6859bSJames Smart  **/
1918d6c1b191SHannes Reinecke static uint32_t
lpfc_bg_setup_sgl(struct lpfc_hba * phba,struct scsi_cmnd * sc,struct sli4_sge * sgl,int datasegcnt,struct lpfc_io_buf * lpfc_cmd)1919acd6859bSJames Smart lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
1920d79c9e9dSJames Smart 		struct sli4_sge *sgl, int datasegcnt,
1921d79c9e9dSJames Smart 		struct lpfc_io_buf *lpfc_cmd)
1922acd6859bSJames Smart {
1923acd6859bSJames Smart 	struct scatterlist *sgde = NULL; /* s/g data entry */
1924acd6859bSJames Smart 	struct sli4_sge_diseed *diseed = NULL;
1925acd6859bSJames Smart 	dma_addr_t physaddr;
1926d6c1b191SHannes Reinecke 	int i = 0, status;
1927d6c1b191SHannes Reinecke 	uint32_t reftag, num_sge = 0;
1928acd6859bSJames Smart 	uint8_t txop, rxop;
19290829a19aSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
1930acd6859bSJames Smart 	uint32_t rc;
19310829a19aSJames Smart #endif
1932acd6859bSJames Smart 	uint32_t checking = 1;
1933acd6859bSJames Smart 	uint32_t dma_len;
1934acd6859bSJames Smart 	uint32_t dma_offset = 0;
1935d79c9e9dSJames Smart 	struct sli4_hybrid_sgl *sgl_xtra = NULL;
1936d79c9e9dSJames Smart 	int j;
1937d79c9e9dSJames Smart 	bool lsp_just_set = false;
1938acd6859bSJames Smart 
1939acd6859bSJames Smart 	status  = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
1940acd6859bSJames Smart 	if (status)
1941acd6859bSJames Smart 		goto out;
1942acd6859bSJames Smart 
1943acd6859bSJames Smart 	/* extract some info from the scsi command for pde*/
1944125c12f7SMartin K. Petersen 	reftag = scsi_prot_ref_tag(sc);
1945acd6859bSJames Smart 
1946acd6859bSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
19474ac9b226SJames Smart 	rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
1948acd6859bSJames Smart 	if (rc) {
19499a6b09c0SJames Smart 		if (rc & BG_ERR_SWAP)
1950acd6859bSJames Smart 			lpfc_bg_err_opcodes(phba, sc, &txop, &rxop);
19519a6b09c0SJames Smart 		if (rc & BG_ERR_CHECK)
1952acd6859bSJames Smart 			checking = 0;
1953acd6859bSJames Smart 	}
1954acd6859bSJames Smart #endif
1955acd6859bSJames Smart 
1956acd6859bSJames Smart 	/* setup DISEED with what we have */
1957acd6859bSJames Smart 	diseed = (struct sli4_sge_diseed *) sgl;
1958acd6859bSJames Smart 	memset(diseed, 0, sizeof(struct sli4_sge_diseed));
1959acd6859bSJames Smart 	bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DISEED);
1960acd6859bSJames Smart 
1961acd6859bSJames Smart 	/* Endianness conversion if necessary */
1962acd6859bSJames Smart 	diseed->ref_tag = cpu_to_le32(reftag);
1963acd6859bSJames Smart 	diseed->ref_tag_tran = diseed->ref_tag;
1964acd6859bSJames Smart 
1965a6887e28SJames Smart 	/*
1966a6887e28SJames Smart 	 * We only need to check the data on READs, for WRITEs
1967a6887e28SJames Smart 	 * protection data is automatically generated, not checked.
1968a6887e28SJames Smart 	 */
1969a6887e28SJames Smart 	if (sc->sc_data_direction == DMA_FROM_DEVICE) {
1970125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
1971a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
1972a6887e28SJames Smart 		else
1973a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
1974a6887e28SJames Smart 
1975125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_REF_CHECK)
1976a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
1977a6887e28SJames Smart 		else
1978a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
1979a6887e28SJames Smart 	}
1980a6887e28SJames Smart 
1981acd6859bSJames Smart 	/* setup DISEED with the rest of the info */
1982acd6859bSJames Smart 	bf_set(lpfc_sli4_sge_dif_optx, diseed, txop);
1983acd6859bSJames Smart 	bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop);
1984a6887e28SJames Smart 
1985acd6859bSJames Smart 	bf_set(lpfc_sli4_sge_dif_ai, diseed, 1);
1986acd6859bSJames Smart 	bf_set(lpfc_sli4_sge_dif_me, diseed, 0);
1987acd6859bSJames Smart 
1988acd6859bSJames Smart 	/* Endianness conversion if necessary for DISEED */
1989acd6859bSJames Smart 	diseed->word2 = cpu_to_le32(diseed->word2);
1990acd6859bSJames Smart 	diseed->word3 = cpu_to_le32(diseed->word3);
1991acd6859bSJames Smart 
1992acd6859bSJames Smart 	/* advance bpl and increment sge count */
1993acd6859bSJames Smart 	num_sge++;
1994acd6859bSJames Smart 	sgl++;
1995acd6859bSJames Smart 
1996acd6859bSJames Smart 	/* assumption: caller has already run dma_map_sg on command data */
1997d79c9e9dSJames Smart 	sgde = scsi_sglist(sc);
1998d79c9e9dSJames Smart 	j = 3;
1999d79c9e9dSJames Smart 	for (i = 0; i < datasegcnt; i++) {
2000d79c9e9dSJames Smart 		/* clear it */
2001d79c9e9dSJames Smart 		sgl->word2 = 0;
2002d79c9e9dSJames Smart 
2003d79c9e9dSJames Smart 		/* do we need to expand the segment */
2004d79c9e9dSJames Smart 		if (!lsp_just_set && !((j + 1) % phba->border_sge_num) &&
2005d79c9e9dSJames Smart 		    ((datasegcnt - 1) != i)) {
2006d79c9e9dSJames Smart 			/* set LSP type */
2007d79c9e9dSJames Smart 			bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_LSP);
2008d79c9e9dSJames Smart 
2009d79c9e9dSJames Smart 			sgl_xtra = lpfc_get_sgl_per_hdwq(phba, lpfc_cmd);
2010d79c9e9dSJames Smart 
2011d79c9e9dSJames Smart 			if (unlikely(!sgl_xtra)) {
2012d79c9e9dSJames Smart 				lpfc_cmd->seg_cnt = 0;
2013d79c9e9dSJames Smart 				return 0;
2014d79c9e9dSJames Smart 			}
2015d79c9e9dSJames Smart 			sgl->addr_lo = cpu_to_le32(putPaddrLow(
2016d79c9e9dSJames Smart 						sgl_xtra->dma_phys_sgl));
2017d79c9e9dSJames Smart 			sgl->addr_hi = cpu_to_le32(putPaddrHigh(
2018d79c9e9dSJames Smart 						sgl_xtra->dma_phys_sgl));
2019d79c9e9dSJames Smart 
2020d79c9e9dSJames Smart 		} else {
2021d79c9e9dSJames Smart 			bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
2022d79c9e9dSJames Smart 		}
2023d79c9e9dSJames Smart 
2024d79c9e9dSJames Smart 		if (!(bf_get(lpfc_sli4_sge_type, sgl) & LPFC_SGE_TYPE_LSP)) {
2025d79c9e9dSJames Smart 			if ((datasegcnt - 1) == i)
2026d79c9e9dSJames Smart 				bf_set(lpfc_sli4_sge_last, sgl, 1);
2027acd6859bSJames Smart 			physaddr = sg_dma_address(sgde);
2028acd6859bSJames Smart 			dma_len = sg_dma_len(sgde);
2029acd6859bSJames Smart 			sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr));
2030acd6859bSJames Smart 			sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr));
2031acd6859bSJames Smart 
2032d79c9e9dSJames Smart 			bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
2033d79c9e9dSJames Smart 			sgl->word2 = cpu_to_le32(sgl->word2);
2034acd6859bSJames Smart 			sgl->sge_len = cpu_to_le32(dma_len);
2035d79c9e9dSJames Smart 
2036acd6859bSJames Smart 			dma_offset += dma_len;
2037d79c9e9dSJames Smart 			sgde = sg_next(sgde);
2038acd6859bSJames Smart 
2039acd6859bSJames Smart 			sgl++;
2040acd6859bSJames Smart 			num_sge++;
2041d79c9e9dSJames Smart 			lsp_just_set = false;
2042d79c9e9dSJames Smart 
2043d79c9e9dSJames Smart 		} else {
2044d79c9e9dSJames Smart 			sgl->word2 = cpu_to_le32(sgl->word2);
2045d79c9e9dSJames Smart 			sgl->sge_len = cpu_to_le32(phba->cfg_sg_dma_buf_size);
2046d79c9e9dSJames Smart 
2047d79c9e9dSJames Smart 			sgl = (struct sli4_sge *)sgl_xtra->dma_sgl;
2048d79c9e9dSJames Smart 			i = i - 1;
2049d79c9e9dSJames Smart 
2050d79c9e9dSJames Smart 			lsp_just_set = true;
2051d79c9e9dSJames Smart 		}
2052d79c9e9dSJames Smart 
2053d79c9e9dSJames Smart 		j++;
2054d79c9e9dSJames Smart 
2055acd6859bSJames Smart 	}
2056acd6859bSJames Smart 
2057acd6859bSJames Smart out:
2058acd6859bSJames Smart 	return num_sge;
2059acd6859bSJames Smart }
2060acd6859bSJames Smart 
2061acd6859bSJames Smart /**
2062acd6859bSJames Smart  * lpfc_bg_setup_sgl_prot - Setup BlockGuard SGL with protection data
2063acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
2064acd6859bSJames Smart  * @sc: pointer to scsi command we're working on
2065acd6859bSJames Smart  * @sgl: pointer to buffer list for protection groups
2066acd6859bSJames Smart  * @datacnt: number of segments of data that have been dma mapped
2067acd6859bSJames Smart  * @protcnt: number of segment of protection data that have been dma mapped
2068eceee00eSLee Jones  * @lpfc_cmd: lpfc scsi command object pointer.
2069acd6859bSJames Smart  *
2070acd6859bSJames Smart  * This function sets up SGL buffer list for protection groups of
2071acd6859bSJames Smart  * type LPFC_PG_TYPE_DIF
2072acd6859bSJames Smart  *
2073acd6859bSJames Smart  * This is usually used when DIFs are in their own buffers,
2074acd6859bSJames Smart  * separate from the data. The HBA can then by instructed
2075acd6859bSJames Smart  * to place the DIFs in the outgoing stream.  For read operations,
2076acd6859bSJames Smart  * The HBA could extract the DIFs and place it in DIF buffers.
2077acd6859bSJames Smart  *
2078acd6859bSJames Smart  * The buffer list for this type consists of one or more of the
2079acd6859bSJames Smart  * protection groups described below:
2080acd6859bSJames Smart  *                                    +-------------------------+
2081acd6859bSJames Smart  *   start of first prot group  -->   |         DISEED          |
2082acd6859bSJames Smart  *                                    +-------------------------+
2083acd6859bSJames Smart  *                                    |      DIF (Prot SGE)     |
2084acd6859bSJames Smart  *                                    +-------------------------+
2085acd6859bSJames Smart  *                                    |        Data SGE         |
2086acd6859bSJames Smart  *                                    +-------------------------+
2087acd6859bSJames Smart  *                                    |more Data SGE's ... (opt)|
2088acd6859bSJames Smart  *                                    +-------------------------+
2089acd6859bSJames Smart  *   start of new  prot group  -->    |         DISEED          |
2090acd6859bSJames Smart  *                                    +-------------------------+
2091acd6859bSJames Smart  *                                    |          ...            |
2092acd6859bSJames Smart  *                                    +-------------------------+
2093acd6859bSJames Smart  *
2094acd6859bSJames Smart  * Note: It is assumed that both data and protection s/g buffers have been
2095acd6859bSJames Smart  *       mapped for DMA
2096acd6859bSJames Smart  *
2097acd6859bSJames Smart  * Returns the number of SGEs added to the SGL.
2098acd6859bSJames Smart  **/
2099d6c1b191SHannes Reinecke static uint32_t
lpfc_bg_setup_sgl_prot(struct lpfc_hba * phba,struct scsi_cmnd * sc,struct sli4_sge * sgl,int datacnt,int protcnt,struct lpfc_io_buf * lpfc_cmd)2100acd6859bSJames Smart lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
2101d79c9e9dSJames Smart 		struct sli4_sge *sgl, int datacnt, int protcnt,
2102d79c9e9dSJames Smart 		struct lpfc_io_buf *lpfc_cmd)
2103acd6859bSJames Smart {
2104acd6859bSJames Smart 	struct scatterlist *sgde = NULL; /* s/g data entry */
2105acd6859bSJames Smart 	struct scatterlist *sgpe = NULL; /* s/g prot entry */
2106acd6859bSJames Smart 	struct sli4_sge_diseed *diseed = NULL;
2107acd6859bSJames Smart 	dma_addr_t dataphysaddr, protphysaddr;
21087ab07683SJustin Tee 	unsigned short curr_prot = 0;
2109acd6859bSJames Smart 	unsigned int split_offset;
2110acd6859bSJames Smart 	unsigned int protgroup_len, protgroup_offset = 0, protgroup_remainder;
2111acd6859bSJames Smart 	unsigned int protgrp_blks, protgrp_bytes;
2112acd6859bSJames Smart 	unsigned int remainder, subtotal;
2113acd6859bSJames Smart 	int status;
2114acd6859bSJames Smart 	unsigned char pgdone = 0, alldone = 0;
2115acd6859bSJames Smart 	unsigned blksize;
2116acd6859bSJames Smart 	uint32_t reftag;
2117acd6859bSJames Smart 	uint8_t txop, rxop;
2118acd6859bSJames Smart 	uint32_t dma_len;
21190829a19aSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
2120acd6859bSJames Smart 	uint32_t rc;
21210829a19aSJames Smart #endif
2122acd6859bSJames Smart 	uint32_t checking = 1;
2123d6c1b191SHannes Reinecke 	uint32_t dma_offset = 0, num_sge = 0;
2124d6c1b191SHannes Reinecke 	int j = 2;
2125d79c9e9dSJames Smart 	struct sli4_hybrid_sgl *sgl_xtra = NULL;
2126acd6859bSJames Smart 
2127acd6859bSJames Smart 	sgpe = scsi_prot_sglist(sc);
2128acd6859bSJames Smart 	sgde = scsi_sglist(sc);
2129acd6859bSJames Smart 
2130acd6859bSJames Smart 	if (!sgpe || !sgde) {
2131372c187bSDick Kennedy 		lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
213232350664SJames Smart 				"9082 Invalid s/g entry: data=x%px prot=x%px\n",
2133acd6859bSJames Smart 				sgpe, sgde);
2134acd6859bSJames Smart 		return 0;
2135acd6859bSJames Smart 	}
2136acd6859bSJames Smart 
2137acd6859bSJames Smart 	status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop);
2138acd6859bSJames Smart 	if (status)
2139acd6859bSJames Smart 		goto out;
2140acd6859bSJames Smart 
2141acd6859bSJames Smart 	/* extract some info from the scsi command */
2142125c12f7SMartin K. Petersen 	blksize = scsi_prot_interval(sc);
2143125c12f7SMartin K. Petersen 	reftag = scsi_prot_ref_tag(sc);
2144acd6859bSJames Smart 
2145acd6859bSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
21464ac9b226SJames Smart 	rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1);
2147acd6859bSJames Smart 	if (rc) {
21489a6b09c0SJames Smart 		if (rc & BG_ERR_SWAP)
2149acd6859bSJames Smart 			lpfc_bg_err_opcodes(phba, sc, &txop, &rxop);
21509a6b09c0SJames Smart 		if (rc & BG_ERR_CHECK)
2151acd6859bSJames Smart 			checking = 0;
2152acd6859bSJames Smart 	}
2153acd6859bSJames Smart #endif
2154acd6859bSJames Smart 
2155acd6859bSJames Smart 	split_offset = 0;
2156acd6859bSJames Smart 	do {
215796f7077fSJames Smart 		/* Check to see if we ran out of space */
2158d79c9e9dSJames Smart 		if ((num_sge >= (phba->cfg_total_seg_cnt - 2)) &&
2159d79c9e9dSJames Smart 		    !(phba->cfg_xpsgl))
216096f7077fSJames Smart 			return num_sge + 3;
216196f7077fSJames Smart 
2162d79c9e9dSJames Smart 		/* DISEED and DIF have to be together */
2163d79c9e9dSJames Smart 		if (!((j + 1) % phba->border_sge_num) ||
2164d79c9e9dSJames Smart 		    !((j + 2) % phba->border_sge_num) ||
2165d79c9e9dSJames Smart 		    !((j + 3) % phba->border_sge_num)) {
2166d79c9e9dSJames Smart 			sgl->word2 = 0;
2167d79c9e9dSJames Smart 
2168d79c9e9dSJames Smart 			/* set LSP type */
2169d79c9e9dSJames Smart 			bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_LSP);
2170d79c9e9dSJames Smart 
2171d79c9e9dSJames Smart 			sgl_xtra = lpfc_get_sgl_per_hdwq(phba, lpfc_cmd);
2172d79c9e9dSJames Smart 
2173d79c9e9dSJames Smart 			if (unlikely(!sgl_xtra)) {
2174d79c9e9dSJames Smart 				goto out;
2175d79c9e9dSJames Smart 			} else {
2176d79c9e9dSJames Smart 				sgl->addr_lo = cpu_to_le32(putPaddrLow(
2177d79c9e9dSJames Smart 						sgl_xtra->dma_phys_sgl));
2178d79c9e9dSJames Smart 				sgl->addr_hi = cpu_to_le32(putPaddrHigh(
2179d79c9e9dSJames Smart 						       sgl_xtra->dma_phys_sgl));
2180d79c9e9dSJames Smart 			}
2181d79c9e9dSJames Smart 
2182d79c9e9dSJames Smart 			sgl->word2 = cpu_to_le32(sgl->word2);
2183d79c9e9dSJames Smart 			sgl->sge_len = cpu_to_le32(phba->cfg_sg_dma_buf_size);
2184d79c9e9dSJames Smart 
2185d79c9e9dSJames Smart 			sgl = (struct sli4_sge *)sgl_xtra->dma_sgl;
2186d79c9e9dSJames Smart 			j = 0;
2187d79c9e9dSJames Smart 		}
2188d79c9e9dSJames Smart 
2189acd6859bSJames Smart 		/* setup DISEED with what we have */
2190acd6859bSJames Smart 		diseed = (struct sli4_sge_diseed *) sgl;
2191acd6859bSJames Smart 		memset(diseed, 0, sizeof(struct sli4_sge_diseed));
2192acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DISEED);
2193acd6859bSJames Smart 
2194acd6859bSJames Smart 		/* Endianness conversion if necessary */
2195acd6859bSJames Smart 		diseed->ref_tag = cpu_to_le32(reftag);
2196acd6859bSJames Smart 		diseed->ref_tag_tran = diseed->ref_tag;
2197acd6859bSJames Smart 
2198125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_GUARD_CHECK) {
2199a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
2200a6887e28SJames Smart 		} else {
2201a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
2202a6887e28SJames Smart 			/*
2203a6887e28SJames Smart 			 * When in this mode, the hardware will replace
2204a6887e28SJames Smart 			 * the guard tag from the host with a
2205a6887e28SJames Smart 			 * newly generated good CRC for the wire.
2206a6887e28SJames Smart 			 * Switch to raw mode here to avoid this
2207a6887e28SJames Smart 			 * behavior. What the host sends gets put on the wire.
2208a6887e28SJames Smart 			 */
2209a6887e28SJames Smart 			if (txop == BG_OP_IN_CRC_OUT_CRC) {
2210a6887e28SJames Smart 				txop = BG_OP_RAW_MODE;
2211a6887e28SJames Smart 				rxop = BG_OP_RAW_MODE;
2212a6887e28SJames Smart 			}
2213a6887e28SJames Smart 		}
2214a6887e28SJames Smart 
2215a6887e28SJames Smart 
2216125c12f7SMartin K. Petersen 		if (sc->prot_flags & SCSI_PROT_REF_CHECK)
2217a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
2218a6887e28SJames Smart 		else
2219a6887e28SJames Smart 			bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
2220a6887e28SJames Smart 
2221acd6859bSJames Smart 		/* setup DISEED with the rest of the info */
2222acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_dif_optx, diseed, txop);
2223acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop);
2224a6887e28SJames Smart 
2225acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_dif_ai, diseed, 1);
2226acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_dif_me, diseed, 0);
2227acd6859bSJames Smart 
2228acd6859bSJames Smart 		/* Endianness conversion if necessary for DISEED */
2229acd6859bSJames Smart 		diseed->word2 = cpu_to_le32(diseed->word2);
2230acd6859bSJames Smart 		diseed->word3 = cpu_to_le32(diseed->word3);
2231acd6859bSJames Smart 
2232acd6859bSJames Smart 		/* advance sgl and increment bde count */
2233acd6859bSJames Smart 		num_sge++;
2234d79c9e9dSJames Smart 
2235acd6859bSJames Smart 		sgl++;
2236d79c9e9dSJames Smart 		j++;
2237acd6859bSJames Smart 
2238acd6859bSJames Smart 		/* setup the first BDE that points to protection buffer */
2239acd6859bSJames Smart 		protphysaddr = sg_dma_address(sgpe) + protgroup_offset;
2240acd6859bSJames Smart 		protgroup_len = sg_dma_len(sgpe) - protgroup_offset;
2241acd6859bSJames Smart 
2242acd6859bSJames Smart 		/* must be integer multiple of the DIF block length */
2243acd6859bSJames Smart 		BUG_ON(protgroup_len % 8);
2244acd6859bSJames Smart 
2245acd6859bSJames Smart 		/* Now setup DIF SGE */
2246acd6859bSJames Smart 		sgl->word2 = 0;
2247acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DIF);
2248acd6859bSJames Smart 		sgl->addr_hi = le32_to_cpu(putPaddrHigh(protphysaddr));
2249acd6859bSJames Smart 		sgl->addr_lo = le32_to_cpu(putPaddrLow(protphysaddr));
2250acd6859bSJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
2251d79c9e9dSJames Smart 		sgl->sge_len = 0;
2252acd6859bSJames Smart 
2253acd6859bSJames Smart 		protgrp_blks = protgroup_len / 8;
2254acd6859bSJames Smart 		protgrp_bytes = protgrp_blks * blksize;
2255acd6859bSJames Smart 
2256acd6859bSJames Smart 		/* check if DIF SGE is crossing the 4K boundary; if so split */
2257acd6859bSJames Smart 		if ((sgl->addr_lo & 0xfff) + protgroup_len > 0x1000) {
2258acd6859bSJames Smart 			protgroup_remainder = 0x1000 - (sgl->addr_lo & 0xfff);
2259acd6859bSJames Smart 			protgroup_offset += protgroup_remainder;
2260acd6859bSJames Smart 			protgrp_blks = protgroup_remainder / 8;
2261acd6859bSJames Smart 			protgrp_bytes = protgrp_blks * blksize;
2262acd6859bSJames Smart 		} else {
2263acd6859bSJames Smart 			protgroup_offset = 0;
2264acd6859bSJames Smart 			curr_prot++;
2265acd6859bSJames Smart 		}
2266acd6859bSJames Smart 
2267acd6859bSJames Smart 		num_sge++;
2268acd6859bSJames Smart 
2269acd6859bSJames Smart 		/* setup SGE's for data blocks associated with DIF data */
2270acd6859bSJames Smart 		pgdone = 0;
2271acd6859bSJames Smart 		subtotal = 0; /* total bytes processed for current prot grp */
2272d79c9e9dSJames Smart 
2273d79c9e9dSJames Smart 		sgl++;
2274d79c9e9dSJames Smart 		j++;
2275d79c9e9dSJames Smart 
2276acd6859bSJames Smart 		while (!pgdone) {
227796f7077fSJames Smart 			/* Check to see if we ran out of space */
2278d79c9e9dSJames Smart 			if ((num_sge >= phba->cfg_total_seg_cnt) &&
2279d79c9e9dSJames Smart 			    !phba->cfg_xpsgl)
228096f7077fSJames Smart 				return num_sge + 1;
228196f7077fSJames Smart 
2282acd6859bSJames Smart 			if (!sgde) {
2283372c187bSDick Kennedy 				lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
2284acd6859bSJames Smart 					"9086 BLKGRD:%s Invalid data segment\n",
2285acd6859bSJames Smart 						__func__);
2286acd6859bSJames Smart 				return 0;
2287acd6859bSJames Smart 			}
2288d79c9e9dSJames Smart 
2289d79c9e9dSJames Smart 			if (!((j + 1) % phba->border_sge_num)) {
2290d79c9e9dSJames Smart 				sgl->word2 = 0;
2291d79c9e9dSJames Smart 
2292d79c9e9dSJames Smart 				/* set LSP type */
2293d79c9e9dSJames Smart 				bf_set(lpfc_sli4_sge_type, sgl,
2294d79c9e9dSJames Smart 				       LPFC_SGE_TYPE_LSP);
2295d79c9e9dSJames Smart 
2296d79c9e9dSJames Smart 				sgl_xtra = lpfc_get_sgl_per_hdwq(phba,
2297d79c9e9dSJames Smart 								 lpfc_cmd);
2298d79c9e9dSJames Smart 
2299d79c9e9dSJames Smart 				if (unlikely(!sgl_xtra)) {
2300d79c9e9dSJames Smart 					goto out;
2301d79c9e9dSJames Smart 				} else {
2302d79c9e9dSJames Smart 					sgl->addr_lo = cpu_to_le32(
2303d79c9e9dSJames Smart 					  putPaddrLow(sgl_xtra->dma_phys_sgl));
2304d79c9e9dSJames Smart 					sgl->addr_hi = cpu_to_le32(
2305d79c9e9dSJames Smart 					  putPaddrHigh(sgl_xtra->dma_phys_sgl));
2306d79c9e9dSJames Smart 				}
2307d79c9e9dSJames Smart 
2308d79c9e9dSJames Smart 				sgl->word2 = cpu_to_le32(sgl->word2);
2309d79c9e9dSJames Smart 				sgl->sge_len = cpu_to_le32(
2310d79c9e9dSJames Smart 						     phba->cfg_sg_dma_buf_size);
2311d79c9e9dSJames Smart 
2312d79c9e9dSJames Smart 				sgl = (struct sli4_sge *)sgl_xtra->dma_sgl;
2313d79c9e9dSJames Smart 			} else {
2314d79c9e9dSJames Smart 				dataphysaddr = sg_dma_address(sgde) +
2315d79c9e9dSJames Smart 								   split_offset;
2316acd6859bSJames Smart 
2317acd6859bSJames Smart 				remainder = sg_dma_len(sgde) - split_offset;
2318acd6859bSJames Smart 
2319acd6859bSJames Smart 				if ((subtotal + remainder) <= protgrp_bytes) {
2320acd6859bSJames Smart 					/* we can use this whole buffer */
2321acd6859bSJames Smart 					dma_len = remainder;
2322acd6859bSJames Smart 					split_offset = 0;
2323acd6859bSJames Smart 
2324d79c9e9dSJames Smart 					if ((subtotal + remainder) ==
2325d79c9e9dSJames Smart 								  protgrp_bytes)
2326acd6859bSJames Smart 						pgdone = 1;
2327acd6859bSJames Smart 				} else {
2328d79c9e9dSJames Smart 					/* must split this buffer with next
2329d79c9e9dSJames Smart 					 * prot grp
2330d79c9e9dSJames Smart 					 */
2331acd6859bSJames Smart 					dma_len = protgrp_bytes - subtotal;
2332acd6859bSJames Smart 					split_offset += dma_len;
2333acd6859bSJames Smart 				}
2334acd6859bSJames Smart 
2335acd6859bSJames Smart 				subtotal += dma_len;
2336acd6859bSJames Smart 
2337d79c9e9dSJames Smart 				sgl->word2 = 0;
2338d79c9e9dSJames Smart 				sgl->addr_lo = cpu_to_le32(putPaddrLow(
2339d79c9e9dSJames Smart 								 dataphysaddr));
2340d79c9e9dSJames Smart 				sgl->addr_hi = cpu_to_le32(putPaddrHigh(
2341d79c9e9dSJames Smart 								 dataphysaddr));
2342acd6859bSJames Smart 				bf_set(lpfc_sli4_sge_last, sgl, 0);
2343acd6859bSJames Smart 				bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
2344d79c9e9dSJames Smart 				bf_set(lpfc_sli4_sge_type, sgl,
2345d79c9e9dSJames Smart 				       LPFC_SGE_TYPE_DATA);
2346acd6859bSJames Smart 
2347acd6859bSJames Smart 				sgl->sge_len = cpu_to_le32(dma_len);
2348acd6859bSJames Smart 				dma_offset += dma_len;
2349acd6859bSJames Smart 
2350acd6859bSJames Smart 				num_sge++;
2351acd6859bSJames Smart 
2352d79c9e9dSJames Smart 				if (split_offset) {
2353d79c9e9dSJames Smart 					sgl++;
2354d79c9e9dSJames Smart 					j++;
2355acd6859bSJames Smart 					break;
2356d79c9e9dSJames Smart 				}
2357acd6859bSJames Smart 
2358acd6859bSJames Smart 				/* Move to the next s/g segment if possible */
2359acd6859bSJames Smart 				sgde = sg_next(sgde);
2360d79c9e9dSJames Smart 
2361d79c9e9dSJames Smart 				sgl++;
2362d79c9e9dSJames Smart 			}
2363d79c9e9dSJames Smart 
2364d79c9e9dSJames Smart 			j++;
2365acd6859bSJames Smart 		}
2366acd6859bSJames Smart 
2367acd6859bSJames Smart 		if (protgroup_offset) {
2368acd6859bSJames Smart 			/* update the reference tag */
2369acd6859bSJames Smart 			reftag += protgrp_blks;
2370acd6859bSJames Smart 			continue;
2371acd6859bSJames Smart 		}
2372acd6859bSJames Smart 
2373acd6859bSJames Smart 		/* are we done ? */
2374acd6859bSJames Smart 		if (curr_prot == protcnt) {
2375d79c9e9dSJames Smart 			/* mark the last SGL */
2376d79c9e9dSJames Smart 			sgl--;
2377acd6859bSJames Smart 			bf_set(lpfc_sli4_sge_last, sgl, 1);
2378acd6859bSJames Smart 			alldone = 1;
2379acd6859bSJames Smart 		} else if (curr_prot < protcnt) {
2380acd6859bSJames Smart 			/* advance to next prot buffer */
2381acd6859bSJames Smart 			sgpe = sg_next(sgpe);
2382acd6859bSJames Smart 
2383acd6859bSJames Smart 			/* update the reference tag */
2384acd6859bSJames Smart 			reftag += protgrp_blks;
2385acd6859bSJames Smart 		} else {
2386acd6859bSJames Smart 			/* if we're here, we have a bug */
2387372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
2388acd6859bSJames Smart 					"9085 BLKGRD: bug in %s\n", __func__);
2389acd6859bSJames Smart 		}
2390acd6859bSJames Smart 
2391acd6859bSJames Smart 	} while (!alldone);
2392acd6859bSJames Smart 
2393acd6859bSJames Smart out:
2394acd6859bSJames Smart 
2395acd6859bSJames Smart 	return num_sge;
2396acd6859bSJames Smart }
2397acd6859bSJames Smart 
2398acd6859bSJames Smart /**
2399acd6859bSJames Smart  * lpfc_prot_group_type - Get prtotection group type of SCSI command
2400acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
2401acd6859bSJames Smart  * @sc: pointer to scsi command we're working on
2402acd6859bSJames Smart  *
2403e2a0a9d6SJames Smart  * Given a SCSI command that supports DIF, determine composition of protection
2404e2a0a9d6SJames Smart  * groups involved in setting up buffer lists
2405e2a0a9d6SJames Smart  *
2406acd6859bSJames Smart  * Returns: Protection group type (with or without DIF)
2407acd6859bSJames Smart  *
2408e2a0a9d6SJames Smart  **/
2409e2a0a9d6SJames Smart static int
lpfc_prot_group_type(struct lpfc_hba * phba,struct scsi_cmnd * sc)2410e2a0a9d6SJames Smart lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc)
2411e2a0a9d6SJames Smart {
2412e2a0a9d6SJames Smart 	int ret = LPFC_PG_TYPE_INVALID;
2413e2a0a9d6SJames Smart 	unsigned char op = scsi_get_prot_op(sc);
2414e2a0a9d6SJames Smart 
2415e2a0a9d6SJames Smart 	switch (op) {
2416e2a0a9d6SJames Smart 	case SCSI_PROT_READ_STRIP:
2417e2a0a9d6SJames Smart 	case SCSI_PROT_WRITE_INSERT:
2418e2a0a9d6SJames Smart 		ret = LPFC_PG_TYPE_NO_DIF;
2419e2a0a9d6SJames Smart 		break;
2420e2a0a9d6SJames Smart 	case SCSI_PROT_READ_INSERT:
2421e2a0a9d6SJames Smart 	case SCSI_PROT_WRITE_STRIP:
2422e2a0a9d6SJames Smart 	case SCSI_PROT_READ_PASS:
2423e2a0a9d6SJames Smart 	case SCSI_PROT_WRITE_PASS:
2424e2a0a9d6SJames Smart 		ret = LPFC_PG_TYPE_DIF_BUF;
2425e2a0a9d6SJames Smart 		break;
2426e2a0a9d6SJames Smart 	default:
24279c6aa9d7SJames Smart 		if (phba)
2428372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
24299c6aa9d7SJames Smart 					"9021 Unsupported protection op:%d\n",
24309c6aa9d7SJames Smart 					op);
2431e2a0a9d6SJames Smart 		break;
2432e2a0a9d6SJames Smart 	}
2433e2a0a9d6SJames Smart 	return ret;
2434e2a0a9d6SJames Smart }
2435e2a0a9d6SJames Smart 
2436acd6859bSJames Smart /**
2437a6887e28SJames Smart  * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard
2438a6887e28SJames Smart  * @phba: The Hba for which this call is being executed.
2439a6887e28SJames Smart  * @lpfc_cmd: The scsi buffer which is going to be adjusted.
2440a6887e28SJames Smart  *
2441a6887e28SJames Smart  * Adjust the data length to account for how much data
2442a6887e28SJames Smart  * is actually on the wire.
2443a6887e28SJames Smart  *
2444a6887e28SJames Smart  * returns the adjusted data length
2445a6887e28SJames Smart  **/
2446a6887e28SJames Smart static int
lpfc_bg_scsi_adjust_dl(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)2447a6887e28SJames Smart lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba,
2448c490850aSJames Smart 		       struct lpfc_io_buf *lpfc_cmd)
2449a6887e28SJames Smart {
2450a6887e28SJames Smart 	struct scsi_cmnd *sc = lpfc_cmd->pCmd;
2451a6887e28SJames Smart 	int fcpdl;
2452a6887e28SJames Smart 
2453a6887e28SJames Smart 	fcpdl = scsi_bufflen(sc);
2454a6887e28SJames Smart 
2455a6887e28SJames Smart 	/* Check if there is protection data on the wire */
2456a6887e28SJames Smart 	if (sc->sc_data_direction == DMA_FROM_DEVICE) {
24579c6aa9d7SJames Smart 		/* Read check for protection data */
2458a6887e28SJames Smart 		if (scsi_get_prot_op(sc) ==  SCSI_PROT_READ_INSERT)
2459a6887e28SJames Smart 			return fcpdl;
2460a6887e28SJames Smart 
2461a6887e28SJames Smart 	} else {
24629c6aa9d7SJames Smart 		/* Write check for protection data */
2463a6887e28SJames Smart 		if (scsi_get_prot_op(sc) ==  SCSI_PROT_WRITE_STRIP)
2464a6887e28SJames Smart 			return fcpdl;
2465a6887e28SJames Smart 	}
2466a6887e28SJames Smart 
2467a6887e28SJames Smart 	/*
2468a6887e28SJames Smart 	 * If we are in DIF Type 1 mode every data block has a 8 byte
24699c6aa9d7SJames Smart 	 * DIF (trailer) attached to it. Must ajust FCP data length
24709c6aa9d7SJames Smart 	 * to account for the protection data.
2471a6887e28SJames Smart 	 */
2472125c12f7SMartin K. Petersen 	fcpdl += (fcpdl / scsi_prot_interval(sc)) * 8;
2473a6887e28SJames Smart 
2474a6887e28SJames Smart 	return fcpdl;
2475a6887e28SJames Smart }
2476a6887e28SJames Smart 
2477a6887e28SJames Smart /**
2478acd6859bSJames Smart  * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec
2479acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
2480acd6859bSJames Smart  * @lpfc_cmd: The scsi buffer which is going to be prep'ed.
2481acd6859bSJames Smart  *
2482e2a0a9d6SJames Smart  * This is the protection/DIF aware version of
2483e2a0a9d6SJames Smart  * lpfc_scsi_prep_dma_buf(). It may be a good idea to combine the
24845e0e2318SJames Smart  * two functions eventually, but for now, it's here.
24855e0e2318SJames Smart  * RETURNS 0 - SUCCESS,
24865e0e2318SJames Smart  *         1 - Failed DMA map, retry.
24875e0e2318SJames Smart  *         2 - Invalid scsi cmd or prot-type. Do not rety.
2488acd6859bSJames Smart  **/
2489e2a0a9d6SJames Smart static int
lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)2490acd6859bSJames Smart lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
2491c490850aSJames Smart 		struct lpfc_io_buf *lpfc_cmd)
2492e2a0a9d6SJames Smart {
2493e2a0a9d6SJames Smart 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
2494e2a0a9d6SJames Smart 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
2495c490850aSJames Smart 	struct ulp_bde64 *bpl = (struct ulp_bde64 *)lpfc_cmd->dma_sgl;
2496e2a0a9d6SJames Smart 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
2497e2a0a9d6SJames Smart 	uint32_t num_bde = 0;
2498e2a0a9d6SJames Smart 	int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
2499e2a0a9d6SJames Smart 	int prot_group_type = 0;
2500a6887e28SJames Smart 	int fcpdl;
25015e0e2318SJames Smart 	int ret = 1;
25027c4042a4SJames Smart 	struct lpfc_vport *vport = phba->pport;
2503e2a0a9d6SJames Smart 
2504e2a0a9d6SJames Smart 	/*
2505e2a0a9d6SJames Smart 	 * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd
2506e2a0a9d6SJames Smart 	 *  fcp_rsp regions to the first data bde entry
2507e2a0a9d6SJames Smart 	 */
2508e2a0a9d6SJames Smart 	bpl += 2;
2509e2a0a9d6SJames Smart 	if (scsi_sg_count(scsi_cmnd)) {
2510e2a0a9d6SJames Smart 		/*
25118d807a06SCai Huoqing 		 * The driver stores the segment count returned from dma_map_sg
2512e2a0a9d6SJames Smart 		 * because this a count of dma-mappings used to map the use_sg
2513e2a0a9d6SJames Smart 		 * pages.  They are not guaranteed to be the same for those
2514e2a0a9d6SJames Smart 		 * architectures that implement an IOMMU.
2515e2a0a9d6SJames Smart 		 */
2516e2a0a9d6SJames Smart 		datasegcnt = dma_map_sg(&phba->pcidev->dev,
2517e2a0a9d6SJames Smart 					scsi_sglist(scsi_cmnd),
2518e2a0a9d6SJames Smart 					scsi_sg_count(scsi_cmnd), datadir);
2519e2a0a9d6SJames Smart 		if (unlikely(!datasegcnt))
2520e2a0a9d6SJames Smart 			return 1;
2521e2a0a9d6SJames Smart 
2522e2a0a9d6SJames Smart 		lpfc_cmd->seg_cnt = datasegcnt;
252396f7077fSJames Smart 
252496f7077fSJames Smart 		/* First check if data segment count from SCSI Layer is good */
25255e0e2318SJames Smart 		if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
25265e0e2318SJames Smart 			WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt);
25275e0e2318SJames Smart 			ret = 2;
252896f7077fSJames Smart 			goto err;
25295e0e2318SJames Smart 		}
2530e2a0a9d6SJames Smart 
2531e2a0a9d6SJames Smart 		prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd);
2532e2a0a9d6SJames Smart 
2533e2a0a9d6SJames Smart 		switch (prot_group_type) {
2534e2a0a9d6SJames Smart 		case LPFC_PG_TYPE_NO_DIF:
253596f7077fSJames Smart 
253696f7077fSJames Smart 			/* Here we need to add a PDE5 and PDE6 to the count */
25375e0e2318SJames Smart 			if ((lpfc_cmd->seg_cnt + 2) > phba->cfg_total_seg_cnt) {
25385e0e2318SJames Smart 				ret = 2;
253996f7077fSJames Smart 				goto err;
25405e0e2318SJames Smart 			}
254196f7077fSJames Smart 
2542e2a0a9d6SJames Smart 			num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl,
2543e2a0a9d6SJames Smart 					datasegcnt);
2544c9404c9cSAdam Buchbinder 			/* we should have 2 or more entries in buffer list */
25455e0e2318SJames Smart 			if (num_bde < 2) {
25465e0e2318SJames Smart 				ret = 2;
2547e2a0a9d6SJames Smart 				goto err;
25485e0e2318SJames Smart 			}
2549e2a0a9d6SJames Smart 			break;
255096f7077fSJames Smart 
255196f7077fSJames Smart 		case LPFC_PG_TYPE_DIF_BUF:
2552e2a0a9d6SJames Smart 			/*
2553e2a0a9d6SJames Smart 			 * This type indicates that protection buffers are
2554e2a0a9d6SJames Smart 			 * passed to the driver, so that needs to be prepared
2555e2a0a9d6SJames Smart 			 * for DMA
2556e2a0a9d6SJames Smart 			 */
2557e2a0a9d6SJames Smart 			protsegcnt = dma_map_sg(&phba->pcidev->dev,
2558e2a0a9d6SJames Smart 					scsi_prot_sglist(scsi_cmnd),
2559e2a0a9d6SJames Smart 					scsi_prot_sg_count(scsi_cmnd), datadir);
2560e2a0a9d6SJames Smart 			if (unlikely(!protsegcnt)) {
2561e2a0a9d6SJames Smart 				scsi_dma_unmap(scsi_cmnd);
2562e2a0a9d6SJames Smart 				return 1;
2563e2a0a9d6SJames Smart 			}
2564e2a0a9d6SJames Smart 
2565e2a0a9d6SJames Smart 			lpfc_cmd->prot_seg_cnt = protsegcnt;
256696f7077fSJames Smart 
256796f7077fSJames Smart 			/*
256896f7077fSJames Smart 			 * There is a minimun of 4 BPLs used for every
256996f7077fSJames Smart 			 * protection data segment.
257096f7077fSJames Smart 			 */
257196f7077fSJames Smart 			if ((lpfc_cmd->prot_seg_cnt * 4) >
25725e0e2318SJames Smart 			    (phba->cfg_total_seg_cnt - 2)) {
25735e0e2318SJames Smart 				ret = 2;
257496f7077fSJames Smart 				goto err;
25755e0e2318SJames Smart 			}
2576e2a0a9d6SJames Smart 
2577e2a0a9d6SJames Smart 			num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl,
2578e2a0a9d6SJames Smart 					datasegcnt, protsegcnt);
2579c9404c9cSAdam Buchbinder 			/* we should have 3 or more entries in buffer list */
258096f7077fSJames Smart 			if ((num_bde < 3) ||
25815e0e2318SJames Smart 			    (num_bde > phba->cfg_total_seg_cnt)) {
25825e0e2318SJames Smart 				ret = 2;
2583e2a0a9d6SJames Smart 				goto err;
25845e0e2318SJames Smart 			}
2585e2a0a9d6SJames Smart 			break;
258696f7077fSJames Smart 
2587e2a0a9d6SJames Smart 		case LPFC_PG_TYPE_INVALID:
2588e2a0a9d6SJames Smart 		default:
258996f7077fSJames Smart 			scsi_dma_unmap(scsi_cmnd);
259096f7077fSJames Smart 			lpfc_cmd->seg_cnt = 0;
259196f7077fSJames Smart 
2592372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
2593e2a0a9d6SJames Smart 					"9022 Unexpected protection group %i\n",
2594e2a0a9d6SJames Smart 					prot_group_type);
25955e0e2318SJames Smart 			return 2;
2596e2a0a9d6SJames Smart 		}
2597e2a0a9d6SJames Smart 	}
2598e2a0a9d6SJames Smart 
2599e2a0a9d6SJames Smart 	/*
2600e2a0a9d6SJames Smart 	 * Finish initializing those IOCB fields that are dependent on the
2601e2a0a9d6SJames Smart 	 * scsi_cmnd request_buffer.  Note that the bdeSize is explicitly
2602e2a0a9d6SJames Smart 	 * reinitialized since all iocb memory resources are used many times
2603e2a0a9d6SJames Smart 	 * for transmit, receive, and continuation bpl's.
2604e2a0a9d6SJames Smart 	 */
2605e2a0a9d6SJames Smart 	iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
2606e2a0a9d6SJames Smart 	iocb_cmd->un.fcpi64.bdl.bdeSize += (num_bde * sizeof(struct ulp_bde64));
2607e2a0a9d6SJames Smart 	iocb_cmd->ulpBdeCount = 1;
2608e2a0a9d6SJames Smart 	iocb_cmd->ulpLe = 1;
2609e2a0a9d6SJames Smart 
2610a6887e28SJames Smart 	fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
2611af20bb73SJustin Tee 	fcp_cmnd->fcpDl = cpu_to_be32(fcpdl);
2612e2a0a9d6SJames Smart 
2613e2a0a9d6SJames Smart 	/*
2614e2a0a9d6SJames Smart 	 * Due to difference in data length between DIF/non-DIF paths,
2615e2a0a9d6SJames Smart 	 * we need to set word 4 of IOCB here
2616e2a0a9d6SJames Smart 	 */
2617e2a0a9d6SJames Smart 	iocb_cmd->un.fcpi.fcpi_parm = fcpdl;
2618e2a0a9d6SJames Smart 
26197c4042a4SJames Smart 	/*
26207c4042a4SJames Smart 	 * For First burst, we may need to adjust the initial transfer
26217c4042a4SJames Smart 	 * length for DIF
26227c4042a4SJames Smart 	 */
26237c4042a4SJames Smart 	if (iocb_cmd->un.fcpi.fcpi_XRdy &&
26247c4042a4SJames Smart 	    (fcpdl < vport->cfg_first_burst_size))
26257c4042a4SJames Smart 		iocb_cmd->un.fcpi.fcpi_XRdy = fcpdl;
26267c4042a4SJames Smart 
2627e2a0a9d6SJames Smart 	return 0;
2628e2a0a9d6SJames Smart err:
262996f7077fSJames Smart 	if (lpfc_cmd->seg_cnt)
263096f7077fSJames Smart 		scsi_dma_unmap(scsi_cmnd);
263196f7077fSJames Smart 	if (lpfc_cmd->prot_seg_cnt)
263296f7077fSJames Smart 		dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd),
263396f7077fSJames Smart 			     scsi_prot_sg_count(scsi_cmnd),
263496f7077fSJames Smart 			     scsi_cmnd->sc_data_direction);
263596f7077fSJames Smart 
2636372c187bSDick Kennedy 	lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
263796f7077fSJames Smart 			"9023 Cannot setup S/G List for HBA"
263896f7077fSJames Smart 			"IO segs %d/%d BPL %d SCSI %d: %d %d\n",
263996f7077fSJames Smart 			lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
264096f7077fSJames Smart 			phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
2641e2a0a9d6SJames Smart 			prot_group_type, num_bde);
264296f7077fSJames Smart 
264396f7077fSJames Smart 	lpfc_cmd->seg_cnt = 0;
264496f7077fSJames Smart 	lpfc_cmd->prot_seg_cnt = 0;
26455e0e2318SJames Smart 	return ret;
2646e2a0a9d6SJames Smart }
2647e2a0a9d6SJames Smart 
2648e2a0a9d6SJames Smart /*
2649737d4248SJames Smart  * This function calcuates the T10 DIF guard tag
2650737d4248SJames Smart  * on the specified data using a CRC algorithmn
2651737d4248SJames Smart  * using crc_t10dif.
2652737d4248SJames Smart  */
26537bfe781eSRashika Kheria static uint16_t
lpfc_bg_crc(uint8_t * data,int count)2654737d4248SJames Smart lpfc_bg_crc(uint8_t *data, int count)
2655737d4248SJames Smart {
2656737d4248SJames Smart 	uint16_t crc = 0;
2657737d4248SJames Smart 	uint16_t x;
2658737d4248SJames Smart 
2659737d4248SJames Smart 	crc = crc_t10dif(data, count);
2660737d4248SJames Smart 	x = cpu_to_be16(crc);
2661737d4248SJames Smart 	return x;
2662737d4248SJames Smart }
2663737d4248SJames Smart 
2664737d4248SJames Smart /*
2665737d4248SJames Smart  * This function calcuates the T10 DIF guard tag
2666737d4248SJames Smart  * on the specified data using a CSUM algorithmn
2667737d4248SJames Smart  * using ip_compute_csum.
2668737d4248SJames Smart  */
26697bfe781eSRashika Kheria static uint16_t
lpfc_bg_csum(uint8_t * data,int count)2670737d4248SJames Smart lpfc_bg_csum(uint8_t *data, int count)
2671737d4248SJames Smart {
2672737d4248SJames Smart 	uint16_t ret;
2673737d4248SJames Smart 
2674737d4248SJames Smart 	ret = ip_compute_csum(data, count);
2675737d4248SJames Smart 	return ret;
2676737d4248SJames Smart }
2677737d4248SJames Smart 
2678737d4248SJames Smart /*
2679737d4248SJames Smart  * This function examines the protection data to try to determine
2680737d4248SJames Smart  * what type of T10-DIF error occurred.
2681737d4248SJames Smart  */
26827bfe781eSRashika Kheria static void
lpfc_calc_bg_err(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)2683c490850aSJames Smart lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
2684737d4248SJames Smart {
2685737d4248SJames Smart 	struct scatterlist *sgpe; /* s/g prot entry */
2686737d4248SJames Smart 	struct scatterlist *sgde; /* s/g data entry */
2687737d4248SJames Smart 	struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
2688737d4248SJames Smart 	struct scsi_dif_tuple *src = NULL;
2689737d4248SJames Smart 	uint8_t *data_src = NULL;
2690db6f1c2fSSebastian Herbszt 	uint16_t guard_tag;
2691737d4248SJames Smart 	uint16_t start_app_tag, app_tag;
2692737d4248SJames Smart 	uint32_t start_ref_tag, ref_tag;
2693737d4248SJames Smart 	int prot, protsegcnt;
2694737d4248SJames Smart 	int err_type, len, data_len;
2695737d4248SJames Smart 	int chk_ref, chk_app, chk_guard;
2696737d4248SJames Smart 	uint16_t sum;
2697737d4248SJames Smart 	unsigned blksize;
2698737d4248SJames Smart 
2699737d4248SJames Smart 	err_type = BGS_GUARD_ERR_MASK;
2700737d4248SJames Smart 	sum = 0;
2701737d4248SJames Smart 	guard_tag = 0;
2702737d4248SJames Smart 
2703737d4248SJames Smart 	/* First check to see if there is protection data to examine */
2704737d4248SJames Smart 	prot = scsi_get_prot_op(cmd);
2705737d4248SJames Smart 	if ((prot == SCSI_PROT_READ_STRIP) ||
2706737d4248SJames Smart 	    (prot == SCSI_PROT_WRITE_INSERT) ||
2707737d4248SJames Smart 	    (prot == SCSI_PROT_NORMAL))
2708737d4248SJames Smart 		goto out;
2709737d4248SJames Smart 
2710737d4248SJames Smart 	/* Currently the driver just supports ref_tag and guard_tag checking */
2711737d4248SJames Smart 	chk_ref = 1;
2712737d4248SJames Smart 	chk_app = 0;
2713737d4248SJames Smart 	chk_guard = 0;
2714737d4248SJames Smart 
2715737d4248SJames Smart 	/* Setup a ptr to the protection data provided by the SCSI host */
2716737d4248SJames Smart 	sgpe = scsi_prot_sglist(cmd);
2717737d4248SJames Smart 	protsegcnt = lpfc_cmd->prot_seg_cnt;
2718737d4248SJames Smart 
2719737d4248SJames Smart 	if (sgpe && protsegcnt) {
2720737d4248SJames Smart 
2721737d4248SJames Smart 		/*
2722737d4248SJames Smart 		 * We will only try to verify guard tag if the segment
2723737d4248SJames Smart 		 * data length is a multiple of the blksize.
2724737d4248SJames Smart 		 */
2725737d4248SJames Smart 		sgde = scsi_sglist(cmd);
2726125c12f7SMartin K. Petersen 		blksize = scsi_prot_interval(cmd);
2727737d4248SJames Smart 		data_src = (uint8_t *)sg_virt(sgde);
2728aa7674bdSJustin Tee 		data_len = sg_dma_len(sgde);
2729737d4248SJames Smart 		if ((data_len & (blksize - 1)) == 0)
2730737d4248SJames Smart 			chk_guard = 1;
2731737d4248SJames Smart 
2732e85d8f9fSJames Smart 		src = (struct scsi_dif_tuple *)sg_virt(sgpe);
2733125c12f7SMartin K. Petersen 		start_ref_tag = scsi_prot_ref_tag(cmd);
2734737d4248SJames Smart 		start_app_tag = src->app_tag;
2735aa7674bdSJustin Tee 		len = sg_dma_len(sgpe);
2736737d4248SJames Smart 		while (src && protsegcnt) {
2737737d4248SJames Smart 			while (len) {
2738737d4248SJames Smart 
2739737d4248SJames Smart 				/*
2740737d4248SJames Smart 				 * First check to see if a protection data
2741737d4248SJames Smart 				 * check is valid
2742737d4248SJames Smart 				 */
2743128b6f9fSDmitry Monakhov 				if ((src->ref_tag == T10_PI_REF_ESCAPE) ||
2744128b6f9fSDmitry Monakhov 				    (src->app_tag == T10_PI_APP_ESCAPE)) {
2745737d4248SJames Smart 					start_ref_tag++;
2746737d4248SJames Smart 					goto skipit;
2747737d4248SJames Smart 				}
2748737d4248SJames Smart 
27499c6aa9d7SJames Smart 				/* First Guard Tag checking */
27509c6aa9d7SJames Smart 				if (chk_guard) {
27519c6aa9d7SJames Smart 					guard_tag = src->guard_tag;
2752125c12f7SMartin K. Petersen 					if (cmd->prot_flags
2753125c12f7SMartin K. Petersen 					    & SCSI_PROT_IP_CHECKSUM)
27549c6aa9d7SJames Smart 						sum = lpfc_bg_csum(data_src,
27559c6aa9d7SJames Smart 								   blksize);
27569c6aa9d7SJames Smart 					else
27579c6aa9d7SJames Smart 						sum = lpfc_bg_crc(data_src,
27589c6aa9d7SJames Smart 								  blksize);
27599c6aa9d7SJames Smart 					if ((guard_tag != sum)) {
27609c6aa9d7SJames Smart 						err_type = BGS_GUARD_ERR_MASK;
2761737d4248SJames Smart 						goto out;
2762737d4248SJames Smart 					}
27639c6aa9d7SJames Smart 				}
2764737d4248SJames Smart 
2765737d4248SJames Smart 				/* Reference Tag checking */
2766737d4248SJames Smart 				ref_tag = be32_to_cpu(src->ref_tag);
2767737d4248SJames Smart 				if (chk_ref && (ref_tag != start_ref_tag)) {
2768737d4248SJames Smart 					err_type = BGS_REFTAG_ERR_MASK;
2769737d4248SJames Smart 					goto out;
2770737d4248SJames Smart 				}
2771737d4248SJames Smart 				start_ref_tag++;
2772737d4248SJames Smart 
27739c6aa9d7SJames Smart 				/* App Tag checking */
27749c6aa9d7SJames Smart 				app_tag = src->app_tag;
27759c6aa9d7SJames Smart 				if (chk_app && (app_tag != start_app_tag)) {
27769c6aa9d7SJames Smart 					err_type = BGS_APPTAG_ERR_MASK;
2777737d4248SJames Smart 					goto out;
2778737d4248SJames Smart 				}
2779737d4248SJames Smart skipit:
2780737d4248SJames Smart 				len -= sizeof(struct scsi_dif_tuple);
2781737d4248SJames Smart 				if (len < 0)
2782737d4248SJames Smart 					len = 0;
2783737d4248SJames Smart 				src++;
2784737d4248SJames Smart 
2785737d4248SJames Smart 				data_src += blksize;
2786737d4248SJames Smart 				data_len -= blksize;
2787737d4248SJames Smart 
2788737d4248SJames Smart 				/*
2789737d4248SJames Smart 				 * Are we at the end of the Data segment?
2790737d4248SJames Smart 				 * The data segment is only used for Guard
2791737d4248SJames Smart 				 * tag checking.
2792737d4248SJames Smart 				 */
2793737d4248SJames Smart 				if (chk_guard && (data_len == 0)) {
2794737d4248SJames Smart 					chk_guard = 0;
2795737d4248SJames Smart 					sgde = sg_next(sgde);
2796737d4248SJames Smart 					if (!sgde)
2797737d4248SJames Smart 						goto out;
2798737d4248SJames Smart 
2799737d4248SJames Smart 					data_src = (uint8_t *)sg_virt(sgde);
2800aa7674bdSJustin Tee 					data_len = sg_dma_len(sgde);
2801737d4248SJames Smart 					if ((data_len & (blksize - 1)) == 0)
2802737d4248SJames Smart 						chk_guard = 1;
2803737d4248SJames Smart 				}
2804737d4248SJames Smart 			}
2805737d4248SJames Smart 
2806737d4248SJames Smart 			/* Goto the next Protection data segment */
2807737d4248SJames Smart 			sgpe = sg_next(sgpe);
2808737d4248SJames Smart 			if (sgpe) {
2809737d4248SJames Smart 				src = (struct scsi_dif_tuple *)sg_virt(sgpe);
2810aa7674bdSJustin Tee 				len = sg_dma_len(sgpe);
2811737d4248SJames Smart 			} else {
2812737d4248SJames Smart 				src = NULL;
2813737d4248SJames Smart 			}
2814737d4248SJames Smart 			protsegcnt--;
2815737d4248SJames Smart 		}
2816737d4248SJames Smart 	}
2817737d4248SJames Smart out:
2818737d4248SJames Smart 	if (err_type == BGS_GUARD_ERR_MASK) {
2819f2b1e9c6SHannes Reinecke 		scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1);
2820f2b1e9c6SHannes Reinecke 		set_host_byte(cmd, DID_ABORT);
2821737d4248SJames Smart 		phba->bg_guard_err_cnt++;
2822737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
282368a6a66cSJames Smart 				"9069 BLKGRD: reftag %x grd_tag err %x != %x\n",
2824125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2825737d4248SJames Smart 				sum, guard_tag);
2826737d4248SJames Smart 
2827737d4248SJames Smart 	} else if (err_type == BGS_REFTAG_ERR_MASK) {
2828f2b1e9c6SHannes Reinecke 		scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
2829f2b1e9c6SHannes Reinecke 		set_host_byte(cmd, DID_ABORT);
2830737d4248SJames Smart 
2831737d4248SJames Smart 		phba->bg_reftag_err_cnt++;
2832737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
283368a6a66cSJames Smart 				"9066 BLKGRD: reftag %x ref_tag err %x != %x\n",
2834125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2835737d4248SJames Smart 				ref_tag, start_ref_tag);
2836737d4248SJames Smart 
2837737d4248SJames Smart 	} else if (err_type == BGS_APPTAG_ERR_MASK) {
2838f2b1e9c6SHannes Reinecke 		scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
2839f2b1e9c6SHannes Reinecke 		set_host_byte(cmd, DID_ABORT);
2840737d4248SJames Smart 
2841737d4248SJames Smart 		phba->bg_apptag_err_cnt++;
2842737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
284368a6a66cSJames Smart 				"9041 BLKGRD: reftag %x app_tag err %x != %x\n",
2844125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2845737d4248SJames Smart 				app_tag, start_app_tag);
2846737d4248SJames Smart 	}
2847737d4248SJames Smart }
2848737d4248SJames Smart 
284996e209beSJames Smart /*
285096e209beSJames Smart  * This function checks for BlockGuard errors detected by
285196e209beSJames Smart  * the HBA.  In case of errors, the ASC/ASCQ fields in the
285296e209beSJames Smart  * sense buffer will be set accordingly, paired with
285396e209beSJames Smart  * ILLEGAL_REQUEST to signal to the kernel that the HBA
285496e209beSJames Smart  * detected corruption.
285596e209beSJames Smart  *
285696e209beSJames Smart  * Returns:
285796e209beSJames Smart  *  0 - No error found
285896e209beSJames Smart  *  1 - BlockGuard error found
285996e209beSJames Smart  * -1 - Internal error (bad profile, ...etc)
286096e209beSJames Smart  */
286196e209beSJames Smart static int
lpfc_parse_bg_err(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd,struct lpfc_iocbq * pIocbOut)28623512ac09SJames Smart lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
28633512ac09SJames Smart 		  struct lpfc_iocbq *pIocbOut)
286496e209beSJames Smart {
286596e209beSJames Smart 	struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
28663512ac09SJames Smart 	struct sli3_bg_fields *bgf;
286796e209beSJames Smart 	int ret = 0;
28683512ac09SJames Smart 	struct lpfc_wcqe_complete *wcqe;
28693512ac09SJames Smart 	u32 status;
287096e209beSJames Smart 	u32 bghm = 0;
287196e209beSJames Smart 	u32 bgstat = 0;
287296e209beSJames Smart 	u64 failing_sector = 0;
287396e209beSJames Smart 
28743512ac09SJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4) {
28753512ac09SJames Smart 		wcqe = &pIocbOut->wcqe_cmpl;
28763512ac09SJames Smart 		status = bf_get(lpfc_wcqe_c_status, wcqe);
28773512ac09SJames Smart 
287896e209beSJames Smart 		if (status == CQE_STATUS_DI_ERROR) {
28793512ac09SJames Smart 			/* Guard Check failed */
28803512ac09SJames Smart 			if (bf_get(lpfc_wcqe_c_bg_ge, wcqe))
288196e209beSJames Smart 				bgstat |= BGS_GUARD_ERR_MASK;
28823512ac09SJames Smart 
28833512ac09SJames Smart 			/* AppTag Check failed */
28843512ac09SJames Smart 			if (bf_get(lpfc_wcqe_c_bg_ae, wcqe))
288596e209beSJames Smart 				bgstat |= BGS_APPTAG_ERR_MASK;
28863512ac09SJames Smart 
28873512ac09SJames Smart 			/* RefTag Check failed */
28883512ac09SJames Smart 			if (bf_get(lpfc_wcqe_c_bg_re, wcqe))
288996e209beSJames Smart 				bgstat |= BGS_REFTAG_ERR_MASK;
289096e209beSJames Smart 
28913512ac09SJames Smart 			/* Check to see if there was any good data before the
28923512ac09SJames Smart 			 * error
28933512ac09SJames Smart 			 */
289496e209beSJames Smart 			if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
289596e209beSJames Smart 				bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK;
289696e209beSJames Smart 				bghm = wcqe->total_data_placed;
289796e209beSJames Smart 			}
289896e209beSJames Smart 
289996e209beSJames Smart 			/*
290096e209beSJames Smart 			 * Set ALL the error bits to indicate we don't know what
290196e209beSJames Smart 			 * type of error it is.
290296e209beSJames Smart 			 */
290396e209beSJames Smart 			if (!bgstat)
29043512ac09SJames Smart 				bgstat |= (BGS_REFTAG_ERR_MASK |
29053512ac09SJames Smart 					   BGS_APPTAG_ERR_MASK |
290696e209beSJames Smart 					   BGS_GUARD_ERR_MASK);
290796e209beSJames Smart 		}
290896e209beSJames Smart 
29093512ac09SJames Smart 	} else {
29103512ac09SJames Smart 		bgf = &pIocbOut->iocb.unsli3.sli3_bg;
29113512ac09SJames Smart 		bghm = bgf->bghm;
29123512ac09SJames Smart 		bgstat = bgf->bgstat;
291396e209beSJames Smart 	}
291496e209beSJames Smart 
2915e2a0a9d6SJames Smart 	if (lpfc_bgs_get_invalid_prof(bgstat)) {
2916c6668caeSJohannes Thumshirn 		cmd->result = DID_ERROR << 16;
2917737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
2918737d4248SJames Smart 				"9072 BLKGRD: Invalid BG Profile in cmd "
291968a6a66cSJames Smart 				"0x%x reftag 0x%x blk cnt 0x%x "
2920737d4248SJames Smart 				"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
2921125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2922125c12f7SMartin K. Petersen 				scsi_logical_block_count(cmd), bgstat, bghm);
2923e2a0a9d6SJames Smart 		ret = (-1);
2924e2a0a9d6SJames Smart 		goto out;
2925e2a0a9d6SJames Smart 	}
2926e2a0a9d6SJames Smart 
2927e2a0a9d6SJames Smart 	if (lpfc_bgs_get_uninit_dif_block(bgstat)) {
2928c6668caeSJohannes Thumshirn 		cmd->result = DID_ERROR << 16;
2929737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
2930737d4248SJames Smart 				"9073 BLKGRD: Invalid BG PDIF Block in cmd "
293168a6a66cSJames Smart 				"0x%x reftag 0x%x blk cnt 0x%x "
2932737d4248SJames Smart 				"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
2933125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2934125c12f7SMartin K. Petersen 				scsi_logical_block_count(cmd), bgstat, bghm);
2935e2a0a9d6SJames Smart 		ret = (-1);
2936e2a0a9d6SJames Smart 		goto out;
2937e2a0a9d6SJames Smart 	}
2938e2a0a9d6SJames Smart 
2939e2a0a9d6SJames Smart 	if (lpfc_bgs_get_guard_err(bgstat)) {
2940e2a0a9d6SJames Smart 		ret = 1;
2941f2b1e9c6SHannes Reinecke 		scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1);
2942f2b1e9c6SHannes Reinecke 		set_host_byte(cmd, DID_ABORT);
2943e2a0a9d6SJames Smart 		phba->bg_guard_err_cnt++;
2944737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
2945737d4248SJames Smart 				"9055 BLKGRD: Guard Tag error in cmd "
294668a6a66cSJames Smart 				"0x%x reftag 0x%x blk cnt 0x%x "
2947737d4248SJames Smart 				"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
2948125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2949125c12f7SMartin K. Petersen 				scsi_logical_block_count(cmd), bgstat, bghm);
2950e2a0a9d6SJames Smart 	}
2951e2a0a9d6SJames Smart 
2952e2a0a9d6SJames Smart 	if (lpfc_bgs_get_reftag_err(bgstat)) {
2953e2a0a9d6SJames Smart 		ret = 1;
2954f2b1e9c6SHannes Reinecke 		scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
2955f2b1e9c6SHannes Reinecke 		set_host_byte(cmd, DID_ABORT);
2956e2a0a9d6SJames Smart 		phba->bg_reftag_err_cnt++;
2957737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
2958737d4248SJames Smart 				"9056 BLKGRD: Ref Tag error in cmd "
295968a6a66cSJames Smart 				"0x%x reftag 0x%x blk cnt 0x%x "
2960737d4248SJames Smart 				"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
2961125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2962125c12f7SMartin K. Petersen 				scsi_logical_block_count(cmd), bgstat, bghm);
2963e2a0a9d6SJames Smart 	}
2964e2a0a9d6SJames Smart 
2965e2a0a9d6SJames Smart 	if (lpfc_bgs_get_apptag_err(bgstat)) {
2966e2a0a9d6SJames Smart 		ret = 1;
2967f2b1e9c6SHannes Reinecke 		scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
2968f2b1e9c6SHannes Reinecke 		set_host_byte(cmd, DID_ABORT);
2969e2a0a9d6SJames Smart 		phba->bg_apptag_err_cnt++;
2970737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
2971737d4248SJames Smart 				"9061 BLKGRD: App Tag error in cmd "
297268a6a66cSJames Smart 				"0x%x reftag 0x%x blk cnt 0x%x "
2973737d4248SJames Smart 				"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
2974125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
2975125c12f7SMartin K. Petersen 				scsi_logical_block_count(cmd), bgstat, bghm);
2976e2a0a9d6SJames Smart 	}
2977e2a0a9d6SJames Smart 
2978e2a0a9d6SJames Smart 	if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
2979e2a0a9d6SJames Smart 		/*
2980e2a0a9d6SJames Smart 		 * setup sense data descriptor 0 per SPC-4 as an information
29817c56b9fdSJames Smart 		 * field, and put the failing LBA in it.
29827c56b9fdSJames Smart 		 * This code assumes there was also a guard/app/ref tag error
29837c56b9fdSJames Smart 		 * indication.
2984e2a0a9d6SJames Smart 		 */
29857c56b9fdSJames Smart 		cmd->sense_buffer[7] = 0xc;   /* Additional sense length */
29867c56b9fdSJames Smart 		cmd->sense_buffer[8] = 0;     /* Information descriptor type */
29877c56b9fdSJames Smart 		cmd->sense_buffer[9] = 0xa;   /* Additional descriptor length */
29887c56b9fdSJames Smart 		cmd->sense_buffer[10] = 0x80; /* Validity bit */
2989acd6859bSJames Smart 
2990acd6859bSJames Smart 		/* bghm is a "on the wire" FC frame based count */
2991acd6859bSJames Smart 		switch (scsi_get_prot_op(cmd)) {
2992acd6859bSJames Smart 		case SCSI_PROT_READ_INSERT:
2993acd6859bSJames Smart 		case SCSI_PROT_WRITE_STRIP:
29942344b5b6SDavid Howells 			bghm /= cmd->device->sector_size;
2995acd6859bSJames Smart 			break;
2996acd6859bSJames Smart 		case SCSI_PROT_READ_STRIP:
2997acd6859bSJames Smart 		case SCSI_PROT_WRITE_INSERT:
2998acd6859bSJames Smart 		case SCSI_PROT_READ_PASS:
2999acd6859bSJames Smart 		case SCSI_PROT_WRITE_PASS:
3000acd6859bSJames Smart 			bghm /= (cmd->device->sector_size +
3001acd6859bSJames Smart 				sizeof(struct scsi_dif_tuple));
3002acd6859bSJames Smart 			break;
3003acd6859bSJames Smart 		}
3004e2a0a9d6SJames Smart 
3005e2a0a9d6SJames Smart 		failing_sector = scsi_get_lba(cmd);
3006e2a0a9d6SJames Smart 		failing_sector += bghm;
3007e2a0a9d6SJames Smart 
30087c56b9fdSJames Smart 		/* Descriptor Information */
30097c56b9fdSJames Smart 		put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]);
3010e2a0a9d6SJames Smart 	}
3011e2a0a9d6SJames Smart 
3012e2a0a9d6SJames Smart 	if (!ret) {
3013e2a0a9d6SJames Smart 		/* No error was reported - problem in FW? */
3014737d4248SJames Smart 		lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
3015737d4248SJames Smart 				"9057 BLKGRD: Unknown error in cmd "
301668a6a66cSJames Smart 				"0x%x reftag 0x%x blk cnt 0x%x "
3017737d4248SJames Smart 				"bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
3018125c12f7SMartin K. Petersen 				scsi_prot_ref_tag(cmd),
3019125c12f7SMartin K. Petersen 				scsi_logical_block_count(cmd), bgstat, bghm);
3020e2a0a9d6SJames Smart 
3021125c12f7SMartin K. Petersen 		/* Calculate what type of error it was */
3022737d4248SJames Smart 		lpfc_calc_bg_err(phba, lpfc_cmd);
3023737d4248SJames Smart 	}
3024e2a0a9d6SJames Smart out:
3025e2a0a9d6SJames Smart 	return ret;
3026e2a0a9d6SJames Smart }
3027e2a0a9d6SJames Smart 
3028ea2151b4SJames Smart /**
3029da0436e9SJames Smart  * lpfc_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec
3030da0436e9SJames Smart  * @phba: The Hba for which this call is being executed.
3031da0436e9SJames Smart  * @lpfc_cmd: The scsi buffer which is going to be mapped.
3032da0436e9SJames Smart  *
3033da0436e9SJames Smart  * This routine does the pci dma mapping for scatter-gather list of scsi cmnd
3034da0436e9SJames Smart  * field of @lpfc_cmd for device with SLI-4 interface spec.
3035da0436e9SJames Smart  *
3036da0436e9SJames Smart  * Return codes:
30375e0e2318SJames Smart  *	2 - Error - Do not retry
30385e0e2318SJames Smart  *	1 - Error - Retry
3039da0436e9SJames Smart  *	0 - Success
3040da0436e9SJames Smart  **/
3041da0436e9SJames Smart static int
lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)3042c490850aSJames Smart lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
3043da0436e9SJames Smart {
3044da0436e9SJames Smart 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
3045da0436e9SJames Smart 	struct scatterlist *sgel = NULL;
3046da0436e9SJames Smart 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
30470794d601SJames Smart 	struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl;
3048fedd3b7bSJames Smart 	struct sli4_sge *first_data_sgl;
3049da255e2eSJames Smart 	struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq;
3050da255e2eSJames Smart 	struct lpfc_vport *vport = phba->pport;
3051da255e2eSJames Smart 	union lpfc_wqe128 *wqe = &pwqeq->wqe;
3052da0436e9SJames Smart 	dma_addr_t physaddr;
3053da0436e9SJames Smart 	uint32_t dma_len;
3054da0436e9SJames Smart 	uint32_t dma_offset = 0;
3055d79c9e9dSJames Smart 	int nseg, i, j;
3056fedd3b7bSJames Smart 	struct ulp_bde64 *bde;
3057d79c9e9dSJames Smart 	bool lsp_just_set = false;
3058d79c9e9dSJames Smart 	struct sli4_hybrid_sgl *sgl_xtra = NULL;
3059da0436e9SJames Smart 
3060da0436e9SJames Smart 	/*
3061da0436e9SJames Smart 	 * There are three possibilities here - use scatter-gather segment, use
3062da0436e9SJames Smart 	 * the single mapping, or neither.  Start the lpfc command prep by
3063da0436e9SJames Smart 	 * bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
3064da0436e9SJames Smart 	 * data bde entry.
3065da0436e9SJames Smart 	 */
3066da0436e9SJames Smart 	if (scsi_sg_count(scsi_cmnd)) {
3067da0436e9SJames Smart 		/*
30688d807a06SCai Huoqing 		 * The driver stores the segment count returned from dma_map_sg
3069da0436e9SJames Smart 		 * because this a count of dma-mappings used to map the use_sg
3070da0436e9SJames Smart 		 * pages.  They are not guaranteed to be the same for those
3071da0436e9SJames Smart 		 * architectures that implement an IOMMU.
3072da0436e9SJames Smart 		 */
3073da0436e9SJames Smart 
3074da0436e9SJames Smart 		nseg = scsi_dma_map(scsi_cmnd);
30755116fbf1SJames Smart 		if (unlikely(nseg <= 0))
3076da0436e9SJames Smart 			return 1;
3077da0436e9SJames Smart 		sgl += 1;
3078da0436e9SJames Smart 		/* clear the last flag in the fcp_rsp map entry */
3079da0436e9SJames Smart 		sgl->word2 = le32_to_cpu(sgl->word2);
3080da0436e9SJames Smart 		bf_set(lpfc_sli4_sge_last, sgl, 0);
3081da0436e9SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
3082da0436e9SJames Smart 		sgl += 1;
3083fedd3b7bSJames Smart 		first_data_sgl = sgl;
3084da0436e9SJames Smart 		lpfc_cmd->seg_cnt = nseg;
3085d79c9e9dSJames Smart 		if (!phba->cfg_xpsgl &&
3086d79c9e9dSJames Smart 		    lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
3087372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
3088372c187bSDick Kennedy 					"9074 BLKGRD:"
30896a9c52cfSJames Smart 					" %s: Too many sg segments from "
3090da0436e9SJames Smart 					"dma_map_sg.  Config %d, seg_cnt %d\n",
3091da0436e9SJames Smart 					__func__, phba->cfg_sg_seg_cnt,
3092da0436e9SJames Smart 					lpfc_cmd->seg_cnt);
30935e0e2318SJames Smart 			WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt);
309496f7077fSJames Smart 			lpfc_cmd->seg_cnt = 0;
3095da0436e9SJames Smart 			scsi_dma_unmap(scsi_cmnd);
30965e0e2318SJames Smart 			return 2;
3097da0436e9SJames Smart 		}
3098da0436e9SJames Smart 
3099da0436e9SJames Smart 		/*
3100da0436e9SJames Smart 		 * The driver established a maximum scatter-gather segment count
3101da0436e9SJames Smart 		 * during probe that limits the number of sg elements in any
3102da0436e9SJames Smart 		 * single scsi command.  Just run through the seg_cnt and format
3103da0436e9SJames Smart 		 * the sge's.
3104da0436e9SJames Smart 		 * When using SLI-3 the driver will try to fit all the BDEs into
3105da0436e9SJames Smart 		 * the IOCB. If it can't then the BDEs get added to a BPL as it
3106da0436e9SJames Smart 		 * does for SLI-2 mode.
3107da0436e9SJames Smart 		 */
3108d79c9e9dSJames Smart 
3109d79c9e9dSJames Smart 		/* for tracking segment boundaries */
3110d79c9e9dSJames Smart 		sgel = scsi_sglist(scsi_cmnd);
3111d79c9e9dSJames Smart 		j = 2;
3112d79c9e9dSJames Smart 		for (i = 0; i < nseg; i++) {
3113d79c9e9dSJames Smart 			sgl->word2 = 0;
3114315b3fd1SJames Smart 			if (nseg == 1) {
3115d79c9e9dSJames Smart 				bf_set(lpfc_sli4_sge_last, sgl, 1);
3116d79c9e9dSJames Smart 				bf_set(lpfc_sli4_sge_type, sgl,
3117d79c9e9dSJames Smart 				       LPFC_SGE_TYPE_DATA);
3118d79c9e9dSJames Smart 			} else {
3119d79c9e9dSJames Smart 				bf_set(lpfc_sli4_sge_last, sgl, 0);
3120d79c9e9dSJames Smart 
3121d79c9e9dSJames Smart 				/* do we need to expand the segment */
3122d79c9e9dSJames Smart 				if (!lsp_just_set &&
3123d79c9e9dSJames Smart 				    !((j + 1) % phba->border_sge_num) &&
3124d79c9e9dSJames Smart 				    ((nseg - 1) != i)) {
3125d79c9e9dSJames Smart 					/* set LSP type */
3126d79c9e9dSJames Smart 					bf_set(lpfc_sli4_sge_type, sgl,
3127d79c9e9dSJames Smart 					       LPFC_SGE_TYPE_LSP);
3128d79c9e9dSJames Smart 
3129d79c9e9dSJames Smart 					sgl_xtra = lpfc_get_sgl_per_hdwq(
3130d79c9e9dSJames Smart 							phba, lpfc_cmd);
3131d79c9e9dSJames Smart 
3132d79c9e9dSJames Smart 					if (unlikely(!sgl_xtra)) {
3133d79c9e9dSJames Smart 						lpfc_cmd->seg_cnt = 0;
3134d79c9e9dSJames Smart 						scsi_dma_unmap(scsi_cmnd);
3135d79c9e9dSJames Smart 						return 1;
3136d79c9e9dSJames Smart 					}
3137d79c9e9dSJames Smart 					sgl->addr_lo = cpu_to_le32(putPaddrLow(
3138d79c9e9dSJames Smart 						       sgl_xtra->dma_phys_sgl));
3139d79c9e9dSJames Smart 					sgl->addr_hi = cpu_to_le32(putPaddrHigh(
3140d79c9e9dSJames Smart 						       sgl_xtra->dma_phys_sgl));
3141d79c9e9dSJames Smart 
3142d79c9e9dSJames Smart 				} else {
3143d79c9e9dSJames Smart 					bf_set(lpfc_sli4_sge_type, sgl,
3144d79c9e9dSJames Smart 					       LPFC_SGE_TYPE_DATA);
3145d79c9e9dSJames Smart 				}
3146d79c9e9dSJames Smart 			}
3147d79c9e9dSJames Smart 
3148d79c9e9dSJames Smart 			if (!(bf_get(lpfc_sli4_sge_type, sgl) &
3149d79c9e9dSJames Smart 				     LPFC_SGE_TYPE_LSP)) {
3150d79c9e9dSJames Smart 				if ((nseg - 1) == i)
3151d79c9e9dSJames Smart 					bf_set(lpfc_sli4_sge_last, sgl, 1);
3152d79c9e9dSJames Smart 
3153da0436e9SJames Smart 				physaddr = sg_dma_address(sgel);
3154da0436e9SJames Smart 				dma_len = sg_dma_len(sgel);
3155d79c9e9dSJames Smart 				sgl->addr_lo = cpu_to_le32(putPaddrLow(
3156d79c9e9dSJames Smart 							   physaddr));
3157d79c9e9dSJames Smart 				sgl->addr_hi = cpu_to_le32(putPaddrHigh(
3158d79c9e9dSJames Smart 							   physaddr));
3159d79c9e9dSJames Smart 
3160da0436e9SJames Smart 				bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
3161da0436e9SJames Smart 				sgl->word2 = cpu_to_le32(sgl->word2);
316228baac74SJames Smart 				sgl->sge_len = cpu_to_le32(dma_len);
3163d79c9e9dSJames Smart 
3164da0436e9SJames Smart 				dma_offset += dma_len;
3165d79c9e9dSJames Smart 				sgel = sg_next(sgel);
3166d79c9e9dSJames Smart 
3167da0436e9SJames Smart 				sgl++;
3168d79c9e9dSJames Smart 				lsp_just_set = false;
3169d79c9e9dSJames Smart 
3170d79c9e9dSJames Smart 			} else {
3171d79c9e9dSJames Smart 				sgl->word2 = cpu_to_le32(sgl->word2);
3172d79c9e9dSJames Smart 				sgl->sge_len = cpu_to_le32(
3173d79c9e9dSJames Smart 						     phba->cfg_sg_dma_buf_size);
3174d79c9e9dSJames Smart 
3175d79c9e9dSJames Smart 				sgl = (struct sli4_sge *)sgl_xtra->dma_sgl;
3176d79c9e9dSJames Smart 				i = i - 1;
3177d79c9e9dSJames Smart 
3178d79c9e9dSJames Smart 				lsp_just_set = true;
3179d79c9e9dSJames Smart 			}
3180d79c9e9dSJames Smart 
3181d79c9e9dSJames Smart 			j++;
3182da0436e9SJames Smart 		}
3183315b3fd1SJames Smart 
3184315b3fd1SJames Smart 		/* PBDE support for first data SGE only.
3185315b3fd1SJames Smart 		 * For FCoE, we key off Performance Hints.
3186315b3fd1SJames Smart 		 * For FC, we key off lpfc_enable_pbde.
31870bc2b7c5SJames Smart 		 */
3188315b3fd1SJames Smart 		if (nseg == 1 &&
3189315b3fd1SJames Smart 		    ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) ||
3190315b3fd1SJames Smart 		     phba->cfg_enable_pbde)) {
3191315b3fd1SJames Smart 			/* Words 13-15 */
3192fedd3b7bSJames Smart 			bde = (struct ulp_bde64 *)
3193da255e2eSJames Smart 				&wqe->words[13];
3194fedd3b7bSJames Smart 			bde->addrLow = first_data_sgl->addr_lo;
3195fedd3b7bSJames Smart 			bde->addrHigh = first_data_sgl->addr_hi;
3196fedd3b7bSJames Smart 			bde->tus.f.bdeSize =
3197fedd3b7bSJames Smart 					le32_to_cpu(first_data_sgl->sge_len);
3198fedd3b7bSJames Smart 			bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
3199fedd3b7bSJames Smart 			bde->tus.w = cpu_to_le32(bde->tus.w);
3200da255e2eSJames Smart 
3201315b3fd1SJames Smart 			/* Word 11 - set PBDE bit */
3202315b3fd1SJames Smart 			bf_set(wqe_pbde, &wqe->generic.wqe_com, 1);
3203da255e2eSJames Smart 		} else {
3204da255e2eSJames Smart 			memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3));
3205315b3fd1SJames Smart 			/* Word 11 - PBDE bit disabled by default template */
3206fedd3b7bSJames Smart 		}
3207da0436e9SJames Smart 	} else {
3208da0436e9SJames Smart 		sgl += 1;
3209315b3fd1SJames Smart 		/* set the last flag in the fcp_rsp map entry */
3210da0436e9SJames Smart 		sgl->word2 = le32_to_cpu(sgl->word2);
3211da0436e9SJames Smart 		bf_set(lpfc_sli4_sge_last, sgl, 1);
3212da0436e9SJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
3213414abe0aSJames Smart 
3214414abe0aSJames Smart 		if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) ||
3215414abe0aSJames Smart 		    phba->cfg_enable_pbde) {
3216414abe0aSJames Smart 			bde = (struct ulp_bde64 *)
3217da255e2eSJames Smart 				&wqe->words[13];
3218414abe0aSJames Smart 			memset(bde, 0, (sizeof(uint32_t) * 3));
3219414abe0aSJames Smart 		}
3220da0436e9SJames Smart 	}
3221da0436e9SJames Smart 
3222da0436e9SJames Smart 	/*
3223da0436e9SJames Smart 	 * Finish initializing those IOCB fields that are dependent on the
3224da0436e9SJames Smart 	 * scsi_cmnd request_buffer.  Note that for SLI-2 the bdeSize is
3225da0436e9SJames Smart 	 * explicitly reinitialized.
3226da0436e9SJames Smart 	 * all iocb memory resources are reused.
3227da0436e9SJames Smart 	 */
3228af20bb73SJustin Tee 	if (scsi_cmnd->cmd_len > LPFC_FCP_CDB_LEN)
3229af20bb73SJustin Tee 		((struct fcp_cmnd32 *)fcp_cmnd)->fcpDl =
3230af20bb73SJustin Tee 				cpu_to_be32(scsi_bufflen(scsi_cmnd));
3231af20bb73SJustin Tee 	else
3232da0436e9SJames Smart 		fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
3233da255e2eSJames Smart 	/* Set first-burst provided it was successfully negotiated */
3234e780c942SJustin Tee 	if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag) &&
3235da255e2eSJames Smart 	    vport->cfg_first_burst_size &&
3236da255e2eSJames Smart 	    scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) {
3237da255e2eSJames Smart 		u32 init_len, total_len;
3238da0436e9SJames Smart 
3239af20bb73SJustin Tee 		total_len = scsi_bufflen(scsi_cmnd);
3240da255e2eSJames Smart 		init_len = min(total_len, vport->cfg_first_burst_size);
3241da255e2eSJames Smart 
3242da255e2eSJames Smart 		/* Word 4 & 5 */
3243da255e2eSJames Smart 		wqe->fcp_iwrite.initial_xfer_len = init_len;
3244da255e2eSJames Smart 		wqe->fcp_iwrite.total_xfer_len = total_len;
3245da255e2eSJames Smart 	} else {
3246da255e2eSJames Smart 		/* Word 4 */
3247da255e2eSJames Smart 		wqe->fcp_iwrite.total_xfer_len =
3248da255e2eSJames Smart 			be32_to_cpu(fcp_cmnd->fcpDl);
3249da255e2eSJames Smart 	}
32501ba981fdSJames Smart 
32511ba981fdSJames Smart 	/*
32521ba981fdSJames Smart 	 * If the OAS driver feature is enabled and the lun is enabled for
32531ba981fdSJames Smart 	 * OAS, set the oas iocb related flags.
32541ba981fdSJames Smart 	 */
3255f38fa0bbSJames Smart 	if ((phba->cfg_fof) && ((struct lpfc_device_data *)
3256c92c841cSJames Smart 		scsi_cmnd->device->hostdata)->oas_enabled) {
3257a680a929SJames Smart 		lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
3258c92c841cSJames Smart 		lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *)
3259c92c841cSJames Smart 			scsi_cmnd->device->hostdata)->priority;
3260da255e2eSJames Smart 
3261da255e2eSJames Smart 		/* Word 10 */
3262da255e2eSJames Smart 		bf_set(wqe_oas, &wqe->generic.wqe_com, 1);
3263da255e2eSJames Smart 		bf_set(wqe_ccpe, &wqe->generic.wqe_com, 1);
3264da255e2eSJames Smart 
3265da255e2eSJames Smart 		if (lpfc_cmd->cur_iocbq.priority)
3266da255e2eSJames Smart 			bf_set(wqe_ccp, &wqe->generic.wqe_com,
3267da255e2eSJames Smart 			       (lpfc_cmd->cur_iocbq.priority << 1));
3268da255e2eSJames Smart 		else
3269da255e2eSJames Smart 			bf_set(wqe_ccp, &wqe->generic.wqe_com,
3270da255e2eSJames Smart 			       (phba->cfg_XLanePriority << 1));
3271c92c841cSJames Smart 	}
3272c490850aSJames Smart 
3273da0436e9SJames Smart 	return 0;
3274da0436e9SJames Smart }
3275da0436e9SJames Smart 
3276da0436e9SJames Smart /**
3277acd6859bSJames Smart  * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec
3278acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
3279acd6859bSJames Smart  * @lpfc_cmd: The scsi buffer which is going to be mapped.
3280acd6859bSJames Smart  *
3281acd6859bSJames Smart  * This is the protection/DIF aware version of
3282acd6859bSJames Smart  * lpfc_scsi_prep_dma_buf(). It may be a good idea to combine the
3283acd6859bSJames Smart  * two functions eventually, but for now, it's here
32845e0e2318SJames Smart  * Return codes:
32855e0e2318SJames Smart  *	2 - Error - Do not retry
32865e0e2318SJames Smart  *	1 - Error - Retry
32875e0e2318SJames Smart  *	0 - Success
3288acd6859bSJames Smart  **/
3289acd6859bSJames Smart static int
lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)3290acd6859bSJames Smart lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
3291c490850aSJames Smart 		struct lpfc_io_buf *lpfc_cmd)
3292acd6859bSJames Smart {
3293acd6859bSJames Smart 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
3294acd6859bSJames Smart 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
32950794d601SJames Smart 	struct sli4_sge *sgl = (struct sli4_sge *)(lpfc_cmd->dma_sgl);
3296da255e2eSJames Smart 	struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq;
3297da255e2eSJames Smart 	union lpfc_wqe128 *wqe = &pwqeq->wqe;
329896f7077fSJames Smart 	uint32_t num_sge = 0;
3299acd6859bSJames Smart 	int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
3300acd6859bSJames Smart 	int prot_group_type = 0;
3301acd6859bSJames Smart 	int fcpdl;
33025e0e2318SJames Smart 	int ret = 1;
33037c4042a4SJames Smart 	struct lpfc_vport *vport = phba->pport;
3304acd6859bSJames Smart 
3305acd6859bSJames Smart 	/*
3306acd6859bSJames Smart 	 * Start the lpfc command prep by bumping the sgl beyond fcp_cmnd
330796f7077fSJames Smart 	 *  fcp_rsp regions to the first data sge entry
3308acd6859bSJames Smart 	 */
3309acd6859bSJames Smart 	if (scsi_sg_count(scsi_cmnd)) {
3310acd6859bSJames Smart 		/*
33118d807a06SCai Huoqing 		 * The driver stores the segment count returned from dma_map_sg
3312acd6859bSJames Smart 		 * because this a count of dma-mappings used to map the use_sg
3313acd6859bSJames Smart 		 * pages.  They are not guaranteed to be the same for those
3314acd6859bSJames Smart 		 * architectures that implement an IOMMU.
3315acd6859bSJames Smart 		 */
3316acd6859bSJames Smart 		datasegcnt = dma_map_sg(&phba->pcidev->dev,
3317acd6859bSJames Smart 					scsi_sglist(scsi_cmnd),
3318acd6859bSJames Smart 					scsi_sg_count(scsi_cmnd), datadir);
3319acd6859bSJames Smart 		if (unlikely(!datasegcnt))
3320acd6859bSJames Smart 			return 1;
3321acd6859bSJames Smart 
3322acd6859bSJames Smart 		sgl += 1;
3323acd6859bSJames Smart 		/* clear the last flag in the fcp_rsp map entry */
3324acd6859bSJames Smart 		sgl->word2 = le32_to_cpu(sgl->word2);
3325acd6859bSJames Smart 		bf_set(lpfc_sli4_sge_last, sgl, 0);
3326acd6859bSJames Smart 		sgl->word2 = cpu_to_le32(sgl->word2);
3327acd6859bSJames Smart 
3328acd6859bSJames Smart 		sgl += 1;
3329acd6859bSJames Smart 		lpfc_cmd->seg_cnt = datasegcnt;
333096f7077fSJames Smart 
333196f7077fSJames Smart 		/* First check if data segment count from SCSI Layer is good */
3332d79c9e9dSJames Smart 		if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt &&
3333d79c9e9dSJames Smart 		    !phba->cfg_xpsgl) {
33345e0e2318SJames Smart 			WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt);
33355e0e2318SJames Smart 			ret = 2;
333696f7077fSJames Smart 			goto err;
33375e0e2318SJames Smart 		}
3338acd6859bSJames Smart 
3339acd6859bSJames Smart 		prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd);
3340acd6859bSJames Smart 
3341acd6859bSJames Smart 		switch (prot_group_type) {
3342acd6859bSJames Smart 		case LPFC_PG_TYPE_NO_DIF:
334396f7077fSJames Smart 			/* Here we need to add a DISEED to the count */
3344d79c9e9dSJames Smart 			if (((lpfc_cmd->seg_cnt + 1) >
3345d79c9e9dSJames Smart 					phba->cfg_total_seg_cnt) &&
3346d79c9e9dSJames Smart 			    !phba->cfg_xpsgl) {
33475e0e2318SJames Smart 				ret = 2;
334896f7077fSJames Smart 				goto err;
33495e0e2318SJames Smart 			}
335096f7077fSJames Smart 
335196f7077fSJames Smart 			num_sge = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl,
3352d79c9e9dSJames Smart 					datasegcnt, lpfc_cmd);
335396f7077fSJames Smart 
3354acd6859bSJames Smart 			/* we should have 2 or more entries in buffer list */
33555e0e2318SJames Smart 			if (num_sge < 2) {
33565e0e2318SJames Smart 				ret = 2;
3357acd6859bSJames Smart 				goto err;
33585e0e2318SJames Smart 			}
3359acd6859bSJames Smart 			break;
336096f7077fSJames Smart 
336196f7077fSJames Smart 		case LPFC_PG_TYPE_DIF_BUF:
3362acd6859bSJames Smart 			/*
3363acd6859bSJames Smart 			 * This type indicates that protection buffers are
3364acd6859bSJames Smart 			 * passed to the driver, so that needs to be prepared
3365acd6859bSJames Smart 			 * for DMA
3366acd6859bSJames Smart 			 */
3367acd6859bSJames Smart 			protsegcnt = dma_map_sg(&phba->pcidev->dev,
3368acd6859bSJames Smart 					scsi_prot_sglist(scsi_cmnd),
3369acd6859bSJames Smart 					scsi_prot_sg_count(scsi_cmnd), datadir);
3370acd6859bSJames Smart 			if (unlikely(!protsegcnt)) {
3371acd6859bSJames Smart 				scsi_dma_unmap(scsi_cmnd);
3372acd6859bSJames Smart 				return 1;
3373acd6859bSJames Smart 			}
3374acd6859bSJames Smart 
3375acd6859bSJames Smart 			lpfc_cmd->prot_seg_cnt = protsegcnt;
337696f7077fSJames Smart 			/*
337796f7077fSJames Smart 			 * There is a minimun of 3 SGEs used for every
337896f7077fSJames Smart 			 * protection data segment.
337996f7077fSJames Smart 			 */
3380d79c9e9dSJames Smart 			if (((lpfc_cmd->prot_seg_cnt * 3) >
3381d79c9e9dSJames Smart 					(phba->cfg_total_seg_cnt - 2)) &&
3382d79c9e9dSJames Smart 			    !phba->cfg_xpsgl) {
33835e0e2318SJames Smart 				ret = 2;
338496f7077fSJames Smart 				goto err;
33855e0e2318SJames Smart 			}
3386acd6859bSJames Smart 
338796f7077fSJames Smart 			num_sge = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl,
3388d79c9e9dSJames Smart 					datasegcnt, protsegcnt, lpfc_cmd);
338996f7077fSJames Smart 
3390acd6859bSJames Smart 			/* we should have 3 or more entries in buffer list */
3391d79c9e9dSJames Smart 			if (num_sge < 3 ||
3392d79c9e9dSJames Smart 			    (num_sge > phba->cfg_total_seg_cnt &&
3393d79c9e9dSJames Smart 			     !phba->cfg_xpsgl)) {
33945e0e2318SJames Smart 				ret = 2;
3395acd6859bSJames Smart 				goto err;
33965e0e2318SJames Smart 			}
3397acd6859bSJames Smart 			break;
339896f7077fSJames Smart 
3399acd6859bSJames Smart 		case LPFC_PG_TYPE_INVALID:
3400acd6859bSJames Smart 		default:
340196f7077fSJames Smart 			scsi_dma_unmap(scsi_cmnd);
340296f7077fSJames Smart 			lpfc_cmd->seg_cnt = 0;
340396f7077fSJames Smart 
3404372c187bSDick Kennedy 			lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
3405acd6859bSJames Smart 					"9083 Unexpected protection group %i\n",
3406acd6859bSJames Smart 					prot_group_type);
34075e0e2318SJames Smart 			return 2;
3408acd6859bSJames Smart 		}
3409acd6859bSJames Smart 	}
3410acd6859bSJames Smart 
34118012cc38SJames Smart 	switch (scsi_get_prot_op(scsi_cmnd)) {
34128012cc38SJames Smart 	case SCSI_PROT_WRITE_STRIP:
34138012cc38SJames Smart 	case SCSI_PROT_READ_STRIP:
3414a680a929SJames Smart 		lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_STRIP;
34158012cc38SJames Smart 		break;
34168012cc38SJames Smart 	case SCSI_PROT_WRITE_INSERT:
34178012cc38SJames Smart 	case SCSI_PROT_READ_INSERT:
3418a680a929SJames Smart 		lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_INSERT;
34198012cc38SJames Smart 		break;
34208012cc38SJames Smart 	case SCSI_PROT_WRITE_PASS:
34218012cc38SJames Smart 	case SCSI_PROT_READ_PASS:
3422a680a929SJames Smart 		lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_PASS;
34238012cc38SJames Smart 		break;
34248012cc38SJames Smart 	}
34258012cc38SJames Smart 
3426acd6859bSJames Smart 	fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
3427af20bb73SJustin Tee 	if (lpfc_cmd->pCmd->cmd_len > LPFC_FCP_CDB_LEN)
3428af20bb73SJustin Tee 		((struct fcp_cmnd32 *)fcp_cmnd)->fcpDl = cpu_to_be32(fcpdl);
3429af20bb73SJustin Tee 	else
3430af20bb73SJustin Tee 		fcp_cmnd->fcpDl = cpu_to_be32(fcpdl);
3431acd6859bSJames Smart 
3432da255e2eSJames Smart 	/* Set first-burst provided it was successfully negotiated */
3433e780c942SJustin Tee 	if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag) &&
3434da255e2eSJames Smart 	    vport->cfg_first_burst_size &&
3435da255e2eSJames Smart 	    scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) {
3436da255e2eSJames Smart 		u32 init_len, total_len;
3437acd6859bSJames Smart 
3438af20bb73SJustin Tee 		total_len = fcpdl;
3439da255e2eSJames Smart 		init_len = min(total_len, vport->cfg_first_burst_size);
3440da255e2eSJames Smart 
3441da255e2eSJames Smart 		/* Word 4 & 5 */
3442da255e2eSJames Smart 		wqe->fcp_iwrite.initial_xfer_len = init_len;
3443da255e2eSJames Smart 		wqe->fcp_iwrite.total_xfer_len = total_len;
3444da255e2eSJames Smart 	} else {
3445da255e2eSJames Smart 		/* Word 4 */
3446af20bb73SJustin Tee 		wqe->fcp_iwrite.total_xfer_len = fcpdl;
3447da255e2eSJames Smart 	}
34487c4042a4SJames Smart 
34497c4042a4SJames Smart 	/*
34509bd2bff5SJames Smart 	 * If the OAS driver feature is enabled and the lun is enabled for
34519bd2bff5SJames Smart 	 * OAS, set the oas iocb related flags.
34529bd2bff5SJames Smart 	 */
34539bd2bff5SJames Smart 	if ((phba->cfg_fof) && ((struct lpfc_device_data *)
3454da255e2eSJames Smart 		scsi_cmnd->device->hostdata)->oas_enabled) {
3455a680a929SJames Smart 		lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
34569bd2bff5SJames Smart 
3457da255e2eSJames Smart 		/* Word 10 */
3458da255e2eSJames Smart 		bf_set(wqe_oas, &wqe->generic.wqe_com, 1);
3459da255e2eSJames Smart 		bf_set(wqe_ccpe, &wqe->generic.wqe_com, 1);
3460da255e2eSJames Smart 		bf_set(wqe_ccp, &wqe->generic.wqe_com,
3461da255e2eSJames Smart 		       (phba->cfg_XLanePriority << 1));
3462da255e2eSJames Smart 	}
3463da255e2eSJames Smart 
3464da255e2eSJames Smart 	/* Word 7. DIF Flags */
3465a680a929SJames Smart 	if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_PASS)
3466da255e2eSJames Smart 		bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU);
3467a680a929SJames Smart 	else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_STRIP)
3468da255e2eSJames Smart 		bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP);
3469a680a929SJames Smart 	else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_INSERT)
3470da255e2eSJames Smart 		bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT);
3471da255e2eSJames Smart 
3472a680a929SJames Smart 	lpfc_cmd->cur_iocbq.cmd_flag &= ~(LPFC_IO_DIF_PASS |
3473da255e2eSJames Smart 				 LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT);
3474da255e2eSJames Smart 
3475acd6859bSJames Smart 	return 0;
3476acd6859bSJames Smart err:
347796f7077fSJames Smart 	if (lpfc_cmd->seg_cnt)
347896f7077fSJames Smart 		scsi_dma_unmap(scsi_cmnd);
347996f7077fSJames Smart 	if (lpfc_cmd->prot_seg_cnt)
348096f7077fSJames Smart 		dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd),
348196f7077fSJames Smart 			     scsi_prot_sg_count(scsi_cmnd),
348296f7077fSJames Smart 			     scsi_cmnd->sc_data_direction);
348396f7077fSJames Smart 
3484372c187bSDick Kennedy 	lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
348596f7077fSJames Smart 			"9084 Cannot setup S/G List for HBA "
34868eebf0e8SJustin Tee 			"IO segs %d/%d SGL %d SCSI %d: %d %d %d\n",
348796f7077fSJames Smart 			lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
348896f7077fSJames Smart 			phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
34898eebf0e8SJustin Tee 			prot_group_type, num_sge, ret);
349096f7077fSJames Smart 
349196f7077fSJames Smart 	lpfc_cmd->seg_cnt = 0;
349296f7077fSJames Smart 	lpfc_cmd->prot_seg_cnt = 0;
34935e0e2318SJames Smart 	return ret;
3494acd6859bSJames Smart }
3495acd6859bSJames Smart 
3496acd6859bSJames Smart /**
34973772a991SJames Smart  * lpfc_scsi_prep_dma_buf - Wrapper function for DMA mapping of scsi buffer
34983772a991SJames Smart  * @phba: The Hba for which this call is being executed.
34993772a991SJames Smart  * @lpfc_cmd: The scsi buffer which is going to be mapped.
35003772a991SJames Smart  *
35013772a991SJames Smart  * This routine wraps the actual DMA mapping function pointer from the
35023772a991SJames Smart  * lpfc_hba struct.
35033772a991SJames Smart  *
35043772a991SJames Smart  * Return codes:
35053772a991SJames Smart  *	1 - Error
35063772a991SJames Smart  *	0 - Success
35073772a991SJames Smart  **/
35083772a991SJames Smart static inline int
lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)3509c490850aSJames Smart lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
35103772a991SJames Smart {
35113772a991SJames Smart 	return phba->lpfc_scsi_prep_dma_buf(phba, lpfc_cmd);
35123772a991SJames Smart }
35133772a991SJames Smart 
35143772a991SJames Smart /**
3515acd6859bSJames Smart  * lpfc_bg_scsi_prep_dma_buf - Wrapper function for DMA mapping of scsi buffer
3516acd6859bSJames Smart  * using BlockGuard.
3517acd6859bSJames Smart  * @phba: The Hba for which this call is being executed.
3518acd6859bSJames Smart  * @lpfc_cmd: The scsi buffer which is going to be mapped.
3519acd6859bSJames Smart  *
3520acd6859bSJames Smart  * This routine wraps the actual DMA mapping function pointer from the
3521acd6859bSJames Smart  * lpfc_hba struct.
3522acd6859bSJames Smart  *
3523acd6859bSJames Smart  * Return codes:
3524acd6859bSJames Smart  *	1 - Error
3525acd6859bSJames Smart  *	0 - Success
3526acd6859bSJames Smart  **/
3527acd6859bSJames Smart static inline int
lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba * phba,struct lpfc_io_buf * lpfc_cmd)3528c490850aSJames Smart lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
3529acd6859bSJames Smart {
3530acd6859bSJames Smart 	return phba->lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd);
3531acd6859bSJames Smart }
3532acd6859bSJames Smart 
3533acd6859bSJames Smart /**
3534da255e2eSJames Smart  * lpfc_scsi_prep_cmnd_buf - Wrapper function for IOCB/WQE mapping of scsi
3535da255e2eSJames Smart  * buffer
35360bb87e01SLee Jones  * @vport: Pointer to vport object.
3537da255e2eSJames Smart  * @lpfc_cmd: The scsi buffer which is going to be mapped.
3538da255e2eSJames Smart  * @tmo: Timeout value for IO
3539da255e2eSJames Smart  *
3540da255e2eSJames Smart  * This routine initializes IOCB/WQE data structure from scsi command
3541da255e2eSJames Smart  *
3542da255e2eSJames Smart  * Return codes:
3543da255e2eSJames Smart  *	1 - Error
3544da255e2eSJames Smart  *	0 - Success
3545da255e2eSJames Smart  **/
3546da255e2eSJames Smart static inline int
lpfc_scsi_prep_cmnd_buf(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,uint8_t tmo)3547da255e2eSJames Smart lpfc_scsi_prep_cmnd_buf(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
3548da255e2eSJames Smart 			uint8_t tmo)
3549da255e2eSJames Smart {
3550da255e2eSJames Smart 	return vport->phba->lpfc_scsi_prep_cmnd_buf(vport, lpfc_cmd, tmo);
3551da255e2eSJames Smart }
3552da255e2eSJames Smart 
3553da255e2eSJames Smart /**
35543621a710SJames Smart  * lpfc_send_scsi_error_event - Posts an event when there is SCSI error
3555ea2151b4SJames Smart  * @phba: Pointer to hba context object.
3556ea2151b4SJames Smart  * @vport: Pointer to vport object.
3557ea2151b4SJames Smart  * @lpfc_cmd: Pointer to lpfc scsi command which reported the error.
35580bb87e01SLee Jones  * @fcpi_parm: FCP Initiator parameter.
3559ea2151b4SJames Smart  *
3560ea2151b4SJames Smart  * This function posts an event when there is a SCSI command reporting
3561ea2151b4SJames Smart  * error from the scsi device.
3562ea2151b4SJames Smart  **/
3563ea2151b4SJames Smart static void
lpfc_send_scsi_error_event(struct lpfc_hba * phba,struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,uint32_t fcpi_parm)3564ea2151b4SJames Smart lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
356596e209beSJames Smart 		struct lpfc_io_buf *lpfc_cmd, uint32_t fcpi_parm) {
3566ea2151b4SJames Smart 	struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
3567ea2151b4SJames Smart 	struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
3568ea2151b4SJames Smart 	uint32_t resp_info = fcprsp->rspStatus2;
3569ea2151b4SJames Smart 	uint32_t scsi_status = fcprsp->rspStatus3;
3570ea2151b4SJames Smart 	struct lpfc_fast_path_event *fast_path_evt = NULL;
3571ea2151b4SJames Smart 	struct lpfc_nodelist *pnode = lpfc_cmd->rdata->pnode;
3572ea2151b4SJames Smart 	unsigned long flags;
3573ea2151b4SJames Smart 
3574307e3380SJames Smart 	if (!pnode)
35755989b8d4SJames Smart 		return;
35765989b8d4SJames Smart 
3577ea2151b4SJames Smart 	/* If there is queuefull or busy condition send a scsi event */
3578ea2151b4SJames Smart 	if ((cmnd->result == SAM_STAT_TASK_SET_FULL) ||
3579ea2151b4SJames Smart 		(cmnd->result == SAM_STAT_BUSY)) {
3580ea2151b4SJames Smart 		fast_path_evt = lpfc_alloc_fast_evt(phba);
3581ea2151b4SJames Smart 		if (!fast_path_evt)
3582ea2151b4SJames Smart 			return;
3583ea2151b4SJames Smart 		fast_path_evt->un.scsi_evt.event_type =
3584ea2151b4SJames Smart 			FC_REG_SCSI_EVENT;
3585ea2151b4SJames Smart 		fast_path_evt->un.scsi_evt.subcategory =
3586ea2151b4SJames Smart 		(cmnd->result == SAM_STAT_TASK_SET_FULL) ?
3587ea2151b4SJames Smart 		LPFC_EVENT_QFULL : LPFC_EVENT_DEVBSY;
3588ea2151b4SJames Smart 		fast_path_evt->un.scsi_evt.lun = cmnd->device->lun;
3589ea2151b4SJames Smart 		memcpy(&fast_path_evt->un.scsi_evt.wwpn,
3590ea2151b4SJames Smart 			&pnode->nlp_portname, sizeof(struct lpfc_name));
3591ea2151b4SJames Smart 		memcpy(&fast_path_evt->un.scsi_evt.wwnn,
3592ea2151b4SJames Smart 			&pnode->nlp_nodename, sizeof(struct lpfc_name));
3593ea2151b4SJames Smart 	} else if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen &&
3594ea2151b4SJames Smart 		((cmnd->cmnd[0] == READ_10) || (cmnd->cmnd[0] == WRITE_10))) {
3595ea2151b4SJames Smart 		fast_path_evt = lpfc_alloc_fast_evt(phba);
3596ea2151b4SJames Smart 		if (!fast_path_evt)
3597ea2151b4SJames Smart 			return;
3598ea2151b4SJames Smart 		fast_path_evt->un.check_cond_evt.scsi_event.event_type =
3599ea2151b4SJames Smart 			FC_REG_SCSI_EVENT;
3600ea2151b4SJames Smart 		fast_path_evt->un.check_cond_evt.scsi_event.subcategory =
3601ea2151b4SJames Smart 			LPFC_EVENT_CHECK_COND;
3602ea2151b4SJames Smart 		fast_path_evt->un.check_cond_evt.scsi_event.lun =
3603ea2151b4SJames Smart 			cmnd->device->lun;
3604ea2151b4SJames Smart 		memcpy(&fast_path_evt->un.check_cond_evt.scsi_event.wwpn,
3605ea2151b4SJames Smart 			&pnode->nlp_portname, sizeof(struct lpfc_name));
3606ea2151b4SJames Smart 		memcpy(&fast_path_evt->un.check_cond_evt.scsi_event.wwnn,
3607ea2151b4SJames Smart 			&pnode->nlp_nodename, sizeof(struct lpfc_name));
3608ea2151b4SJames Smart 		fast_path_evt->un.check_cond_evt.sense_key =
3609ea2151b4SJames Smart 			cmnd->sense_buffer[2] & 0xf;
3610ea2151b4SJames Smart 		fast_path_evt->un.check_cond_evt.asc = cmnd->sense_buffer[12];
3611ea2151b4SJames Smart 		fast_path_evt->un.check_cond_evt.ascq = cmnd->sense_buffer[13];
3612ea2151b4SJames Smart 	} else if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
3613ea2151b4SJames Smart 		     fcpi_parm &&
3614ea2151b4SJames Smart 		     ((be32_to_cpu(fcprsp->rspResId) != fcpi_parm) ||
3615ea2151b4SJames Smart 			((scsi_status == SAM_STAT_GOOD) &&
3616ea2151b4SJames Smart 			!(resp_info & (RESID_UNDER | RESID_OVER))))) {
3617ea2151b4SJames Smart 		/*
3618ea2151b4SJames Smart 		 * If status is good or resid does not match with fcp_param and
3619ea2151b4SJames Smart 		 * there is valid fcpi_parm, then there is a read_check error
3620ea2151b4SJames Smart 		 */
3621ea2151b4SJames Smart 		fast_path_evt = lpfc_alloc_fast_evt(phba);
3622ea2151b4SJames Smart 		if (!fast_path_evt)
3623ea2151b4SJames Smart 			return;
3624ea2151b4SJames Smart 		fast_path_evt->un.read_check_error.header.event_type =
3625ea2151b4SJames Smart 			FC_REG_FABRIC_EVENT;
3626ea2151b4SJames Smart 		fast_path_evt->un.read_check_error.header.subcategory =
3627ea2151b4SJames Smart 			LPFC_EVENT_FCPRDCHKERR;
3628ea2151b4SJames Smart 		memcpy(&fast_path_evt->un.read_check_error.header.wwpn,
3629ea2151b4SJames Smart 			&pnode->nlp_portname, sizeof(struct lpfc_name));
3630ea2151b4SJames Smart 		memcpy(&fast_path_evt->un.read_check_error.header.wwnn,
3631ea2151b4SJames Smart 			&pnode->nlp_nodename, sizeof(struct lpfc_name));
3632ea2151b4SJames Smart 		fast_path_evt->un.read_check_error.lun = cmnd->device->lun;
3633ea2151b4SJames Smart 		fast_path_evt->un.read_check_error.opcode = cmnd->cmnd[0];
3634ea2151b4SJames Smart 		fast_path_evt->un.read_check_error.fcpiparam =
3635ea2151b4SJames Smart 			fcpi_parm;
3636ea2151b4SJames Smart 	} else
3637ea2151b4SJames Smart 		return;
3638ea2151b4SJames Smart 
3639ea2151b4SJames Smart 	fast_path_evt->vport = vport;
3640ea2151b4SJames Smart 	spin_lock_irqsave(&phba->hbalock, flags);
3641ea2151b4SJames Smart 	list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
3642ea2151b4SJames Smart 	spin_unlock_irqrestore(&phba->hbalock, flags);
3643ea2151b4SJames Smart 	lpfc_worker_wake_up(phba);
3644ea2151b4SJames Smart 	return;
3645ea2151b4SJames Smart }
36469bad7671SJames Smart 
36479bad7671SJames Smart /**
3648f1126688SJames Smart  * lpfc_scsi_unprep_dma_buf - Un-map DMA mapping of SG-list for dev
36493772a991SJames Smart  * @phba: The HBA for which this call is being executed.
36509bad7671SJames Smart  * @psb: The scsi buffer which is going to be un-mapped.
36519bad7671SJames Smart  *
36529bad7671SJames Smart  * This routine does DMA un-mapping of scatter gather list of scsi command
36533772a991SJames Smart  * field of @lpfc_cmd for device with SLI-3 interface spec.
36549bad7671SJames Smart  **/
3655dea3101eS static void
lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba,struct lpfc_io_buf * psb)3656c490850aSJames Smart lpfc_scsi_unprep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
3657bcf4dbfaSJames Smart {
3658bcf4dbfaSJames Smart 	/*
3659bcf4dbfaSJames Smart 	 * There are only two special cases to consider.  (1) the scsi command
3660bcf4dbfaSJames Smart 	 * requested scatter-gather usage or (2) the scsi command allocated
3661bcf4dbfaSJames Smart 	 * a request buffer, but did not request use_sg.  There is a third
3662bcf4dbfaSJames Smart 	 * case, but it does not require resource deallocation.
3663bcf4dbfaSJames Smart 	 */
3664a0b4f78fSFUJITA Tomonori 	if (psb->seg_cnt > 0)
3665a0b4f78fSFUJITA Tomonori 		scsi_dma_unmap(psb->pCmd);
3666e2a0a9d6SJames Smart 	if (psb->prot_seg_cnt > 0)
3667e2a0a9d6SJames Smart 		dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(psb->pCmd),
3668e2a0a9d6SJames Smart 				scsi_prot_sg_count(psb->pCmd),
3669e2a0a9d6SJames Smart 				psb->pCmd->sc_data_direction);
3670bcf4dbfaSJames Smart }
3671bcf4dbfaSJames Smart 
36729bad7671SJames Smart /**
367302243836SJames Smart  * lpfc_unblock_requests - allow further commands to be queued.
367402243836SJames Smart  * @phba: pointer to phba object
367502243836SJames Smart  *
367602243836SJames Smart  * For single vport, just call scsi_unblock_requests on physical port.
367702243836SJames Smart  * For multiple vports, send scsi_unblock_requests for all the vports.
367802243836SJames Smart  */
367902243836SJames Smart void
lpfc_unblock_requests(struct lpfc_hba * phba)368002243836SJames Smart lpfc_unblock_requests(struct lpfc_hba *phba)
368102243836SJames Smart {
368202243836SJames Smart 	struct lpfc_vport **vports;
368302243836SJames Smart 	struct Scsi_Host  *shost;
368402243836SJames Smart 	int i;
368502243836SJames Smart 
368602243836SJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4 &&
368702243836SJames Smart 	    !phba->sli4_hba.max_cfg_param.vpi_used) {
368802243836SJames Smart 		shost = lpfc_shost_from_vport(phba->pport);
368902243836SJames Smart 		scsi_unblock_requests(shost);
369002243836SJames Smart 		return;
369102243836SJames Smart 	}
369202243836SJames Smart 
369302243836SJames Smart 	vports = lpfc_create_vport_work_array(phba);
369402243836SJames Smart 	if (vports != NULL)
369502243836SJames Smart 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
369602243836SJames Smart 			shost = lpfc_shost_from_vport(vports[i]);
369702243836SJames Smart 			scsi_unblock_requests(shost);
369802243836SJames Smart 		}
369902243836SJames Smart 	lpfc_destroy_vport_work_array(phba, vports);
370002243836SJames Smart }
370102243836SJames Smart 
370202243836SJames Smart /**
370302243836SJames Smart  * lpfc_block_requests - prevent further commands from being queued.
370402243836SJames Smart  * @phba: pointer to phba object
370502243836SJames Smart  *
370602243836SJames Smart  * For single vport, just call scsi_block_requests on physical port.
370702243836SJames Smart  * For multiple vports, send scsi_block_requests for all the vports.
370802243836SJames Smart  */
370902243836SJames Smart void
lpfc_block_requests(struct lpfc_hba * phba)371002243836SJames Smart lpfc_block_requests(struct lpfc_hba *phba)
371102243836SJames Smart {
371202243836SJames Smart 	struct lpfc_vport **vports;
371302243836SJames Smart 	struct Scsi_Host  *shost;
371402243836SJames Smart 	int i;
371502243836SJames Smart 
371602243836SJames Smart 	if (atomic_read(&phba->cmf_stop_io))
371702243836SJames Smart 		return;
371802243836SJames Smart 
371902243836SJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4 &&
372002243836SJames Smart 	    !phba->sli4_hba.max_cfg_param.vpi_used) {
372102243836SJames Smart 		shost = lpfc_shost_from_vport(phba->pport);
372202243836SJames Smart 		scsi_block_requests(shost);
372302243836SJames Smart 		return;
372402243836SJames Smart 	}
372502243836SJames Smart 
372602243836SJames Smart 	vports = lpfc_create_vport_work_array(phba);
372702243836SJames Smart 	if (vports != NULL)
372802243836SJames Smart 		for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
372902243836SJames Smart 			shost = lpfc_shost_from_vport(vports[i]);
373002243836SJames Smart 			scsi_block_requests(shost);
373102243836SJames Smart 		}
373202243836SJames Smart 	lpfc_destroy_vport_work_array(phba, vports);
373302243836SJames Smart }
373402243836SJames Smart 
373502243836SJames Smart /**
373602243836SJames Smart  * lpfc_update_cmf_cmpl - Adjust CMF counters for IO completion
373702243836SJames Smart  * @phba: The HBA for which this call is being executed.
373802243836SJames Smart  * @time: The latency of the IO that completed (in ns)
373902243836SJames Smart  * @size: The size of the IO that completed
374002243836SJames Smart  * @shost: SCSI host the IO completed on (NULL for a NVME IO)
374102243836SJames Smart  *
374202243836SJames Smart  * The routine adjusts the various Burst and Bandwidth counters used in
374302243836SJames Smart  * Congestion management and E2E. If time is set to LPFC_CGN_NOT_SENT,
374402243836SJames Smart  * that means the IO was never issued to the HBA, so this routine is
374502243836SJames Smart  * just being called to cleanup the counter from a previous
374602243836SJames Smart  * lpfc_update_cmf_cmd call.
374702243836SJames Smart  */
374802243836SJames Smart int
lpfc_update_cmf_cmpl(struct lpfc_hba * phba,uint64_t time,uint32_t size,struct Scsi_Host * shost)374902243836SJames Smart lpfc_update_cmf_cmpl(struct lpfc_hba *phba,
375002243836SJames Smart 		     uint64_t time, uint32_t size, struct Scsi_Host *shost)
375102243836SJames Smart {
375202243836SJames Smart 	struct lpfc_cgn_stat *cgs;
375302243836SJames Smart 
375402243836SJames Smart 	if (time != LPFC_CGN_NOT_SENT) {
375502243836SJames Smart 		/* lat is ns coming in, save latency in us */
375602243836SJames Smart 		if (time < 1000)
375702243836SJames Smart 			time = 1;
375802243836SJames Smart 		else
375902243836SJames Smart 			time = div_u64(time + 500, 1000); /* round it */
376002243836SJames Smart 
3761d6d45f67SJames Smart 		cgs = per_cpu_ptr(phba->cmf_stat, raw_smp_processor_id());
376202243836SJames Smart 		atomic64_add(size, &cgs->rcv_bytes);
376302243836SJames Smart 		atomic64_add(time, &cgs->rx_latency);
376402243836SJames Smart 		atomic_inc(&cgs->rx_io_cnt);
376502243836SJames Smart 	}
376602243836SJames Smart 	return 0;
376702243836SJames Smart }
376802243836SJames Smart 
376902243836SJames Smart /**
377002243836SJames Smart  * lpfc_update_cmf_cmd - Adjust CMF counters for IO submission
377102243836SJames Smart  * @phba: The HBA for which this call is being executed.
377202243836SJames Smart  * @size: The size of the IO that will be issued
377302243836SJames Smart  *
377402243836SJames Smart  * The routine adjusts the various Burst and Bandwidth counters used in
377502243836SJames Smart  * Congestion management and E2E.
377602243836SJames Smart  */
377702243836SJames Smart int
lpfc_update_cmf_cmd(struct lpfc_hba * phba,uint32_t size)377802243836SJames Smart lpfc_update_cmf_cmd(struct lpfc_hba *phba, uint32_t size)
377902243836SJames Smart {
378002243836SJames Smart 	uint64_t total;
378102243836SJames Smart 	struct lpfc_cgn_stat *cgs;
378202243836SJames Smart 	int cpu;
378302243836SJames Smart 
378402243836SJames Smart 	/* At this point we are either LPFC_CFG_MANAGED or LPFC_CFG_MONITOR */
37853ea998cbSJames Smart 	if (phba->cmf_active_mode == LPFC_CFG_MANAGED &&
37863ea998cbSJames Smart 	    phba->cmf_max_bytes_per_interval) {
378702243836SJames Smart 		total = 0;
378802243836SJames Smart 		for_each_present_cpu(cpu) {
378902243836SJames Smart 			cgs = per_cpu_ptr(phba->cmf_stat, cpu);
379002243836SJames Smart 			total += atomic64_read(&cgs->total_bytes);
379102243836SJames Smart 		}
379202243836SJames Smart 		if (total >= phba->cmf_max_bytes_per_interval) {
379302243836SJames Smart 			if (!atomic_xchg(&phba->cmf_bw_wait, 1)) {
379402243836SJames Smart 				lpfc_block_requests(phba);
379502243836SJames Smart 				phba->cmf_last_ts =
379602243836SJames Smart 					lpfc_calc_cmf_latency(phba);
379702243836SJames Smart 			}
379802243836SJames Smart 			atomic_inc(&phba->cmf_busy);
379902243836SJames Smart 			return -EBUSY;
380002243836SJames Smart 		}
380117b27ac5SJames Smart 		if (size > atomic_read(&phba->rx_max_read_cnt))
380217b27ac5SJames Smart 			atomic_set(&phba->rx_max_read_cnt, size);
380302243836SJames Smart 	}
380402243836SJames Smart 
3805d6d45f67SJames Smart 	cgs = per_cpu_ptr(phba->cmf_stat, raw_smp_processor_id());
380602243836SJames Smart 	atomic64_add(size, &cgs->total_bytes);
380702243836SJames Smart 	return 0;
380802243836SJames Smart }
380902243836SJames Smart 
381002243836SJames Smart /**
38110bb87e01SLee Jones  * lpfc_handle_fcp_err - FCP response handler
38129bad7671SJames Smart  * @vport: The virtual port for which this call is being executed.
3813c490850aSJames Smart  * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
38140bb87e01SLee Jones  * @fcpi_parm: FCP Initiator parameter.
38159bad7671SJames Smart  *
38169bad7671SJames Smart  * This routine is called to process response IOCB with status field
38179bad7671SJames Smart  * IOSTAT_FCP_RSP_ERROR. This routine sets result field of scsi command
38189bad7671SJames Smart  * based upon SCSI and FCP error.
38199bad7671SJames Smart  **/
3820bcf4dbfaSJames Smart static void
lpfc_handle_fcp_err(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,uint32_t fcpi_parm)3821c490850aSJames Smart lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
382296e209beSJames Smart 		    uint32_t fcpi_parm)
3823dea3101eS {
3824dea3101eS 	struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
3825dea3101eS 	struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
3826dea3101eS 	struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
3827dea3101eS 	uint32_t resp_info = fcprsp->rspStatus2;
3828dea3101eS 	uint32_t scsi_status = fcprsp->rspStatus3;
3829c7743956SJames Smart 	uint32_t *lp;
3830dea3101eS 	uint32_t host_status = DID_OK;
3831dea3101eS 	uint32_t rsplen = 0;
38325afab6bbSJames Smart 	uint32_t fcpDl;
3833c7743956SJames Smart 	uint32_t logit = LOG_FCP | LOG_FCP_ERROR;
3834dea3101eS 
3835ea2151b4SJames Smart 
3836dea3101eS 	/*
3837dea3101eS 	 *  If this is a task management command, there is no
3838dea3101eS 	 *  scsi packet associated with this lpfc_cmd.  The driver
3839dea3101eS 	 *  consumes it.
3840dea3101eS 	 */
3841dea3101eS 	if (fcpcmd->fcpCntl2) {
3842dea3101eS 		scsi_status = 0;
3843dea3101eS 		goto out;
3844dea3101eS 	}
3845dea3101eS 
38466a9c52cfSJames Smart 	if (resp_info & RSP_LEN_VALID) {
38476a9c52cfSJames Smart 		rsplen = be32_to_cpu(fcprsp->rspRspLen);
3848e40a02c1SJames Smart 		if (rsplen != 0 && rsplen != 4 && rsplen != 8) {
3849372c187bSDick Kennedy 			lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
38506a9c52cfSJames Smart 					 "2719 Invalid response length: "
3851372c187bSDick Kennedy 					 "tgt x%x lun x%llx cmnd x%x rsplen "
3852372c187bSDick Kennedy 					 "x%x\n", cmnd->device->id,
38536a9c52cfSJames Smart 					 cmnd->device->lun, cmnd->cmnd[0],
38546a9c52cfSJames Smart 					 rsplen);
38556a9c52cfSJames Smart 			host_status = DID_ERROR;
38566a9c52cfSJames Smart 			goto out;
38576a9c52cfSJames Smart 		}
3858e40a02c1SJames Smart 		if (fcprsp->rspInfo3 != RSP_NO_FAILURE) {
3859372c187bSDick Kennedy 			lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
3860e40a02c1SJames Smart 				 "2757 Protocol failure detected during "
3861e40a02c1SJames Smart 				 "processing of FCP I/O op: "
38629cb78c16SHannes Reinecke 				 "tgt x%x lun x%llx cmnd x%x rspInfo3 x%x\n",
3863e40a02c1SJames Smart 				 cmnd->device->id,
3864e40a02c1SJames Smart 				 cmnd->device->lun, cmnd->cmnd[0],
3865e40a02c1SJames Smart 				 fcprsp->rspInfo3);
3866e40a02c1SJames Smart 			host_status = DID_ERROR;
3867e40a02c1SJames Smart 			goto out;
3868e40a02c1SJames Smart 		}
38696a9c52cfSJames Smart 	}
38706a9c52cfSJames Smart 
3871c7743956SJames Smart 	if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) {
3872c7743956SJames Smart 		uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen);
3873c7743956SJames Smart 		if (snslen > SCSI_SENSE_BUFFERSIZE)
3874c7743956SJames Smart 			snslen = SCSI_SENSE_BUFFERSIZE;
3875c7743956SJames Smart 
3876c7743956SJames Smart 		if (resp_info & RSP_LEN_VALID)
3877c7743956SJames Smart 		  rsplen = be32_to_cpu(fcprsp->rspRspLen);
3878c7743956SJames Smart 		memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen);
3879c7743956SJames Smart 	}
3880c7743956SJames Smart 	lp = (uint32_t *)cmnd->sense_buffer;
3881c7743956SJames Smart 
3882aa1c7ee7SJames Smart 	/* special handling for under run conditions */
3883aa1c7ee7SJames Smart 	if (!scsi_status && (resp_info & RESID_UNDER)) {
3884aa1c7ee7SJames Smart 		/* don't log under runs if fcp set... */
3885aa1c7ee7SJames Smart 		if (vport->cfg_log_verbose & LOG_FCP)
3886aa1c7ee7SJames Smart 			logit = LOG_FCP_ERROR;
3887aa1c7ee7SJames Smart 		/* unless operator says so */
3888aa1c7ee7SJames Smart 		if (vport->cfg_log_verbose & LOG_FCP_UNDER)
388973d91e50SJames Smart 			logit = LOG_FCP_UNDER;
3890aa1c7ee7SJames Smart 	}
3891c7743956SJames Smart 
3892e8b62011SJames Smart 	lpfc_printf_vlog(vport, KERN_WARNING, logit,
3893e2a0a9d6SJames Smart 			 "9024 FCP command x%x failed: x%x SNS x%x x%x "
3894c7743956SJames Smart 			 "Data: x%x x%x x%x x%x x%x\n",
3895e8b62011SJames Smart 			 cmnd->cmnd[0], scsi_status,
3896c7743956SJames Smart 			 be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info,
3897dea3101eS 			 be32_to_cpu(fcprsp->rspResId),
3898dea3101eS 			 be32_to_cpu(fcprsp->rspSnsLen),
3899dea3101eS 			 be32_to_cpu(fcprsp->rspRspLen),
3900dea3101eS 			 fcprsp->rspInfo3);
3901dea3101eS 
3902a0b4f78fSFUJITA Tomonori 	scsi_set_resid(cmnd, 0);
3903af20bb73SJustin Tee 	if (cmnd->cmd_len > LPFC_FCP_CDB_LEN)
3904af20bb73SJustin Tee 		fcpDl = be32_to_cpu(((struct fcp_cmnd32 *)fcpcmd)->fcpDl);
3905af20bb73SJustin Tee 	else
39065afab6bbSJames Smart 		fcpDl = be32_to_cpu(fcpcmd->fcpDl);
3907dea3101eS 	if (resp_info & RESID_UNDER) {
3908a0b4f78fSFUJITA Tomonori 		scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
3909dea3101eS 
391073d91e50SJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER,
391145634a86SJames Smart 				 "9025 FCP Underrun, expected %d, "
391292d7f7b0SJames Smart 				 "residual %d Data: x%x x%x x%x\n",
39135afab6bbSJames Smart 				 fcpDl,
3914a0b4f78fSFUJITA Tomonori 				 scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0],
391592d7f7b0SJames Smart 				 cmnd->underflow);
3916dea3101eS 
3917dea3101eS 		/*
391845634a86SJames Smart 		 * If there is an under run, check if under run reported by
39197054a606SJames Smart 		 * storage array is same as the under run reported by HBA.
39207054a606SJames Smart 		 * If this is not same, there is a dropped frame.
39217054a606SJames Smart 		 */
392245634a86SJames Smart 		if (fcpi_parm && (scsi_get_resid(cmnd) != fcpi_parm)) {
3923e8b62011SJames Smart 			lpfc_printf_vlog(vport, KERN_WARNING,
39247054a606SJames Smart 					 LOG_FCP | LOG_FCP_ERROR,
3925e2a0a9d6SJames Smart 					 "9026 FCP Read Check Error "
392692d7f7b0SJames Smart 					 "and Underrun Data: x%x x%x x%x x%x\n",
39275afab6bbSJames Smart 					 fcpDl,
3928a0b4f78fSFUJITA Tomonori 					 scsi_get_resid(cmnd), fcpi_parm,
3929a0b4f78fSFUJITA Tomonori 					 cmnd->cmnd[0]);
3930a0b4f78fSFUJITA Tomonori 			scsi_set_resid(cmnd, scsi_bufflen(cmnd));
39317054a606SJames Smart 			host_status = DID_ERROR;
39327054a606SJames Smart 		}
39337054a606SJames Smart 		/*
3934dea3101eS 		 * The cmnd->underflow is the minimum number of bytes that must
393525985edcSLucas De Marchi 		 * be transferred for this command.  Provided a sense condition
3936dea3101eS 		 * is not present, make sure the actual amount transferred is at
3937dea3101eS 		 * least the underflow value or fail.
3938dea3101eS 		 */
3939dea3101eS 		if (!(resp_info & SNS_LEN_VALID) &&
3940dea3101eS 		    (scsi_status == SAM_STAT_GOOD) &&
3941a0b4f78fSFUJITA Tomonori 		    (scsi_bufflen(cmnd) - scsi_get_resid(cmnd)
3942a0b4f78fSFUJITA Tomonori 		     < cmnd->underflow)) {
3943e8b62011SJames Smart 			lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
3944e2a0a9d6SJames Smart 					 "9027 FCP command x%x residual "
3945dea3101eS 					 "underrun converted to error "
394692d7f7b0SJames Smart 					 "Data: x%x x%x x%x\n",
394766dbfbe6SJames Smart 					 cmnd->cmnd[0], scsi_bufflen(cmnd),
3948a0b4f78fSFUJITA Tomonori 					 scsi_get_resid(cmnd), cmnd->underflow);
3949dea3101eS 			host_status = DID_ERROR;
3950dea3101eS 		}
3951dea3101eS 	} else if (resp_info & RESID_OVER) {
3952e8b62011SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
3953e2a0a9d6SJames Smart 				 "9028 FCP command x%x residual overrun error. "
3954e8b62011SJames Smart 				 "Data: x%x x%x\n", cmnd->cmnd[0],
3955a0b4f78fSFUJITA Tomonori 				 scsi_bufflen(cmnd), scsi_get_resid(cmnd));
3956dea3101eS 		host_status = DID_ERROR;
3957dea3101eS 
3958dea3101eS 	/*
3959dea3101eS 	 * Check SLI validation that all the transfer was actually done
396026373d23SJames Smart 	 * (fcpi_parm should be zero). Apply check only to reads.
3961dea3101eS 	 */
39625afab6bbSJames Smart 	} else if (fcpi_parm) {
3963e8b62011SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
396496e209beSJames Smart 				 "9029 FCP %s Check Error Data: "
3965eee8877eSJames Smart 				 "x%x x%x x%x x%x x%x\n",
39665afab6bbSJames Smart 				 ((cmnd->sc_data_direction == DMA_FROM_DEVICE) ?
39675afab6bbSJames Smart 				 "Read" : "Write"),
39685afab6bbSJames Smart 				 fcpDl, be32_to_cpu(fcprsp->rspResId),
3969eee8877eSJames Smart 				 fcpi_parm, cmnd->cmnd[0], scsi_status);
39705afab6bbSJames Smart 
39715afab6bbSJames Smart 		/* There is some issue with the LPe12000 that causes it
39725afab6bbSJames Smart 		 * to miscalculate the fcpi_parm and falsely trip this
39735afab6bbSJames Smart 		 * recovery logic.  Detect this case and don't error when true.
39745afab6bbSJames Smart 		 */
39755afab6bbSJames Smart 		if (fcpi_parm > fcpDl)
39765afab6bbSJames Smart 			goto out;
39775afab6bbSJames Smart 
3978eee8877eSJames Smart 		switch (scsi_status) {
3979eee8877eSJames Smart 		case SAM_STAT_GOOD:
3980eee8877eSJames Smart 		case SAM_STAT_CHECK_CONDITION:
3981eee8877eSJames Smart 			/* Fabric dropped a data frame. Fail any successful
3982eee8877eSJames Smart 			 * command in which we detected dropped frames.
3983eee8877eSJames Smart 			 * A status of good or some check conditions could
3984eee8877eSJames Smart 			 * be considered a successful command.
3985eee8877eSJames Smart 			 */
3986dea3101eS 			host_status = DID_ERROR;
3987eee8877eSJames Smart 			break;
3988eee8877eSJames Smart 		}
3989a0b4f78fSFUJITA Tomonori 		scsi_set_resid(cmnd, scsi_bufflen(cmnd));
3990dea3101eS 	}
3991dea3101eS 
3992dea3101eS  out:
3993c6668caeSJohannes Thumshirn 	cmnd->result = host_status << 16 | scsi_status;
399496e209beSJames Smart 	lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, fcpi_parm);
399596e209beSJames Smart }
399696e209beSJames Smart 
399796e209beSJames Smart /**
399896e209beSJames Smart  * lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO
399996e209beSJames Smart  * @phba: The hba for which this call is being executed.
400096e209beSJames Smart  * @pwqeIn: The command WQE for the scsi cmnd.
4001a680a929SJames Smart  * @pwqeOut: Pointer to driver response WQE object.
400296e209beSJames Smart  *
400396e209beSJames Smart  * This routine assigns scsi command result by looking into response WQE
400496e209beSJames Smart  * status field appropriately. This routine handles QUEUE FULL condition as
400596e209beSJames Smart  * well by ramping down device queue depth.
400696e209beSJames Smart  **/
400796e209beSJames Smart static void
lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba * phba,struct lpfc_iocbq * pwqeIn,struct lpfc_iocbq * pwqeOut)400896e209beSJames Smart lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
4009a680a929SJames Smart 			 struct lpfc_iocbq *pwqeOut)
401096e209beSJames Smart {
4011d51cf5bdSJames Smart 	struct lpfc_io_buf *lpfc_cmd = pwqeIn->io_buf;
4012a680a929SJames Smart 	struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl;
401396e209beSJames Smart 	struct lpfc_vport *vport = pwqeIn->vport;
40141e7dddb2SColin Ian King 	struct lpfc_rport_data *rdata;
40151e7dddb2SColin Ian King 	struct lpfc_nodelist *ndlp;
401696e209beSJames Smart 	struct scsi_cmnd *cmd;
401796e209beSJames Smart 	unsigned long flags;
401896e209beSJames Smart 	struct lpfc_fast_path_event *fast_path_evt;
401996e209beSJames Smart 	struct Scsi_Host *shost;
402096e209beSJames Smart 	u32 logit = LOG_FCP;
40216a84d015SJustin Tee 	u32 idx;
402202243836SJames Smart 	u32 lat;
40233e49af93SJames Smart 	u8 wait_xb_clr = 0;
402496e209beSJames Smart 
402596e209beSJames Smart 	/* Sanity check on return of outstanding command */
402696e209beSJames Smart 	if (!lpfc_cmd) {
402796e209beSJames Smart 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
402896e209beSJames Smart 				 "9032 Null lpfc_cmd pointer. No "
402996e209beSJames Smart 				 "release, skip completion\n");
403096e209beSJames Smart 		return;
403196e209beSJames Smart 	}
403296e209beSJames Smart 
40331e7dddb2SColin Ian King 	rdata = lpfc_cmd->rdata;
40341e7dddb2SColin Ian King 	ndlp = rdata->pnode;
40351e7dddb2SColin Ian King 
403696e209beSJames Smart 	/* Sanity check on return of outstanding command */
403796e209beSJames Smart 	cmd = lpfc_cmd->pCmd;
4038ae960d78SJames Smart 	if (!cmd) {
403996e209beSJames Smart 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
404096e209beSJames Smart 				 "9042 I/O completion: Not an active IO\n");
404196e209beSJames Smart 		lpfc_release_scsi_buf(phba, lpfc_cmd);
404296e209beSJames Smart 		return;
404396e209beSJames Smart 	}
40443512ac09SJames Smart 	/* Guard against abort handler being called at same time */
40453512ac09SJames Smart 	spin_lock(&lpfc_cmd->buf_lock);
404696e209beSJames Smart 	idx = lpfc_cmd->cur_iocbq.hba_wqidx;
404796e209beSJames Smart 	if (phba->sli4_hba.hdwq)
404896e209beSJames Smart 		phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
404996e209beSJames Smart 
405096e209beSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
405196e209beSJames Smart 	if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
405296e209beSJames Smart 		this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io);
405396e209beSJames Smart #endif
405496e209beSJames Smart 	shost = cmd->device->host;
405596e209beSJames Smart 
40566a84d015SJustin Tee 	lpfc_cmd->status = bf_get(lpfc_wcqe_c_status, wcqe);
405796e209beSJames Smart 	lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK);
405896e209beSJames Smart 
405996e209beSJames Smart 	lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
40603e49af93SJames Smart 	if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
406196e209beSJames Smart 		lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
40623e49af93SJames Smart 		if (phba->cfg_fcp_wait_abts_rsp)
40633e49af93SJames Smart 			wait_xb_clr = 1;
40643e49af93SJames Smart 	}
406596e209beSJames Smart 
406696e209beSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
406796e209beSJames Smart 	if (lpfc_cmd->prot_data_type) {
406896e209beSJames Smart 		struct scsi_dif_tuple *src = NULL;
406996e209beSJames Smart 
407096e209beSJames Smart 		src =  (struct scsi_dif_tuple *)lpfc_cmd->prot_data_segment;
407196e209beSJames Smart 		/*
407296e209beSJames Smart 		 * Used to restore any changes to protection
407396e209beSJames Smart 		 * data for error injection.
407496e209beSJames Smart 		 */
407596e209beSJames Smart 		switch (lpfc_cmd->prot_data_type) {
407696e209beSJames Smart 		case LPFC_INJERR_REFTAG:
407796e209beSJames Smart 			src->ref_tag =
407896e209beSJames Smart 				lpfc_cmd->prot_data;
407996e209beSJames Smart 			break;
408096e209beSJames Smart 		case LPFC_INJERR_APPTAG:
408196e209beSJames Smart 			src->app_tag =
408296e209beSJames Smart 				(uint16_t)lpfc_cmd->prot_data;
408396e209beSJames Smart 			break;
408496e209beSJames Smart 		case LPFC_INJERR_GUARD:
408596e209beSJames Smart 			src->guard_tag =
408696e209beSJames Smart 				(uint16_t)lpfc_cmd->prot_data;
408796e209beSJames Smart 			break;
408896e209beSJames Smart 		default:
408996e209beSJames Smart 			break;
409096e209beSJames Smart 		}
409196e209beSJames Smart 
409296e209beSJames Smart 		lpfc_cmd->prot_data = 0;
409396e209beSJames Smart 		lpfc_cmd->prot_data_type = 0;
409496e209beSJames Smart 		lpfc_cmd->prot_data_segment = NULL;
409596e209beSJames Smart 	}
409696e209beSJames Smart #endif
409796e209beSJames Smart 	if (unlikely(lpfc_cmd->status)) {
409896e209beSJames Smart 		if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR &&
409996e209beSJames Smart 		    !lpfc_cmd->fcp_rsp->rspStatus3 &&
410096e209beSJames Smart 		    (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) &&
410196e209beSJames Smart 		    !(vport->cfg_log_verbose & LOG_FCP_UNDER))
410296e209beSJames Smart 			logit = 0;
410396e209beSJames Smart 		else
410496e209beSJames Smart 			logit = LOG_FCP | LOG_FCP_UNDER;
410596e209beSJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, logit,
410696e209beSJames Smart 				 "9034 FCP cmd x%x failed <%d/%lld> "
410796e209beSJames Smart 				 "status: x%x result: x%x "
410896e209beSJames Smart 				 "sid: x%x did: x%x oxid: x%x "
410996e209beSJames Smart 				 "Data: x%x x%x x%x\n",
411096e209beSJames Smart 				 cmd->cmnd[0],
411196e209beSJames Smart 				 cmd->device ? cmd->device->id : 0xffff,
411296e209beSJames Smart 				 cmd->device ? cmd->device->lun : 0xffff,
411396e209beSJames Smart 				 lpfc_cmd->status, lpfc_cmd->result,
411496e209beSJames Smart 				 vport->fc_myDID,
411596e209beSJames Smart 				 (ndlp) ? ndlp->nlp_DID : 0,
411696e209beSJames Smart 				 lpfc_cmd->cur_iocbq.sli4_xritag,
411796e209beSJames Smart 				 wcqe->parameter, wcqe->total_data_placed,
411896e209beSJames Smart 				 lpfc_cmd->cur_iocbq.iotag);
411996e209beSJames Smart 	}
412096e209beSJames Smart 
412196e209beSJames Smart 	switch (lpfc_cmd->status) {
41226a84d015SJustin Tee 	case CQE_STATUS_SUCCESS:
412396e209beSJames Smart 		cmd->result = DID_OK << 16;
412496e209beSJames Smart 		break;
41256a84d015SJustin Tee 	case CQE_STATUS_FCP_RSP_FAILURE:
412696e209beSJames Smart 		lpfc_handle_fcp_err(vport, lpfc_cmd,
412796e209beSJames Smart 				    pwqeIn->wqe.fcp_iread.total_xfer_len -
412896e209beSJames Smart 				    wcqe->total_data_placed);
412996e209beSJames Smart 		break;
41306a84d015SJustin Tee 	case CQE_STATUS_NPORT_BSY:
41316a84d015SJustin Tee 	case CQE_STATUS_FABRIC_BSY:
413296e209beSJames Smart 		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
413396e209beSJames Smart 		fast_path_evt = lpfc_alloc_fast_evt(phba);
413496e209beSJames Smart 		if (!fast_path_evt)
413596e209beSJames Smart 			break;
413696e209beSJames Smart 		fast_path_evt->un.fabric_evt.event_type =
413796e209beSJames Smart 			FC_REG_FABRIC_EVENT;
413896e209beSJames Smart 		fast_path_evt->un.fabric_evt.subcategory =
413996e209beSJames Smart 			(lpfc_cmd->status == IOSTAT_NPORT_BSY) ?
414096e209beSJames Smart 			LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY;
414196e209beSJames Smart 		if (ndlp) {
414296e209beSJames Smart 			memcpy(&fast_path_evt->un.fabric_evt.wwpn,
414396e209beSJames Smart 			       &ndlp->nlp_portname,
414496e209beSJames Smart 				sizeof(struct lpfc_name));
414596e209beSJames Smart 			memcpy(&fast_path_evt->un.fabric_evt.wwnn,
414696e209beSJames Smart 			       &ndlp->nlp_nodename,
414796e209beSJames Smart 				sizeof(struct lpfc_name));
414896e209beSJames Smart 		}
414996e209beSJames Smart 		fast_path_evt->vport = vport;
415096e209beSJames Smart 		fast_path_evt->work_evt.evt =
415196e209beSJames Smart 			LPFC_EVT_FASTPATH_MGMT_EVT;
415296e209beSJames Smart 		spin_lock_irqsave(&phba->hbalock, flags);
415396e209beSJames Smart 		list_add_tail(&fast_path_evt->work_evt.evt_listp,
415496e209beSJames Smart 			      &phba->work_list);
415596e209beSJames Smart 		spin_unlock_irqrestore(&phba->hbalock, flags);
415696e209beSJames Smart 		lpfc_worker_wake_up(phba);
415796e209beSJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, logit,
415896e209beSJames Smart 				 "9035 Fabric/Node busy FCP cmd x%x failed"
415996e209beSJames Smart 				 " <%d/%lld> "
416096e209beSJames Smart 				 "status: x%x result: x%x "
416196e209beSJames Smart 				 "sid: x%x did: x%x oxid: x%x "
416296e209beSJames Smart 				 "Data: x%x x%x x%x\n",
416396e209beSJames Smart 				 cmd->cmnd[0],
416496e209beSJames Smart 				 cmd->device ? cmd->device->id : 0xffff,
416596e209beSJames Smart 				 cmd->device ? cmd->device->lun : 0xffff,
416696e209beSJames Smart 				 lpfc_cmd->status, lpfc_cmd->result,
416796e209beSJames Smart 				 vport->fc_myDID,
416896e209beSJames Smart 				 (ndlp) ? ndlp->nlp_DID : 0,
416996e209beSJames Smart 				 lpfc_cmd->cur_iocbq.sli4_xritag,
417096e209beSJames Smart 				 wcqe->parameter,
417196e209beSJames Smart 				 wcqe->total_data_placed,
417296e209beSJames Smart 				 lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
417396e209beSJames Smart 		break;
41746a84d015SJustin Tee 	case CQE_STATUS_DI_ERROR:
41756a84d015SJustin Tee 		if (bf_get(lpfc_wcqe_c_bg_edir, wcqe))
41766a84d015SJustin Tee 			lpfc_cmd->result = IOERR_RX_DMA_FAILED;
41776a84d015SJustin Tee 		else
41786a84d015SJustin Tee 			lpfc_cmd->result = IOERR_TX_DMA_FAILED;
41796a84d015SJustin Tee 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_BG,
41806a84d015SJustin Tee 				 "9048 DI Error xri x%x status x%x DI ext "
41816a84d015SJustin Tee 				 "status x%x data placed x%x\n",
41826a84d015SJustin Tee 				 lpfc_cmd->cur_iocbq.sli4_xritag,
41836a84d015SJustin Tee 				 lpfc_cmd->status, wcqe->parameter,
41846a84d015SJustin Tee 				 wcqe->total_data_placed);
41856a84d015SJustin Tee 		if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
41866a84d015SJustin Tee 			/* BG enabled cmd. Parse BG error */
41876a84d015SJustin Tee 			lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut);
41886a84d015SJustin Tee 			break;
41896a84d015SJustin Tee 		}
41906a84d015SJustin Tee 		cmd->result = DID_ERROR << 16;
41916a84d015SJustin Tee 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG,
41926a84d015SJustin Tee 				 "9040 DI Error on unprotected cmd\n");
41936a84d015SJustin Tee 		break;
41946a84d015SJustin Tee 	case CQE_STATUS_REMOTE_STOP:
419596e209beSJames Smart 		if (ndlp) {
419696e209beSJames Smart 			/* This I/O was aborted by the target, we don't
419796e209beSJames Smart 			 * know the rxid and because we did not send the
419896e209beSJames Smart 			 * ABTS we cannot generate and RRQ.
419996e209beSJames Smart 			 */
420096e209beSJames Smart 			lpfc_set_rrq_active(phba, ndlp,
420196e209beSJames Smart 					    lpfc_cmd->cur_iocbq.sli4_lxritag,
420296e209beSJames Smart 					    0, 0);
420396e209beSJames Smart 		}
420496e209beSJames Smart 		fallthrough;
42056a84d015SJustin Tee 	case CQE_STATUS_LOCAL_REJECT:
420696e209beSJames Smart 		if (lpfc_cmd->result & IOERR_DRVR_MASK)
420796e209beSJames Smart 			lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
420896e209beSJames Smart 		if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR ||
420996e209beSJames Smart 		    lpfc_cmd->result ==
421096e209beSJames Smart 		    IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR ||
421196e209beSJames Smart 		    lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR ||
421296e209beSJames Smart 		    lpfc_cmd->result ==
421396e209beSJames Smart 		    IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) {
421496e209beSJames Smart 			cmd->result = DID_NO_CONNECT << 16;
421596e209beSJames Smart 			break;
421696e209beSJames Smart 		}
421796e209beSJames Smart 		if (lpfc_cmd->result == IOERR_INVALID_RPI ||
4218b6474465SJames Smart 		    lpfc_cmd->result == IOERR_LINK_DOWN ||
421996e209beSJames Smart 		    lpfc_cmd->result == IOERR_NO_RESOURCES ||
422096e209beSJames Smart 		    lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
42212e81b1a3SJames Smart 		    lpfc_cmd->result == IOERR_RPI_SUSPENDED ||
422296e209beSJames Smart 		    lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
4223c0a50cd3SHannes Reinecke 			cmd->result = DID_TRANSPORT_DISRUPTED << 16;
422496e209beSJames Smart 			break;
422596e209beSJames Smart 		}
422696e209beSJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, logit,
422796e209beSJames Smart 				 "9036 Local Reject FCP cmd x%x failed"
422896e209beSJames Smart 				 " <%d/%lld> "
422996e209beSJames Smart 				 "status: x%x result: x%x "
423096e209beSJames Smart 				 "sid: x%x did: x%x oxid: x%x "
423196e209beSJames Smart 				 "Data: x%x x%x x%x\n",
423296e209beSJames Smart 				 cmd->cmnd[0],
423396e209beSJames Smart 				 cmd->device ? cmd->device->id : 0xffff,
423496e209beSJames Smart 				 cmd->device ? cmd->device->lun : 0xffff,
423596e209beSJames Smart 				 lpfc_cmd->status, lpfc_cmd->result,
423696e209beSJames Smart 				 vport->fc_myDID,
423796e209beSJames Smart 				 (ndlp) ? ndlp->nlp_DID : 0,
423896e209beSJames Smart 				 lpfc_cmd->cur_iocbq.sli4_xritag,
423996e209beSJames Smart 				 wcqe->parameter,
424096e209beSJames Smart 				 wcqe->total_data_placed,
424196e209beSJames Smart 				 lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
424296e209beSJames Smart 		fallthrough;
424396e209beSJames Smart 	default:
424496e209beSJames Smart 		cmd->result = DID_ERROR << 16;
42456a84d015SJustin Tee 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
424696e209beSJames Smart 				 "9037 FCP Completion Error: xri %x "
424796e209beSJames Smart 				 "status x%x result x%x [x%x] "
424896e209beSJames Smart 				 "placed x%x\n",
424996e209beSJames Smart 				 lpfc_cmd->cur_iocbq.sli4_xritag,
425096e209beSJames Smart 				 lpfc_cmd->status, lpfc_cmd->result,
425196e209beSJames Smart 				 wcqe->parameter,
425296e209beSJames Smart 				 wcqe->total_data_placed);
425396e209beSJames Smart 	}
425496e209beSJames Smart 	if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) {
425596e209beSJames Smart 		u32 *lp = (u32 *)cmd->sense_buffer;
425696e209beSJames Smart 
425796e209beSJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
4258f1156125SJames Smart 				 "9039 Iodone <%d/%llu> cmd x%px, error "
42592e81b1a3SJames Smart 				 "x%x SNS x%x x%x LBA x%llx Data: x%x x%x\n",
426096e209beSJames Smart 				 cmd->device->id, cmd->device->lun, cmd,
42612e81b1a3SJames Smart 				 cmd->result, *lp, *(lp + 3),
426284c868a7SJustin Tee 				 (cmd->device->sector_size) ?
426384c868a7SJustin Tee 				 (u64)scsi_get_lba(cmd) : 0,
42642e81b1a3SJames Smart 				 cmd->retries, scsi_get_resid(cmd));
426596e209beSJames Smart 	}
426696e209beSJames Smart 
426796e209beSJames Smart 	if (vport->cfg_max_scsicmpl_time &&
426896e209beSJames Smart 	    time_after(jiffies, lpfc_cmd->start_time +
426996e209beSJames Smart 	    msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
427096e209beSJames Smart 		spin_lock_irqsave(shost->host_lock, flags);
427196e209beSJames Smart 		if (ndlp) {
427296e209beSJames Smart 			if (ndlp->cmd_qdepth >
427396e209beSJames Smart 				atomic_read(&ndlp->cmd_pending) &&
427496e209beSJames Smart 				(atomic_read(&ndlp->cmd_pending) >
427596e209beSJames Smart 				LPFC_MIN_TGT_QDEPTH) &&
427696e209beSJames Smart 				(cmd->cmnd[0] == READ_10 ||
427796e209beSJames Smart 				cmd->cmnd[0] == WRITE_10))
427896e209beSJames Smart 				ndlp->cmd_qdepth =
427996e209beSJames Smart 					atomic_read(&ndlp->cmd_pending);
428096e209beSJames Smart 
428196e209beSJames Smart 			ndlp->last_change_time = jiffies;
428296e209beSJames Smart 		}
428396e209beSJames Smart 		spin_unlock_irqrestore(shost->host_lock, flags);
428496e209beSJames Smart 	}
428596e209beSJames Smart 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
428696e209beSJames Smart 
428796e209beSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
428896e209beSJames Smart 	if (lpfc_cmd->ts_cmd_start) {
428996e209beSJames Smart 		lpfc_cmd->ts_isr_cmpl = lpfc_cmd->cur_iocbq.isr_timestamp;
429096e209beSJames Smart 		lpfc_cmd->ts_data_io = ktime_get_ns();
429196e209beSJames Smart 		phba->ktime_last_cmd = lpfc_cmd->ts_data_io;
429296e209beSJames Smart 		lpfc_io_ktime(phba, lpfc_cmd);
429396e209beSJames Smart 	}
429496e209beSJames Smart #endif
429502243836SJames Smart 	if (likely(!wait_xb_clr))
429696e209beSJames Smart 		lpfc_cmd->pCmd = NULL;
429796e209beSJames Smart 	spin_unlock(&lpfc_cmd->buf_lock);
429896e209beSJames Smart 
429902243836SJames Smart 	/* Check if IO qualified for CMF */
430002243836SJames Smart 	if (phba->cmf_active_mode != LPFC_CFG_OFF &&
430102243836SJames Smart 	    cmd->sc_data_direction == DMA_FROM_DEVICE &&
430202243836SJames Smart 	    (scsi_sg_count(cmd))) {
430302243836SJames Smart 		/* Used when calculating average latency */
430402243836SJames Smart 		lat = ktime_get_ns() - lpfc_cmd->rx_cmd_start;
430502243836SJames Smart 		lpfc_update_cmf_cmpl(phba, lat, scsi_bufflen(cmd), shost);
430602243836SJames Smart 	}
430702243836SJames Smart 
430802243836SJames Smart 	if (wait_xb_clr)
430902243836SJames Smart 		goto out;
431002243836SJames Smart 
431196e209beSJames Smart 	/* The sdev is not guaranteed to be valid post scsi_done upcall. */
4312ca068c2cSBart Van Assche 	scsi_done(cmd);
431396e209beSJames Smart 
431496e209beSJames Smart 	/*
431596e209beSJames Smart 	 * If there is an abort thread waiting for command completion
431696e209beSJames Smart 	 * wake up the thread.
431796e209beSJames Smart 	 */
431896e209beSJames Smart 	spin_lock(&lpfc_cmd->buf_lock);
4319a680a929SJames Smart 	lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED;
432096e209beSJames Smart 	if (lpfc_cmd->waitq)
432196e209beSJames Smart 		wake_up(lpfc_cmd->waitq);
432296e209beSJames Smart 	spin_unlock(&lpfc_cmd->buf_lock);
432302243836SJames Smart out:
432496e209beSJames Smart 	lpfc_release_scsi_buf(phba, lpfc_cmd);
4325dea3101eS }
4326dea3101eS 
43279bad7671SJames Smart /**
43283621a710SJames Smart  * lpfc_scsi_cmd_iocb_cmpl - Scsi cmnd IOCB completion routine
43299bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
43309bad7671SJames Smart  * @pIocbIn: The command IOCBQ for the scsi cmnd.
43319bad7671SJames Smart  * @pIocbOut: The response IOCBQ for the scsi cmnd.
43329bad7671SJames Smart  *
43339bad7671SJames Smart  * This routine assigns scsi command result by looking into response IOCB
43349bad7671SJames Smart  * status field appropriately. This routine handles QUEUE FULL condition as
43359bad7671SJames Smart  * well by ramping down device queue depth.
43369bad7671SJames Smart  **/
4337dea3101eS static void
lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba * phba,struct lpfc_iocbq * pIocbIn,struct lpfc_iocbq * pIocbOut)4338dea3101eS lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
4339dea3101eS 			struct lpfc_iocbq *pIocbOut)
4340dea3101eS {
4341c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd =
4342d51cf5bdSJames Smart 		(struct lpfc_io_buf *) pIocbIn->io_buf;
43432e0fef85SJames Smart 	struct lpfc_vport      *vport = pIocbIn->vport;
4344dea3101eS 	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
4345dea3101eS 	struct lpfc_nodelist *pnode = rdata->pnode;
434675baf696SJames Smart 	struct scsi_cmnd *cmd;
4347fa61a54eSJames Smart 	unsigned long flags;
4348ea2151b4SJames Smart 	struct lpfc_fast_path_event *fast_path_evt;
434975baf696SJames Smart 	struct Scsi_Host *shost;
43504c47efc1SJames Smart 	int idx;
435173d91e50SJames Smart 	uint32_t logit = LOG_FCP;
4352dea3101eS 
4353c2017260SJames Smart 	/* Guard against abort handler being called at same time */
4354c2017260SJames Smart 	spin_lock(&lpfc_cmd->buf_lock);
4355c2017260SJames Smart 
435675baf696SJames Smart 	/* Sanity check on return of outstanding command */
435775baf696SJames Smart 	cmd = lpfc_cmd->pCmd;
435843bfea1bSJames Smart 	if (!cmd || !phba) {
4359372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
4360c2017260SJames Smart 				 "2621 IO completion: Not an active IO\n");
4361c2017260SJames Smart 		spin_unlock(&lpfc_cmd->buf_lock);
4362c90261dcSJames Smart 		return;
4363c2017260SJames Smart 	}
43644c47efc1SJames Smart 
43654c47efc1SJames Smart 	idx = lpfc_cmd->cur_iocbq.hba_wqidx;
43664c47efc1SJames Smart 	if (phba->sli4_hba.hdwq)
43674c47efc1SJames Smart 		phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
43684c47efc1SJames Smart 
43696a828b0fSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
4370840eda96SJames Smart 	if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
4371840eda96SJames Smart 		this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io);
43726a828b0fSJames Smart #endif
437375baf696SJames Smart 	shost = cmd->device->host;
437475baf696SJames Smart 
4375e3d2b802SJames Smart 	lpfc_cmd->result = (pIocbOut->iocb.un.ulpWord[4] & IOERR_PARAM_MASK);
4376dea3101eS 	lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
43773e49af93SJames Smart 	/* pick up SLI4 exchange busy status from HBA */
43783e49af93SJames Smart 	lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
4379a680a929SJames Smart 	if (pIocbOut->cmd_flag & LPFC_EXCHANGE_BUSY)
4380324e1c40SJames Smart 		lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
4381341af102SJames Smart 
43829a6b09c0SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
43839a6b09c0SJames Smart 	if (lpfc_cmd->prot_data_type) {
43849a6b09c0SJames Smart 		struct scsi_dif_tuple *src = NULL;
43859a6b09c0SJames Smart 
43869a6b09c0SJames Smart 		src =  (struct scsi_dif_tuple *)lpfc_cmd->prot_data_segment;
43879a6b09c0SJames Smart 		/*
43889a6b09c0SJames Smart 		 * Used to restore any changes to protection
43899a6b09c0SJames Smart 		 * data for error injection.
43909a6b09c0SJames Smart 		 */
43919a6b09c0SJames Smart 		switch (lpfc_cmd->prot_data_type) {
43929a6b09c0SJames Smart 		case LPFC_INJERR_REFTAG:
43939a6b09c0SJames Smart 			src->ref_tag =
43949a6b09c0SJames Smart 				lpfc_cmd->prot_data;
43959a6b09c0SJames Smart 			break;
43969a6b09c0SJames Smart 		case LPFC_INJERR_APPTAG:
43979a6b09c0SJames Smart 			src->app_tag =
43989a6b09c0SJames Smart 				(uint16_t)lpfc_cmd->prot_data;
43999a6b09c0SJames Smart 			break;
44009a6b09c0SJames Smart 		case LPFC_INJERR_GUARD:
44019a6b09c0SJames Smart 			src->guard_tag =
44029a6b09c0SJames Smart 				(uint16_t)lpfc_cmd->prot_data;
44039a6b09c0SJames Smart 			break;
44049a6b09c0SJames Smart 		default:
44059a6b09c0SJames Smart 			break;
44069a6b09c0SJames Smart 		}
44079a6b09c0SJames Smart 
44089a6b09c0SJames Smart 		lpfc_cmd->prot_data = 0;
44099a6b09c0SJames Smart 		lpfc_cmd->prot_data_type = 0;
44109a6b09c0SJames Smart 		lpfc_cmd->prot_data_segment = NULL;
44119a6b09c0SJames Smart 	}
44129a6b09c0SJames Smart #endif
44132ea259eeSJames Smart 
441422770cbaSJames Smart 	if (unlikely(lpfc_cmd->status)) {
4415dea3101eS 		if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
4416dea3101eS 		    (lpfc_cmd->result & IOERR_DRVR_MASK))
4417dea3101eS 			lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
4418dea3101eS 		else if (lpfc_cmd->status >= IOSTAT_CNT)
4419dea3101eS 			lpfc_cmd->status = IOSTAT_DEFAULT;
4420aa1c7ee7SJames Smart 		if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR &&
4421aa1c7ee7SJames Smart 		    !lpfc_cmd->fcp_rsp->rspStatus3 &&
4422aa1c7ee7SJames Smart 		    (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) &&
4423aa1c7ee7SJames Smart 		    !(vport->cfg_log_verbose & LOG_FCP_UNDER))
442473d91e50SJames Smart 			logit = 0;
442573d91e50SJames Smart 		else
442673d91e50SJames Smart 			logit = LOG_FCP | LOG_FCP_UNDER;
442773d91e50SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, logit,
44289cb78c16SHannes Reinecke 			 "9030 FCP cmd x%x failed <%d/%lld> "
44295a0d80fcSJames Smart 			 "status: x%x result: x%x "
44305a0d80fcSJames Smart 			 "sid: x%x did: x%x oxid: x%x "
44315a0d80fcSJames Smart 			 "Data: x%x x%x\n",
4432e8b62011SJames Smart 			 cmd->cmnd[0],
443392d7f7b0SJames Smart 			 cmd->device ? cmd->device->id : 0xffff,
443492d7f7b0SJames Smart 			 cmd->device ? cmd->device->lun : 0xffff,
443592d7f7b0SJames Smart 			 lpfc_cmd->status, lpfc_cmd->result,
44363bf41ba9SJames Smart 			 vport->fc_myDID,
44373bf41ba9SJames Smart 			 (pnode) ? pnode->nlp_DID : 0,
44385a0d80fcSJames Smart 			 phba->sli_rev == LPFC_SLI_REV4 ?
44395a0d80fcSJames Smart 			     lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff,
444092d7f7b0SJames Smart 			 pIocbOut->iocb.ulpContext,
4441dea3101eS 			 lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
4442dea3101eS 
4443dea3101eS 		switch (lpfc_cmd->status) {
4444dea3101eS 		case IOSTAT_FCP_RSP_ERROR:
4445dea3101eS 			/* Call FCP RSP handler to determine result */
444696e209beSJames Smart 			lpfc_handle_fcp_err(vport, lpfc_cmd,
444796e209beSJames Smart 					    pIocbOut->iocb.un.fcpi.fcpi_parm);
4448dea3101eS 			break;
4449dea3101eS 		case IOSTAT_NPORT_BSY:
4450dea3101eS 		case IOSTAT_FABRIC_BSY:
4451c6668caeSJohannes Thumshirn 			cmd->result = DID_TRANSPORT_DISRUPTED << 16;
4452ea2151b4SJames Smart 			fast_path_evt = lpfc_alloc_fast_evt(phba);
4453ea2151b4SJames Smart 			if (!fast_path_evt)
4454ea2151b4SJames Smart 				break;
4455ea2151b4SJames Smart 			fast_path_evt->un.fabric_evt.event_type =
4456ea2151b4SJames Smart 				FC_REG_FABRIC_EVENT;
4457ea2151b4SJames Smart 			fast_path_evt->un.fabric_evt.subcategory =
4458ea2151b4SJames Smart 				(lpfc_cmd->status == IOSTAT_NPORT_BSY) ?
4459ea2151b4SJames Smart 				LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY;
4460307e3380SJames Smart 			if (pnode) {
4461ea2151b4SJames Smart 				memcpy(&fast_path_evt->un.fabric_evt.wwpn,
4462ea2151b4SJames Smart 					&pnode->nlp_portname,
4463ea2151b4SJames Smart 					sizeof(struct lpfc_name));
4464ea2151b4SJames Smart 				memcpy(&fast_path_evt->un.fabric_evt.wwnn,
4465ea2151b4SJames Smart 					&pnode->nlp_nodename,
4466ea2151b4SJames Smart 					sizeof(struct lpfc_name));
4467ea2151b4SJames Smart 			}
4468ea2151b4SJames Smart 			fast_path_evt->vport = vport;
4469ea2151b4SJames Smart 			fast_path_evt->work_evt.evt =
4470ea2151b4SJames Smart 				LPFC_EVT_FASTPATH_MGMT_EVT;
4471ea2151b4SJames Smart 			spin_lock_irqsave(&phba->hbalock, flags);
4472ea2151b4SJames Smart 			list_add_tail(&fast_path_evt->work_evt.evt_listp,
4473ea2151b4SJames Smart 				&phba->work_list);
4474ea2151b4SJames Smart 			spin_unlock_irqrestore(&phba->hbalock, flags);
4475ea2151b4SJames Smart 			lpfc_worker_wake_up(phba);
4476dea3101eS 			break;
447792d7f7b0SJames Smart 		case IOSTAT_LOCAL_REJECT:
44781151e3ecSJames Smart 		case IOSTAT_REMOTE_STOP:
4479ab56dc2eSJames Smart 			if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR ||
4480ab56dc2eSJames Smart 			    lpfc_cmd->result ==
4481ab56dc2eSJames Smart 					IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR ||
4482ab56dc2eSJames Smart 			    lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR ||
4483ab56dc2eSJames Smart 			    lpfc_cmd->result ==
4484ab56dc2eSJames Smart 					IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) {
4485c6668caeSJohannes Thumshirn 				cmd->result = DID_NO_CONNECT << 16;
4486ab56dc2eSJames Smart 				break;
4487ab56dc2eSJames Smart 			}
4488d7c255b2SJames Smart 			if (lpfc_cmd->result == IOERR_INVALID_RPI ||
448992d7f7b0SJames Smart 			    lpfc_cmd->result == IOERR_NO_RESOURCES ||
4490b92938b4SJames Smart 			    lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
4491b92938b4SJames Smart 			    lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
4492c0a50cd3SHannes Reinecke 				cmd->result = DID_TRANSPORT_DISRUPTED << 16;
449392d7f7b0SJames Smart 				break;
4494e2a0a9d6SJames Smart 			}
4495e2a0a9d6SJames Smart 			if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
4496e2a0a9d6SJames Smart 			     lpfc_cmd->result == IOERR_TX_DMA_FAILED) &&
4497e2a0a9d6SJames Smart 			     pIocbOut->iocb.unsli3.sli3_bg.bgstat) {
4498e2a0a9d6SJames Smart 				if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
4499e2a0a9d6SJames Smart 					/*
4500e2a0a9d6SJames Smart 					 * This is a response for a BG enabled
4501e2a0a9d6SJames Smart 					 * cmd. Parse BG error
4502e2a0a9d6SJames Smart 					 */
4503e2a0a9d6SJames Smart 					lpfc_parse_bg_err(phba, lpfc_cmd,
4504e2a0a9d6SJames Smart 							pIocbOut);
4505e2a0a9d6SJames Smart 					break;
4506e2a0a9d6SJames Smart 				} else {
4507e2a0a9d6SJames Smart 					lpfc_printf_vlog(vport, KERN_WARNING,
4508e2a0a9d6SJames Smart 							LOG_BG,
4509e2a0a9d6SJames Smart 							"9031 non-zero BGSTAT "
45106a9c52cfSJames Smart 							"on unprotected cmd\n");
4511e2a0a9d6SJames Smart 				}
4512e2a0a9d6SJames Smart 			}
45131151e3ecSJames Smart 			if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP)
45141151e3ecSJames Smart 				&& (phba->sli_rev == LPFC_SLI_REV4)
4515307e3380SJames Smart 				&& pnode) {
45161151e3ecSJames Smart 				/* This IO was aborted by the target, we don't
45171151e3ecSJames Smart 				 * know the rxid and because we did not send the
45181151e3ecSJames Smart 				 * ABTS we cannot generate and RRQ.
45191151e3ecSJames Smart 				 */
45201151e3ecSJames Smart 				lpfc_set_rrq_active(phba, pnode,
4521ee0f4fe1SJames Smart 					lpfc_cmd->cur_iocbq.sli4_lxritag,
45221151e3ecSJames Smart 					0, 0);
45231151e3ecSJames Smart 			}
4524df561f66SGustavo A. R. Silva 			fallthrough;
4525dea3101eS 		default:
4526c6668caeSJohannes Thumshirn 			cmd->result = DID_ERROR << 16;
4527dea3101eS 			break;
4528dea3101eS 		}
4529dea3101eS 
4530307e3380SJames Smart 		if (!pnode || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
4531c6668caeSJohannes Thumshirn 			cmd->result = DID_TRANSPORT_DISRUPTED << 16 |
4532c6668caeSJohannes Thumshirn 				      SAM_STAT_BUSY;
4533ab56dc2eSJames Smart 	} else
4534c6668caeSJohannes Thumshirn 		cmd->result = DID_OK << 16;
4535dea3101eS 
4536dea3101eS 	if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) {
4537dea3101eS 		uint32_t *lp = (uint32_t *)cmd->sense_buffer;
4538dea3101eS 
4539e8b62011SJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
454032350664SJames Smart 				 "0710 Iodone <%d/%llu> cmd x%px, error "
454192d7f7b0SJames Smart 				 "x%x SNS x%x x%x Data: x%x x%x\n",
4542e8b62011SJames Smart 				 cmd->device->id, cmd->device->lun, cmd,
4543e8b62011SJames Smart 				 cmd->result, *lp, *(lp + 3), cmd->retries,
4544a0b4f78fSFUJITA Tomonori 				 scsi_get_resid(cmd));
4545dea3101eS 	}
4546dea3101eS 
4547977b5a0aSJames Smart 	if (vport->cfg_max_scsicmpl_time &&
4548977b5a0aSJames Smart 	   time_after(jiffies, lpfc_cmd->start_time +
4549977b5a0aSJames Smart 		msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
4550a257bf90SJames Smart 		spin_lock_irqsave(shost->host_lock, flags);
4551307e3380SJames Smart 		if (pnode) {
4552109f6ed0SJames Smart 			if (pnode->cmd_qdepth >
4553109f6ed0SJames Smart 				atomic_read(&pnode->cmd_pending) &&
4554109f6ed0SJames Smart 				(atomic_read(&pnode->cmd_pending) >
4555109f6ed0SJames Smart 				LPFC_MIN_TGT_QDEPTH) &&
4556109f6ed0SJames Smart 				((cmd->cmnd[0] == READ_10) ||
4557109f6ed0SJames Smart 				(cmd->cmnd[0] == WRITE_10)))
4558109f6ed0SJames Smart 				pnode->cmd_qdepth =
4559109f6ed0SJames Smart 					atomic_read(&pnode->cmd_pending);
4560977b5a0aSJames Smart 
4561977b5a0aSJames Smart 			pnode->last_change_time = jiffies;
4562109f6ed0SJames Smart 		}
4563a257bf90SJames Smart 		spin_unlock_irqrestore(shost->host_lock, flags);
4564977b5a0aSJames Smart 	}
45651dcb58e5SJames Smart 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
4566a257bf90SJames Smart 
4567c2017260SJames Smart 	lpfc_cmd->pCmd = NULL;
4568c2017260SJames Smart 	spin_unlock(&lpfc_cmd->buf_lock);
456992e3af66SJames Smart 
45702fcbc569SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
45712fcbc569SJames Smart 	if (lpfc_cmd->ts_cmd_start) {
45722fcbc569SJames Smart 		lpfc_cmd->ts_isr_cmpl = pIocbIn->isr_timestamp;
45732fcbc569SJames Smart 		lpfc_cmd->ts_data_io = ktime_get_ns();
45742fcbc569SJames Smart 		phba->ktime_last_cmd = lpfc_cmd->ts_data_io;
45752fcbc569SJames Smart 		lpfc_io_ktime(phba, lpfc_cmd);
45762fcbc569SJames Smart 	}
45772fcbc569SJames Smart #endif
45783e49af93SJames Smart 
457989533e9bSJames Smart 	/* The sdev is not guaranteed to be valid post scsi_done upcall. */
4580ca068c2cSBart Van Assche 	scsi_done(cmd);
458189533e9bSJames Smart 
4582fa61a54eSJames Smart 	/*
4583c2017260SJames Smart 	 * If there is an abort thread waiting for command completion
4584fa61a54eSJames Smart 	 * wake up the thread.
4585fa61a54eSJames Smart 	 */
4586c2017260SJames Smart 	spin_lock(&lpfc_cmd->buf_lock);
4587a680a929SJames Smart 	lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED;
4588b9e5a2d9SJames Smart 	if (lpfc_cmd->waitq)
4589fa61a54eSJames Smart 		wake_up(lpfc_cmd->waitq);
4590c2017260SJames Smart 	spin_unlock(&lpfc_cmd->buf_lock);
4591fa61a54eSJames Smart 
45920bd4ca25SJames.Smart@Emulex.Com 	lpfc_release_scsi_buf(phba, lpfc_cmd);
4593dea3101eS }
4594dea3101eS 
459534b02dcdSJames Smart /**
4596da255e2eSJames Smart  * lpfc_scsi_prep_cmnd_buf_s3 - SLI-3 IOCB init for the IO
45970bb87e01SLee Jones  * @vport: Pointer to vport object.
4598da255e2eSJames Smart  * @lpfc_cmd: The scsi buffer which is going to be prep'ed.
4599da255e2eSJames Smart  * @tmo: timeout value for the IO
46008b2564ecSAlexey Kardashevskiy  *
4601da255e2eSJames Smart  * Based on the data-direction of the command, initialize IOCB
4602da255e2eSJames Smart  * in the I/O buffer. Fill in the IOCB fields which are independent
4603da255e2eSJames Smart  * of the scsi buffer
4604da255e2eSJames Smart  *
4605da255e2eSJames Smart  * RETURNS 0 - SUCCESS,
46068b2564ecSAlexey Kardashevskiy  **/
lpfc_scsi_prep_cmnd_buf_s3(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,uint8_t tmo)4607da255e2eSJames Smart static int lpfc_scsi_prep_cmnd_buf_s3(struct lpfc_vport *vport,
4608da255e2eSJames Smart 				      struct lpfc_io_buf *lpfc_cmd,
4609da255e2eSJames Smart 				      uint8_t tmo)
46108b2564ecSAlexey Kardashevskiy {
4611da255e2eSJames Smart 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
4612da255e2eSJames Smart 	struct lpfc_iocbq *piocbq = &lpfc_cmd->cur_iocbq;
4613da255e2eSJames Smart 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
4614da255e2eSJames Smart 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
4615da255e2eSJames Smart 	struct lpfc_nodelist *pnode = lpfc_cmd->ndlp;
4616da255e2eSJames Smart 	int datadir = scsi_cmnd->sc_data_direction;
4617da255e2eSJames Smart 	u32 fcpdl;
4618da255e2eSJames Smart 
4619da255e2eSJames Smart 	piocbq->iocb.un.fcpi.fcpi_XRdy = 0;
4620da255e2eSJames Smart 
4621da255e2eSJames Smart 	/*
4622da255e2eSJames Smart 	 * There are three possibilities here - use scatter-gather segment, use
4623da255e2eSJames Smart 	 * the single mapping, or neither.  Start the lpfc command prep by
4624da255e2eSJames Smart 	 * bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
4625da255e2eSJames Smart 	 * data bde entry.
4626da255e2eSJames Smart 	 */
4627da255e2eSJames Smart 	if (scsi_sg_count(scsi_cmnd)) {
4628da255e2eSJames Smart 		if (datadir == DMA_TO_DEVICE) {
4629da255e2eSJames Smart 			iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
4630da255e2eSJames Smart 			iocb_cmd->ulpPU = PARM_READ_CHECK;
4631da255e2eSJames Smart 			if (vport->cfg_first_burst_size &&
4632da255e2eSJames Smart 			    (pnode->nlp_flag & NLP_FIRSTBURST)) {
4633da255e2eSJames Smart 				u32 xrdy_len;
4634da255e2eSJames Smart 
4635da255e2eSJames Smart 				fcpdl = scsi_bufflen(scsi_cmnd);
4636da255e2eSJames Smart 				xrdy_len = min(fcpdl,
4637da255e2eSJames Smart 					       vport->cfg_first_burst_size);
4638da255e2eSJames Smart 				piocbq->iocb.un.fcpi.fcpi_XRdy = xrdy_len;
46398b2564ecSAlexey Kardashevskiy 			}
4640da255e2eSJames Smart 			fcp_cmnd->fcpCntl3 = WRITE_DATA;
4641da255e2eSJames Smart 		} else {
4642da255e2eSJames Smart 			iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
4643da255e2eSJames Smart 			iocb_cmd->ulpPU = PARM_READ_CHECK;
4644da255e2eSJames Smart 			fcp_cmnd->fcpCntl3 = READ_DATA;
4645da255e2eSJames Smart 		}
4646da255e2eSJames Smart 	} else {
4647da255e2eSJames Smart 		iocb_cmd->ulpCommand = CMD_FCP_ICMND64_CR;
4648da255e2eSJames Smart 		iocb_cmd->un.fcpi.fcpi_parm = 0;
4649da255e2eSJames Smart 		iocb_cmd->ulpPU = 0;
4650da255e2eSJames Smart 		fcp_cmnd->fcpCntl3 = 0;
4651da255e2eSJames Smart 	}
4652da255e2eSJames Smart 
4653da255e2eSJames Smart 	/*
4654da255e2eSJames Smart 	 * Finish initializing those IOCB fields that are independent
4655da255e2eSJames Smart 	 * of the scsi_cmnd request_buffer
4656da255e2eSJames Smart 	 */
4657da255e2eSJames Smart 	piocbq->iocb.ulpContext = pnode->nlp_rpi;
4658da255e2eSJames Smart 	if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE)
4659da255e2eSJames Smart 		piocbq->iocb.ulpFCP2Rcvy = 1;
4660da255e2eSJames Smart 	else
4661da255e2eSJames Smart 		piocbq->iocb.ulpFCP2Rcvy = 0;
4662da255e2eSJames Smart 
4663da255e2eSJames Smart 	piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f);
4664d51cf5bdSJames Smart 	piocbq->io_buf  = lpfc_cmd;
4665a680a929SJames Smart 	if (!piocbq->cmd_cmpl)
4666a680a929SJames Smart 		piocbq->cmd_cmpl = lpfc_scsi_cmd_iocb_cmpl;
4667da255e2eSJames Smart 	piocbq->iocb.ulpTimeout = tmo;
4668da255e2eSJames Smart 	piocbq->vport = vport;
4669da255e2eSJames Smart 	return 0;
4670da255e2eSJames Smart }
4671da255e2eSJames Smart 
4672da255e2eSJames Smart /**
4673da255e2eSJames Smart  * lpfc_scsi_prep_cmnd_buf_s4 - SLI-4 WQE init for the IO
46740bb87e01SLee Jones  * @vport: Pointer to vport object.
4675da255e2eSJames Smart  * @lpfc_cmd: The scsi buffer which is going to be prep'ed.
4676da255e2eSJames Smart  * @tmo: timeout value for the IO
4677da255e2eSJames Smart  *
4678da255e2eSJames Smart  * Based on the data-direction of the command copy WQE template
4679da255e2eSJames Smart  * to I/O buffer WQE. Fill in the WQE fields which are independent
4680da255e2eSJames Smart  * of the scsi buffer
4681da255e2eSJames Smart  *
4682da255e2eSJames Smart  * RETURNS 0 - SUCCESS,
4683da255e2eSJames Smart  **/
lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,uint8_t tmo)4684da255e2eSJames Smart static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
4685da255e2eSJames Smart 				      struct lpfc_io_buf *lpfc_cmd,
4686da255e2eSJames Smart 				      uint8_t tmo)
4687da255e2eSJames Smart {
4688da255e2eSJames Smart 	struct lpfc_hba *phba = vport->phba;
4689da255e2eSJames Smart 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
4690da255e2eSJames Smart 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
4691da255e2eSJames Smart 	struct lpfc_sli4_hdw_queue *hdwq = NULL;
4692da255e2eSJames Smart 	struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq;
4693da255e2eSJames Smart 	struct lpfc_nodelist *pnode = lpfc_cmd->ndlp;
4694da255e2eSJames Smart 	union lpfc_wqe128 *wqe = &pwqeq->wqe;
4695da255e2eSJames Smart 	u16 idx = lpfc_cmd->hdwq_no;
4696da255e2eSJames Smart 	int datadir = scsi_cmnd->sc_data_direction;
4697da255e2eSJames Smart 
4698da255e2eSJames Smart 	hdwq = &phba->sli4_hba.hdwq[idx];
4699da255e2eSJames Smart 
4700da255e2eSJames Smart 	/* Initialize 64 bytes only */
4701da255e2eSJames Smart 	memset(wqe, 0, sizeof(union lpfc_wqe128));
4702da255e2eSJames Smart 
4703da255e2eSJames Smart 	/*
4704da255e2eSJames Smart 	 * There are three possibilities here - use scatter-gather segment, use
4705da255e2eSJames Smart 	 * the single mapping, or neither.
4706da255e2eSJames Smart 	 */
4707da255e2eSJames Smart 	if (scsi_sg_count(scsi_cmnd)) {
4708da255e2eSJames Smart 		if (datadir == DMA_TO_DEVICE) {
4709da255e2eSJames Smart 			/* From the iwrite template, initialize words 7 -  11 */
4710da255e2eSJames Smart 			memcpy(&wqe->words[7],
4711da255e2eSJames Smart 			       &lpfc_iwrite_cmd_template.words[7],
4712da255e2eSJames Smart 			       sizeof(uint32_t) * 5);
4713da255e2eSJames Smart 
4714da255e2eSJames Smart 			fcp_cmnd->fcpCntl3 = WRITE_DATA;
4715da255e2eSJames Smart 			if (hdwq)
4716da255e2eSJames Smart 				hdwq->scsi_cstat.output_requests++;
4717da255e2eSJames Smart 		} else {
4718da255e2eSJames Smart 			/* From the iread template, initialize words 7 - 11 */
4719da255e2eSJames Smart 			memcpy(&wqe->words[7],
4720da255e2eSJames Smart 			       &lpfc_iread_cmd_template.words[7],
4721da255e2eSJames Smart 			       sizeof(uint32_t) * 5);
4722da255e2eSJames Smart 
4723da255e2eSJames Smart 			/* Word 7 */
4724da255e2eSJames Smart 			bf_set(wqe_tmo, &wqe->fcp_iread.wqe_com, tmo);
4725da255e2eSJames Smart 
4726da255e2eSJames Smart 			fcp_cmnd->fcpCntl3 = READ_DATA;
4727da255e2eSJames Smart 			if (hdwq)
4728da255e2eSJames Smart 				hdwq->scsi_cstat.input_requests++;
472902243836SJames Smart 
473002243836SJames Smart 			/* For a CMF Managed port, iod must be zero'ed */
473102243836SJames Smart 			if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
473202243836SJames Smart 				bf_set(wqe_iod, &wqe->fcp_iread.wqe_com,
473302243836SJames Smart 				       LPFC_WQE_IOD_NONE);
4734da255e2eSJames Smart 		}
4735af20bb73SJustin Tee 
4736af20bb73SJustin Tee 		/* Additional fcp cdb length field calculation.
4737af20bb73SJustin Tee 		 * LPFC_FCP_CDB_LEN_32 - normal 16 byte cdb length,
4738af20bb73SJustin Tee 		 * then divide by 4 for the word count.
4739af20bb73SJustin Tee 		 * shift 2 because of the RDDATA/WRDATA.
4740af20bb73SJustin Tee 		 */
4741af20bb73SJustin Tee 		if (scsi_cmnd->cmd_len > LPFC_FCP_CDB_LEN)
4742af20bb73SJustin Tee 			fcp_cmnd->fcpCntl3 |= 4 << 2;
4743da255e2eSJames Smart 	} else {
4744da255e2eSJames Smart 		/* From the icmnd template, initialize words 4 - 11 */
4745da255e2eSJames Smart 		memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
4746da255e2eSJames Smart 		       sizeof(uint32_t) * 8);
4747da255e2eSJames Smart 
4748da255e2eSJames Smart 		/* Word 7 */
4749da255e2eSJames Smart 		bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, tmo);
4750da255e2eSJames Smart 
4751da255e2eSJames Smart 		fcp_cmnd->fcpCntl3 = 0;
4752da255e2eSJames Smart 		if (hdwq)
4753da255e2eSJames Smart 			hdwq->scsi_cstat.control_requests++;
4754da255e2eSJames Smart 	}
4755da255e2eSJames Smart 
4756da255e2eSJames Smart 	/*
4757da255e2eSJames Smart 	 * Finish initializing those WQE fields that are independent
4758da255e2eSJames Smart 	 * of the request_buffer
4759da255e2eSJames Smart 	 */
4760da255e2eSJames Smart 
4761da255e2eSJames Smart 	 /* Word 3 */
4762da255e2eSJames Smart 	bf_set(payload_offset_len, &wqe->fcp_icmd,
476305ab4e78SJustin Tee 	       sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
4764da255e2eSJames Smart 
4765da255e2eSJames Smart 	/* Word 6 */
4766da255e2eSJames Smart 	bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com,
4767da255e2eSJames Smart 	       phba->sli4_hba.rpi_ids[pnode->nlp_rpi]);
4768da255e2eSJames Smart 	bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag);
4769da255e2eSJames Smart 
4770da255e2eSJames Smart 	/* Word 7*/
4771da255e2eSJames Smart 	if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE)
4772da255e2eSJames Smart 		bf_set(wqe_erp, &wqe->generic.wqe_com, 1);
4773da255e2eSJames Smart 
4774da255e2eSJames Smart 	bf_set(wqe_class, &wqe->generic.wqe_com,
4775da255e2eSJames Smart 	       (pnode->nlp_fcp_info & 0x0f));
4776da255e2eSJames Smart 
4777da255e2eSJames Smart 	 /* Word 8 */
4778da255e2eSJames Smart 	wqe->generic.wqe_com.abort_tag = pwqeq->iotag;
4779da255e2eSJames Smart 
4780da255e2eSJames Smart 	/* Word 9 */
4781da255e2eSJames Smart 	bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag);
4782da255e2eSJames Smart 
4783da255e2eSJames Smart 	pwqeq->vport = vport;
4784d51cf5bdSJames Smart 	pwqeq->io_buf = lpfc_cmd;
4785da255e2eSJames Smart 	pwqeq->hba_wqidx = lpfc_cmd->hdwq_no;
4786a680a929SJames Smart 	pwqeq->cmd_cmpl = lpfc_fcp_io_cmd_wqe_cmpl;
4787da255e2eSJames Smart 
4788da255e2eSJames Smart 	return 0;
47898b2564ecSAlexey Kardashevskiy }
47908b2564ecSAlexey Kardashevskiy 
47918b2564ecSAlexey Kardashevskiy /**
4792f1126688SJames Smart  * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit
47939bad7671SJames Smart  * @vport: The virtual port for which this call is being executed.
47949bad7671SJames Smart  * @lpfc_cmd: The scsi command which needs to send.
47959bad7671SJames Smart  * @pnode: Pointer to lpfc_nodelist.
47969bad7671SJames Smart  *
47979bad7671SJames Smart  * This routine initializes fcp_cmnd and iocb data structure from scsi command
47983772a991SJames Smart  * to transfer for device with SLI3 interface spec.
47999bad7671SJames Smart  **/
4800da255e2eSJames Smart static int
lpfc_scsi_prep_cmnd(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,struct lpfc_nodelist * pnode)4801c490850aSJames Smart lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
4802dea3101eS 		    struct lpfc_nodelist *pnode)
4803dea3101eS {
4804dea3101eS 	struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
4805dea3101eS 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
4806da255e2eSJames Smart 	u8 *ptr;
4807dea3101eS 
4808307e3380SJames Smart 	if (!pnode)
4809da255e2eSJames Smart 		return 0;
481058da1ffbSJames Smart 
4811dea3101eS 	lpfc_cmd->fcp_rsp->rspSnsLen = 0;
481269859dc4SJames.Smart@Emulex.Com 	/* clear task management bits */
481369859dc4SJames.Smart@Emulex.Com 	lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
4814dea3101eS 
481591886523SJames.Smart@Emulex.Com 	int_to_scsilun(lpfc_cmd->pCmd->device->lun,
481691886523SJames.Smart@Emulex.Com 		       &lpfc_cmd->fcp_cmnd->fcp_lun);
4817dea3101eS 
4818af20bb73SJustin Tee 	ptr = &((struct fcp_cmnd32 *)fcp_cmnd)->fcpCdb[0];
4819027140eaSJames Smart 	memcpy(ptr, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
4820027140eaSJames Smart 	if (scsi_cmnd->cmd_len < LPFC_FCP_CDB_LEN) {
4821027140eaSJames Smart 		ptr += scsi_cmnd->cmd_len;
4822027140eaSJames Smart 		memset(ptr, 0, (LPFC_FCP_CDB_LEN - scsi_cmnd->cmd_len));
4823027140eaSJames Smart 	}
4824027140eaSJames Smart 
4825fe8f7f9cSJames Smart 	fcp_cmnd->fcpCntl1 = SIMPLE_Q;
4826dea3101eS 
4827da255e2eSJames Smart 	lpfc_scsi_prep_cmnd_buf(vport, lpfc_cmd, lpfc_cmd->timeout);
4828027140eaSJames Smart 
4829da255e2eSJames Smart 	return 0;
4830dea3101eS }
4831dea3101eS 
48329bad7671SJames Smart /**
48333512ac09SJames Smart  * lpfc_scsi_prep_task_mgmt_cmd_s3 - Convert SLI3 scsi TM cmd to FCP info unit
48349bad7671SJames Smart  * @vport: The virtual port for which this call is being executed.
4835c490850aSJames Smart  * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
48369bad7671SJames Smart  * @lun: Logical unit number.
48379bad7671SJames Smart  * @task_mgmt_cmd: SCSI task management command.
48389bad7671SJames Smart  *
48393772a991SJames Smart  * This routine creates FCP information unit corresponding to @task_mgmt_cmd
48403772a991SJames Smart  * for device with SLI-3 interface spec.
48419bad7671SJames Smart  *
48429bad7671SJames Smart  * Return codes:
48439bad7671SJames Smart  *   0 - Error
48449bad7671SJames Smart  *   1 - Success
48459bad7671SJames Smart  **/
4846dea3101eS static int
lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,u64 lun,u8 task_mgmt_cmd)48473512ac09SJames Smart lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport,
4848c490850aSJames Smart 				struct lpfc_io_buf *lpfc_cmd,
48493512ac09SJames Smart 				u64 lun, u8 task_mgmt_cmd)
4850dea3101eS {
4851dea3101eS 	struct lpfc_iocbq *piocbq;
4852dea3101eS 	IOCB_t *piocb;
4853dea3101eS 	struct fcp_cmnd *fcp_cmnd;
48540b18ac42SJames Smart 	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
4855dea3101eS 	struct lpfc_nodelist *ndlp = rdata->pnode;
4856dea3101eS 
4857307e3380SJames Smart 	if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE)
4858dea3101eS 		return 0;
4859dea3101eS 
4860dea3101eS 	piocbq = &(lpfc_cmd->cur_iocbq);
48612e0fef85SJames Smart 	piocbq->vport = vport;
48622e0fef85SJames Smart 
4863dea3101eS 	piocb = &piocbq->iocb;
4864dea3101eS 
4865dea3101eS 	fcp_cmnd = lpfc_cmd->fcp_cmnd;
486634b02dcdSJames Smart 	/* Clear out any old data in the FCP command area */
486734b02dcdSJames Smart 	memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
486834b02dcdSJames Smart 	int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
4869dea3101eS 	fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
48703512ac09SJames Smart 	if (!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED))
487134b02dcdSJames Smart 		lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd);
4872dea3101eS 	piocb->ulpCommand = CMD_FCP_ICMND64_CR;
4873dea3101eS 	piocb->ulpContext = ndlp->nlp_rpi;
487453151bbbSJames Smart 	piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0;
4875dea3101eS 	piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f);
4876f9226c20SJames Smart 	piocb->ulpPU = 0;
4877f9226c20SJames Smart 	piocb->un.fcpi.fcpi_parm = 0;
4878dea3101eS 
4879dea3101eS 	/* ulpTimeout is only one byte */
4880dea3101eS 	if (lpfc_cmd->timeout > 0xff) {
4881dea3101eS 		/*
4882dea3101eS 		 * Do not timeout the command at the firmware level.
4883dea3101eS 		 * The driver will provide the timeout mechanism.
4884dea3101eS 		 */
4885dea3101eS 		piocb->ulpTimeout = 0;
4886f1126688SJames Smart 	} else
4887dea3101eS 		piocb->ulpTimeout = lpfc_cmd->timeout;
4888f1126688SJames Smart 
48893512ac09SJames Smart 	return 1;
48903512ac09SJames Smart }
48913512ac09SJames Smart 
48923512ac09SJames Smart /**
48933512ac09SJames Smart  * lpfc_scsi_prep_task_mgmt_cmd_s4 - Convert SLI4 scsi TM cmd to FCP info unit
48943512ac09SJames Smart  * @vport: The virtual port for which this call is being executed.
48953512ac09SJames Smart  * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
48963512ac09SJames Smart  * @lun: Logical unit number.
48973512ac09SJames Smart  * @task_mgmt_cmd: SCSI task management command.
48983512ac09SJames Smart  *
48993512ac09SJames Smart  * This routine creates FCP information unit corresponding to @task_mgmt_cmd
49003512ac09SJames Smart  * for device with SLI-4 interface spec.
49013512ac09SJames Smart  *
49023512ac09SJames Smart  * Return codes:
49033512ac09SJames Smart  *   0 - Error
49043512ac09SJames Smart  *   1 - Success
49053512ac09SJames Smart  **/
49063512ac09SJames Smart static int
lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd,u64 lun,u8 task_mgmt_cmd)49073512ac09SJames Smart lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport,
49083512ac09SJames Smart 				struct lpfc_io_buf *lpfc_cmd,
49093512ac09SJames Smart 				u64 lun, u8 task_mgmt_cmd)
49103512ac09SJames Smart {
49113512ac09SJames Smart 	struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq;
49123512ac09SJames Smart 	union lpfc_wqe128 *wqe = &pwqeq->wqe;
49133512ac09SJames Smart 	struct fcp_cmnd *fcp_cmnd;
49143512ac09SJames Smart 	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
49153512ac09SJames Smart 	struct lpfc_nodelist *ndlp = rdata->pnode;
49163512ac09SJames Smart 
49173512ac09SJames Smart 	if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE)
49183512ac09SJames Smart 		return 0;
49193512ac09SJames Smart 
49203512ac09SJames Smart 	pwqeq->vport = vport;
49213512ac09SJames Smart 	/* Initialize 64 bytes only */
49223512ac09SJames Smart 	memset(wqe, 0, sizeof(union lpfc_wqe128));
49233512ac09SJames Smart 
49243512ac09SJames Smart 	/* From the icmnd template, initialize words 4 - 11 */
49253512ac09SJames Smart 	memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
49263512ac09SJames Smart 	       sizeof(uint32_t) * 8);
49273512ac09SJames Smart 
49283512ac09SJames Smart 	fcp_cmnd = lpfc_cmd->fcp_cmnd;
49293512ac09SJames Smart 	/* Clear out any old data in the FCP command area */
49303512ac09SJames Smart 	memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
49313512ac09SJames Smart 	int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
49323512ac09SJames Smart 	fcp_cmnd->fcpCntl3 = 0;
49333512ac09SJames Smart 	fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
49343512ac09SJames Smart 
49353512ac09SJames Smart 	bf_set(payload_offset_len, &wqe->fcp_icmd,
49363512ac09SJames Smart 	       sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
49373512ac09SJames Smart 	bf_set(cmd_buff_len, &wqe->fcp_icmd, 0);
49383512ac09SJames Smart 	bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com,  /* ulpContext */
49393512ac09SJames Smart 	       vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
49403512ac09SJames Smart 	bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com,
49413512ac09SJames Smart 	       ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0));
49423512ac09SJames Smart 	bf_set(wqe_class, &wqe->fcp_icmd.wqe_com,
49433512ac09SJames Smart 	       (ndlp->nlp_fcp_info & 0x0f));
49443512ac09SJames Smart 
49453512ac09SJames Smart 	/* ulpTimeout is only one byte */
49463512ac09SJames Smart 	if (lpfc_cmd->timeout > 0xff) {
49473512ac09SJames Smart 		/*
49483512ac09SJames Smart 		 * Do not timeout the command at the firmware level.
49493512ac09SJames Smart 		 * The driver will provide the timeout mechanism.
49503512ac09SJames Smart 		 */
49513512ac09SJames Smart 		bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, 0);
49523512ac09SJames Smart 	} else {
49533512ac09SJames Smart 		bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, lpfc_cmd->timeout);
49543512ac09SJames Smart 	}
49553512ac09SJames Smart 
49563512ac09SJames Smart 	lpfc_prep_embed_io(vport->phba, lpfc_cmd);
49573512ac09SJames Smart 	bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag);
49583512ac09SJames Smart 	wqe->generic.wqe_com.abort_tag = pwqeq->iotag;
49593512ac09SJames Smart 	bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag);
49603512ac09SJames Smart 
4961f1126688SJames Smart 	lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd);
4962dea3101eS 
49632e0fef85SJames Smart 	return 1;
4964dea3101eS }
4965dea3101eS 
49669bad7671SJames Smart /**
496725985edcSLucas De Marchi  * lpfc_scsi_api_table_setup - Set up scsi api function jump table
49683772a991SJames Smart  * @phba: The hba struct for which this call is being executed.
49693772a991SJames Smart  * @dev_grp: The HBA PCI-Device group number.
49703772a991SJames Smart  *
49713772a991SJames Smart  * This routine sets up the SCSI interface API function jump table in @phba
49723772a991SJames Smart  * struct.
49733772a991SJames Smart  * Returns: 0 - success, -ENODEV - failure.
49743772a991SJames Smart  **/
49753772a991SJames Smart int
lpfc_scsi_api_table_setup(struct lpfc_hba * phba,uint8_t dev_grp)49763772a991SJames Smart lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
49773772a991SJames Smart {
49783772a991SJames Smart 
4979f1126688SJames Smart 	phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf;
4980f1126688SJames Smart 
49813772a991SJames Smart 	switch (dev_grp) {
49823772a991SJames Smart 	case LPFC_PCI_DEV_LP:
49833772a991SJames Smart 		phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3;
4984acd6859bSJames Smart 		phba->lpfc_bg_scsi_prep_dma_buf = lpfc_bg_scsi_prep_dma_buf_s3;
49853772a991SJames Smart 		phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
498619ca7609SJames Smart 		phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3;
4987da255e2eSJames Smart 		phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3;
49883512ac09SJames Smart 		phba->lpfc_scsi_prep_task_mgmt_cmd =
49893512ac09SJames Smart 					lpfc_scsi_prep_task_mgmt_cmd_s3;
49903772a991SJames Smart 		break;
4991da0436e9SJames Smart 	case LPFC_PCI_DEV_OC:
4992da0436e9SJames Smart 		phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
4993acd6859bSJames Smart 		phba->lpfc_bg_scsi_prep_dma_buf = lpfc_bg_scsi_prep_dma_buf_s4;
4994da0436e9SJames Smart 		phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
499519ca7609SJames Smart 		phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4;
4996da255e2eSJames Smart 		phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4;
49973512ac09SJames Smart 		phba->lpfc_scsi_prep_task_mgmt_cmd =
49983512ac09SJames Smart 					lpfc_scsi_prep_task_mgmt_cmd_s4;
4999da0436e9SJames Smart 		break;
50003772a991SJames Smart 	default:
5001a516074cSJames Smart 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
50023772a991SJames Smart 				"1418 Invalid HBA PCI-device group: 0x%x\n",
50033772a991SJames Smart 				dev_grp);
50043772a991SJames Smart 		return -ENODEV;
50053772a991SJames Smart 	}
50063772a991SJames Smart 	phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth;
50073772a991SJames Smart 	return 0;
50083772a991SJames Smart }
50093772a991SJames Smart 
50103772a991SJames Smart /**
50110bb87e01SLee Jones  * lpfc_tskmgmt_def_cmpl - IOCB completion routine for task management command
50129bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
50139bad7671SJames Smart  * @cmdiocbq: Pointer to lpfc_iocbq data structure.
50149bad7671SJames Smart  * @rspiocbq: Pointer to lpfc_iocbq data structure.
50159bad7671SJames Smart  *
50169bad7671SJames Smart  * This routine is IOCB completion routine for device reset and target reset
50179bad7671SJames Smart  * routine. This routine release scsi buffer associated with lpfc_cmd.
50189bad7671SJames Smart  **/
50197054a606SJames Smart static void
lpfc_tskmgmt_def_cmpl(struct lpfc_hba * phba,struct lpfc_iocbq * cmdiocbq,struct lpfc_iocbq * rspiocbq)50207054a606SJames Smart lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
50217054a606SJames Smart 			struct lpfc_iocbq *cmdiocbq,
50227054a606SJames Smart 			struct lpfc_iocbq *rspiocbq)
50237054a606SJames Smart {
5024d51cf5bdSJames Smart 	struct lpfc_io_buf *lpfc_cmd = cmdiocbq->io_buf;
50257054a606SJames Smart 	if (lpfc_cmd)
50267054a606SJames Smart 		lpfc_release_scsi_buf(phba, lpfc_cmd);
50277054a606SJames Smart 	return;
50287054a606SJames Smart }
50297054a606SJames Smart 
50309bad7671SJames Smart /**
50315021267aSJames Smart  * lpfc_check_pci_resettable - Walks list of devices on pci_dev's bus to check
50325021267aSJames Smart  *                             if issuing a pci_bus_reset is possibly unsafe
50335021267aSJames Smart  * @phba: lpfc_hba pointer.
50345021267aSJames Smart  *
50355021267aSJames Smart  * Description:
50365021267aSJames Smart  * Walks the bus_list to ensure only PCI devices with Emulex
50375021267aSJames Smart  * vendor id, device ids that support hot reset, and only one occurrence
50385021267aSJames Smart  * of function 0.
50395021267aSJames Smart  *
50405021267aSJames Smart  * Returns:
50415021267aSJames Smart  * -EBADSLT,  detected invalid device
50425021267aSJames Smart  *      0,    successful
50435021267aSJames Smart  */
50445021267aSJames Smart int
lpfc_check_pci_resettable(struct lpfc_hba * phba)5045372c187bSDick Kennedy lpfc_check_pci_resettable(struct lpfc_hba *phba)
50465021267aSJames Smart {
50475021267aSJames Smart 	const struct pci_dev *pdev = phba->pcidev;
50485021267aSJames Smart 	struct pci_dev *ptr = NULL;
50495021267aSJames Smart 	u8 counter = 0;
50505021267aSJames Smart 
50515021267aSJames Smart 	/* Walk the list of devices on the pci_dev's bus */
50525021267aSJames Smart 	list_for_each_entry(ptr, &pdev->bus->devices, bus_list) {
50535021267aSJames Smart 		/* Check for Emulex Vendor ID */
50545021267aSJames Smart 		if (ptr->vendor != PCI_VENDOR_ID_EMULEX) {
50555021267aSJames Smart 			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
50565021267aSJames Smart 					"8346 Non-Emulex vendor found: "
50575021267aSJames Smart 					"0x%04x\n", ptr->vendor);
50585021267aSJames Smart 			return -EBADSLT;
50595021267aSJames Smart 		}
50605021267aSJames Smart 
50615021267aSJames Smart 		/* Check for valid Emulex Device ID */
5062f6c5e6c4SJames Smart 		if (phba->sli_rev != LPFC_SLI_REV4 ||
5063e780c942SJustin Tee 		    test_bit(HBA_FCOE_MODE, &phba->hba_flag)) {
50645021267aSJames Smart 			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
5065a94a40ebSJames Smart 					"8347 Incapable PCI reset device: "
50665021267aSJames Smart 					"0x%04x\n", ptr->device);
50675021267aSJames Smart 			return -EBADSLT;
50685021267aSJames Smart 		}
50695021267aSJames Smart 
50705021267aSJames Smart 		/* Check for only one function 0 ID to ensure only one HBA on
50715021267aSJames Smart 		 * secondary bus
50725021267aSJames Smart 		 */
50735021267aSJames Smart 		if (ptr->devfn == 0) {
50745021267aSJames Smart 			if (++counter > 1) {
50755021267aSJames Smart 				lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
50765021267aSJames Smart 						"8348 More than one device on "
50775021267aSJames Smart 						"secondary bus found\n");
50785021267aSJames Smart 				return -EBADSLT;
50795021267aSJames Smart 			}
50805021267aSJames Smart 		}
50815021267aSJames Smart 	}
50825021267aSJames Smart 
50835021267aSJames Smart 	return 0;
50845021267aSJames Smart }
50855021267aSJames Smart 
50865021267aSJames Smart /**
50873621a710SJames Smart  * lpfc_info - Info entry point of scsi_host_template data structure
50889bad7671SJames Smart  * @host: The scsi host for which this call is being executed.
50899bad7671SJames Smart  *
50909bad7671SJames Smart  * This routine provides module information about hba.
50919bad7671SJames Smart  *
50929bad7671SJames Smart  * Reutrn code:
50939bad7671SJames Smart  *   Pointer to char - Success.
50949bad7671SJames Smart  **/
5095dea3101eS const char *
lpfc_info(struct Scsi_Host * host)5096dea3101eS lpfc_info(struct Scsi_Host *host)
5097dea3101eS {
50982e0fef85SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) host->hostdata;
50992e0fef85SJames Smart 	struct lpfc_hba   *phba = vport->phba;
51005021267aSJames Smart 	int link_speed = 0;
5101dea3101eS 	static char lpfcinfobuf[384];
51025021267aSJames Smart 	char tmp[384] = {0};
5103dea3101eS 
51045021267aSJames Smart 	memset(lpfcinfobuf, 0, sizeof(lpfcinfobuf));
5105dea3101eS 	if (phba && phba->pcidev){
51065021267aSJames Smart 		/* Model Description */
51075021267aSJames Smart 		scnprintf(tmp, sizeof(tmp), phba->ModelDesc);
51085021267aSJames Smart 		if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
51095021267aSJames Smart 		    sizeof(lpfcinfobuf))
51105021267aSJames Smart 			goto buffer_done;
51115021267aSJames Smart 
51125021267aSJames Smart 		/* PCI Info */
51135021267aSJames Smart 		scnprintf(tmp, sizeof(tmp),
5114dea3101eS 			  " on PCI bus %02x device %02x irq %d",
51155021267aSJames Smart 			  phba->pcidev->bus->number, phba->pcidev->devfn,
5116dea3101eS 			  phba->pcidev->irq);
51175021267aSJames Smart 		if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
51185021267aSJames Smart 		    sizeof(lpfcinfobuf))
51195021267aSJames Smart 			goto buffer_done;
51205021267aSJames Smart 
51215021267aSJames Smart 		/* Port Number */
5122dea3101eS 		if (phba->Port[0]) {
51235021267aSJames Smart 			scnprintf(tmp, sizeof(tmp), " port %s", phba->Port);
51245021267aSJames Smart 			if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
51255021267aSJames Smart 			    sizeof(lpfcinfobuf))
51265021267aSJames Smart 				goto buffer_done;
5127dea3101eS 		}
51285021267aSJames Smart 
51295021267aSJames Smart 		/* Link Speed */
51308b68cd52SJames Smart 		link_speed = lpfc_sli_port_speed_get(phba);
51315021267aSJames Smart 		if (link_speed != 0) {
51325021267aSJames Smart 			scnprintf(tmp, sizeof(tmp),
51338b68cd52SJames Smart 				  " Logical Link Speed: %d Mbps", link_speed);
51345021267aSJames Smart 			if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
51355021267aSJames Smart 			    sizeof(lpfcinfobuf))
51365021267aSJames Smart 				goto buffer_done;
5137dea3101eS 		}
51385021267aSJames Smart 
51395021267aSJames Smart 		/* PCI resettable */
51405021267aSJames Smart 		if (!lpfc_check_pci_resettable(phba)) {
51415021267aSJames Smart 			scnprintf(tmp, sizeof(tmp), " PCI resettable");
51425021267aSJames Smart 			strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf));
51435021267aSJames Smart 		}
51445021267aSJames Smart 	}
51455021267aSJames Smart 
51465021267aSJames Smart buffer_done:
5147dea3101eS 	return lpfcinfobuf;
5148dea3101eS }
5149dea3101eS 
51509bad7671SJames Smart /**
51510bb87e01SLee Jones  * lpfc_poll_rearm_timer - Routine to modify fcp_poll timer of hba
51529bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
51539bad7671SJames Smart  *
51549bad7671SJames Smart  * This routine modifies fcp_poll_timer  field of @phba by cfg_poll_tmo.
51559bad7671SJames Smart  * The default value of cfg_poll_tmo is 10 milliseconds.
51569bad7671SJames Smart  **/
lpfc_poll_rearm_timer(struct lpfc_hba * phba)5157875fbdfeSJames.Smart@Emulex.Com static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
5158875fbdfeSJames.Smart@Emulex.Com {
5159875fbdfeSJames.Smart@Emulex.Com 	unsigned long  poll_tmo_expires =
5160875fbdfeSJames.Smart@Emulex.Com 		(jiffies + msecs_to_jiffies(phba->cfg_poll_tmo));
5161875fbdfeSJames.Smart@Emulex.Com 
5162895427bdSJames Smart 	if (!list_empty(&phba->sli.sli3_ring[LPFC_FCP_RING].txcmplq))
5163875fbdfeSJames.Smart@Emulex.Com 		mod_timer(&phba->fcp_poll_timer,
5164875fbdfeSJames.Smart@Emulex.Com 			  poll_tmo_expires);
5165875fbdfeSJames.Smart@Emulex.Com }
5166875fbdfeSJames.Smart@Emulex.Com 
51679bad7671SJames Smart /**
51683621a710SJames Smart  * lpfc_poll_start_timer - Routine to start fcp_poll_timer of HBA
51699bad7671SJames Smart  * @phba: The Hba for which this call is being executed.
51709bad7671SJames Smart  *
51719bad7671SJames Smart  * This routine starts the fcp_poll_timer of @phba.
51729bad7671SJames Smart  **/
lpfc_poll_start_timer(struct lpfc_hba * phba)5173875fbdfeSJames.Smart@Emulex.Com void lpfc_poll_start_timer(struct lpfc_hba * phba)
5174875fbdfeSJames.Smart@Emulex.Com {
5175875fbdfeSJames.Smart@Emulex.Com 	lpfc_poll_rearm_timer(phba);
5176875fbdfeSJames.Smart@Emulex.Com }
5177875fbdfeSJames.Smart@Emulex.Com 
51789bad7671SJames Smart /**
51793621a710SJames Smart  * lpfc_poll_timeout - Restart polling timer
5180eceee00eSLee Jones  * @t: Timer construct where lpfc_hba data structure pointer is obtained.
51819bad7671SJames Smart  *
51829bad7671SJames Smart  * This routine restarts fcp_poll timer, when FCP ring  polling is enable
51839bad7671SJames Smart  * and FCP Ring interrupt is disable.
51849bad7671SJames Smart  **/
lpfc_poll_timeout(struct timer_list * t)5185f22eb4d3SKees Cook void lpfc_poll_timeout(struct timer_list *t)
5186875fbdfeSJames.Smart@Emulex.Com {
5187f22eb4d3SKees Cook 	struct lpfc_hba *phba = from_timer(phba, t, fcp_poll_timer);
5188875fbdfeSJames.Smart@Emulex.Com 
5189875fbdfeSJames.Smart@Emulex.Com 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
519045ed1190SJames Smart 		lpfc_sli_handle_fast_ring_event(phba,
5191895427bdSJames Smart 			&phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ);
519245ed1190SJames Smart 
5193875fbdfeSJames.Smart@Emulex.Com 		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
5194875fbdfeSJames.Smart@Emulex.Com 			lpfc_poll_rearm_timer(phba);
5195875fbdfeSJames.Smart@Emulex.Com 	}
5196875fbdfeSJames.Smart@Emulex.Com }
5197875fbdfeSJames.Smart@Emulex.Com 
5198dc50715eSGaurav Srivastava /*
519933c79741SGaurav Srivastava  * lpfc_is_command_vm_io - get the UUID from blk cgroup
520033c79741SGaurav Srivastava  * @cmd: Pointer to scsi_cmnd data structure
520133c79741SGaurav Srivastava  * Returns UUID if present, otherwise NULL
520233c79741SGaurav Srivastava  */
lpfc_is_command_vm_io(struct scsi_cmnd * cmd)520333c79741SGaurav Srivastava static char *lpfc_is_command_vm_io(struct scsi_cmnd *cmd)
520433c79741SGaurav Srivastava {
52054221c8a4SBart Van Assche 	struct bio *bio = scsi_cmd_to_rq(cmd)->bio;
520633c79741SGaurav Srivastava 
5207db056284SChristoph Hellwig 	if (!IS_ENABLED(CONFIG_BLK_CGROUP_FC_APPID) || !bio)
5208db056284SChristoph Hellwig 		return NULL;
5209db056284SChristoph Hellwig 	return blkcg_get_fc_appid(bio);
521033c79741SGaurav Srivastava }
521133c79741SGaurav Srivastava 
52129bad7671SJames Smart /**
52133621a710SJames Smart  * lpfc_queuecommand - scsi_host_template queuecommand entry point
5214eceee00eSLee Jones  * @shost: kernel scsi host pointer.
52159bad7671SJames Smart  * @cmnd: Pointer to scsi_cmnd data structure.
52169bad7671SJames Smart  *
52179bad7671SJames Smart  * Driver registers this routine to scsi midlayer to submit a @cmd to process.
52189bad7671SJames Smart  * This routine prepares an IOCB from scsi command and provides to firmware.
52199bad7671SJames Smart  * The @done callback is invoked after driver finished processing the command.
52209bad7671SJames Smart  *
52219bad7671SJames Smart  * Return value :
52229bad7671SJames Smart  *   0 - Success
52239bad7671SJames Smart  *   SCSI_MLQUEUE_HOST_BUSY - Block all devices served by this host temporarily.
52249bad7671SJames Smart  **/
5225dea3101eS static int
lpfc_queuecommand(struct Scsi_Host * shost,struct scsi_cmnd * cmnd)5226b9a7c631SJames Smart lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
5227dea3101eS {
52282e0fef85SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
52292e0fef85SJames Smart 	struct lpfc_hba   *phba = vport->phba;
52303512ac09SJames Smart 	struct lpfc_iocbq *cur_iocbq = NULL;
52311ba981fdSJames Smart 	struct lpfc_rport_data *rdata;
52321c6f4ef5SJames Smart 	struct lpfc_nodelist *ndlp;
5233c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd;
523419a7b4aeSJames.Smart@Emulex.Com 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
52354c47efc1SJames Smart 	int err, idx;
523666b4d63bSJames Smart 	u8 *uuid = NULL;
523737e38409SJames Smart 	uint64_t start;
52382fcbc569SJames Smart 
523902243836SJames Smart 	start = ktime_get_ns();
52401ba981fdSJames Smart 	rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
5241b0e83012SJames Smart 
5242b0e83012SJames Smart 	/* sanity check on references */
5243b0e83012SJames Smart 	if (unlikely(!rdata) || unlikely(!rport))
5244b0e83012SJames Smart 		goto out_fail_command;
5245b0e83012SJames Smart 
524619a7b4aeSJames.Smart@Emulex.Com 	err = fc_remote_port_chkready(rport);
524719a7b4aeSJames.Smart@Emulex.Com 	if (err) {
524819a7b4aeSJames.Smart@Emulex.Com 		cmnd->result = err;
524919a7b4aeSJames.Smart@Emulex.Com 		goto out_fail_command;
525019a7b4aeSJames.Smart@Emulex.Com 	}
52511c6f4ef5SJames Smart 	ndlp = rdata->pnode;
5252dea3101eS 
5253bf08611bSJames Smart 	if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) &&
5254acd6859bSJames Smart 		(!(phba->sli3_options & LPFC_SLI3_BG_ENABLED))) {
5255e2a0a9d6SJames Smart 
5256372c187bSDick Kennedy 		lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
52576a9c52cfSJames Smart 				"9058 BLKGRD: ERROR: rcvd protected cmd:%02x"
52586a9c52cfSJames Smart 				" op:%02x str=%s without registering for"
52596a9c52cfSJames Smart 				" BlockGuard - Rejecting command\n",
5260e2a0a9d6SJames Smart 				cmnd->cmnd[0], scsi_get_prot_op(cmnd),
5261e2a0a9d6SJames Smart 				dif_op_str[scsi_get_prot_op(cmnd)]);
5262e2a0a9d6SJames Smart 		goto out_fail_command;
5263e2a0a9d6SJames Smart 	}
5264e2a0a9d6SJames Smart 
5265dea3101eS 	/*
526619a7b4aeSJames.Smart@Emulex.Com 	 * Catch race where our node has transitioned, but the
526719a7b4aeSJames.Smart@Emulex.Com 	 * transport is still transitioning.
5268dea3101eS 	 */
5269307e3380SJames Smart 	if (!ndlp)
527002243836SJames Smart 		goto out_tgt_busy1;
527102243836SJames Smart 
527202243836SJames Smart 	/* Check if IO qualifies for CMF */
527302243836SJames Smart 	if (phba->cmf_active_mode != LPFC_CFG_OFF &&
527402243836SJames Smart 	    cmnd->sc_data_direction == DMA_FROM_DEVICE &&
527502243836SJames Smart 	    (scsi_sg_count(cmnd))) {
527602243836SJames Smart 		/* Latency start time saved in rx_cmd_start later in routine */
527702243836SJames Smart 		err = lpfc_update_cmf_cmd(phba, scsi_bufflen(cmnd));
527802243836SJames Smart 		if (err)
527902243836SJames Smart 			goto out_tgt_busy1;
528002243836SJames Smart 	}
528102243836SJames Smart 
52822a5b7d62SJames Smart 	if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
528364bf0099SJames Smart 		if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) {
528464bf0099SJames Smart 			lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR,
52852a5b7d62SJames Smart 					 "3377 Target Queue Full, scsi Id:%d "
52862a5b7d62SJames Smart 					 "Qdepth:%d Pending command:%d"
52872a5b7d62SJames Smart 					 " WWNN:%02x:%02x:%02x:%02x:"
52882a5b7d62SJames Smart 					 "%02x:%02x:%02x:%02x, "
52892a5b7d62SJames Smart 					 " WWPN:%02x:%02x:%02x:%02x:"
52902a5b7d62SJames Smart 					 "%02x:%02x:%02x:%02x",
529164bf0099SJames Smart 					 ndlp->nlp_sid, ndlp->cmd_qdepth,
529264bf0099SJames Smart 					 atomic_read(&ndlp->cmd_pending),
529364bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[0],
529464bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[1],
529564bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[2],
529664bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[3],
529764bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[4],
529864bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[5],
529964bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[6],
530064bf0099SJames Smart 					 ndlp->nlp_nodename.u.wwn[7],
530164bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[0],
530264bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[1],
530364bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[2],
530464bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[3],
530564bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[4],
530664bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[5],
530764bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[6],
530864bf0099SJames Smart 					 ndlp->nlp_portname.u.wwn[7]);
530902243836SJames Smart 			goto out_tgt_busy2;
531064bf0099SJames Smart 		}
53112a5b7d62SJames Smart 	}
5312f91bc594SJames Smart 
5313ace44e48SJames Smart 	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp, cmnd);
5314dea3101eS 	if (lpfc_cmd == NULL) {
5315eaf15d5bSJames Smart 		lpfc_rampdown_queue_depth(phba);
531692d7f7b0SJames Smart 
5317895427bdSJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR,
5318e8b62011SJames Smart 				 "0707 driver's buffer pool is empty, "
5319e8b62011SJames Smart 				 "IO busied\n");
5320dea3101eS 		goto out_host_busy;
5321dea3101eS 	}
532202243836SJames Smart 	lpfc_cmd->rx_cmd_start = start;
5323dea3101eS 
53243512ac09SJames Smart 	cur_iocbq = &lpfc_cmd->cur_iocbq;
5325dea3101eS 	/*
5326dea3101eS 	 * Store the midlayer's command structure for the completion phase
5327dea3101eS 	 * and complete the command initialization.
5328dea3101eS 	 */
5329dea3101eS 	lpfc_cmd->pCmd  = cmnd;
5330dea3101eS 	lpfc_cmd->rdata = rdata;
53312a5b7d62SJames Smart 	lpfc_cmd->ndlp = ndlp;
53323512ac09SJames Smart 	cur_iocbq->cmd_cmpl = NULL;
5333dea3101eS 	cmnd->host_scribble = (unsigned char *)lpfc_cmd;
5334dea3101eS 
5335da255e2eSJames Smart 	err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
5336da255e2eSJames Smart 	if (err)
5337da255e2eSJames Smart 		goto out_host_busy_release_buf;
5338da255e2eSJames Smart 
5339e2a0a9d6SJames Smart 	if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
53406a9c52cfSJames Smart 		if (vport->phba->cfg_enable_bg) {
5341737d4248SJames Smart 			lpfc_printf_vlog(vport,
5342737d4248SJames Smart 					 KERN_INFO, LOG_SCSI_CMD,
53432613470aSJames Smart 					 "9033 BLKGRD: rcvd %s cmd:x%x "
534468a6a66cSJames Smart 					 "reftag x%x cnt %u pt %x\n",
53459a6b09c0SJames Smart 					 dif_op_str[scsi_get_prot_op(cmnd)],
53462613470aSJames Smart 					 cmnd->cmnd[0],
5347125c12f7SMartin K. Petersen 					 scsi_prot_ref_tag(cmnd),
5348125c12f7SMartin K. Petersen 					 scsi_logical_block_count(cmnd),
534918f7761dSJustin Tee 					 scsi_get_prot_type(cmnd));
53506a9c52cfSJames Smart 		}
5351e2a0a9d6SJames Smart 		err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd);
5352e2a0a9d6SJames Smart 	} else {
5353dea3101eS 		err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd);
5354e2a0a9d6SJames Smart 	}
5355e2a0a9d6SJames Smart 
535622770cbaSJames Smart 	if (unlikely(err)) {
53575e0e2318SJames Smart 		if (err == 2) {
53585e0e2318SJames Smart 			cmnd->result = DID_ERROR << 16;
53595e0e2318SJames Smart 			goto out_fail_command_release_buf;
536022770cbaSJames Smart 		}
5361dea3101eS 		goto out_host_busy_free_buf;
53625e0e2318SJames Smart 	}
5363dea3101eS 
536433c79741SGaurav Srivastava 	/* check the necessary and sufficient condition to support VMID */
536533c79741SGaurav Srivastava 	if (lpfc_is_vmid_enabled(phba) &&
536633c79741SGaurav Srivastava 	    (ndlp->vmid_support ||
536733c79741SGaurav Srivastava 	     phba->pport->vmid_priority_tagging ==
536833c79741SGaurav Srivastava 	     LPFC_VMID_PRIO_TAG_ALL_TARGETS)) {
536933c79741SGaurav Srivastava 		/* is the I/O generated by a VM, get the associated virtual */
537033c79741SGaurav Srivastava 		/* entity id */
537133c79741SGaurav Srivastava 		uuid = lpfc_is_command_vm_io(cmnd);
537233c79741SGaurav Srivastava 
537333c79741SGaurav Srivastava 		if (uuid) {
5374348efecaSJames Smart 			err = lpfc_vmid_get_appid(vport, uuid,
5375348efecaSJames Smart 					cmnd->sc_data_direction,
537633c79741SGaurav Srivastava 					(union lpfc_vmid_io_tag *)
53773512ac09SJames Smart 						&cur_iocbq->vmid_tag);
537833c79741SGaurav Srivastava 			if (!err)
53793512ac09SJames Smart 				cur_iocbq->cmd_flag |= LPFC_IO_VMID;
538033c79741SGaurav Srivastava 		}
538133c79741SGaurav Srivastava 	}
53823512ac09SJames Smart 
53836a828b0fSJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
5384840eda96SJames Smart 	if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
5385840eda96SJames Smart 		this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);
53866a828b0fSJames Smart #endif
538747ff4c51SJames Smart 	/* Issue I/O to adapter */
53883512ac09SJames Smart 	err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, cur_iocbq,
538947ff4c51SJames Smart 				    SLI_IOCB_RET_IOCB);
53902fcbc569SJames Smart #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
53912fcbc569SJames Smart 	if (start) {
53922fcbc569SJames Smart 		lpfc_cmd->ts_cmd_start = start;
53932fcbc569SJames Smart 		lpfc_cmd->ts_last_cmd = phba->ktime_last_cmd;
53942fcbc569SJames Smart 		lpfc_cmd->ts_cmd_wqput = ktime_get_ns();
53952fcbc569SJames Smart 	} else {
53962fcbc569SJames Smart 		lpfc_cmd->ts_cmd_start = 0;
53972fcbc569SJames Smart 	}
53982fcbc569SJames Smart #endif
5399eaf15d5bSJames Smart 	if (err) {
540076f96b6dSJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
54013512ac09SJames Smart 				 "3376 FCP could not issue iocb err %x "
54029cb78c16SHannes Reinecke 				 "FCP cmd x%x <%d/%llu> "
540376f96b6dSJames Smart 				 "sid: x%x did: x%x oxid: x%x "
540476f96b6dSJames Smart 				 "Data: x%x x%x x%x x%x\n",
540576f96b6dSJames Smart 				 err, cmnd->cmnd[0],
540676f96b6dSJames Smart 				 cmnd->device ? cmnd->device->id : 0xffff,
54079cb78c16SHannes Reinecke 				 cmnd->device ? cmnd->device->lun : (u64)-1,
540876f96b6dSJames Smart 				 vport->fc_myDID, ndlp->nlp_DID,
540976f96b6dSJames Smart 				 phba->sli_rev == LPFC_SLI_REV4 ?
54103512ac09SJames Smart 				 cur_iocbq->sli4_xritag : 0xffff,
5411da255e2eSJames Smart 				 phba->sli_rev == LPFC_SLI_REV4 ?
5412da255e2eSJames Smart 				 phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] :
54133512ac09SJames Smart 				 cur_iocbq->iocb.ulpContext,
54143512ac09SJames Smart 				 cur_iocbq->iotag,
5415da255e2eSJames Smart 				 phba->sli_rev == LPFC_SLI_REV4 ?
5416da255e2eSJames Smart 				 bf_get(wqe_tmo,
54173512ac09SJames Smart 					&cur_iocbq->wqe.generic.wqe_com) :
54183512ac09SJames Smart 				 cur_iocbq->iocb.ulpTimeout,
54194221c8a4SBart Van Assche 				 (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000));
542076f96b6dSJames Smart 
5421dea3101eS 		goto out_host_busy_free_buf;
5422eaf15d5bSJames Smart 	}
5423da255e2eSJames Smart 
5424875fbdfeSJames.Smart@Emulex.Com 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
542545ed1190SJames Smart 		lpfc_sli_handle_fast_ring_event(phba,
5426895427bdSJames Smart 			&phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ);
542745ed1190SJames Smart 
5428875fbdfeSJames.Smart@Emulex.Com 		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
5429875fbdfeSJames.Smart@Emulex.Com 			lpfc_poll_rearm_timer(phba);
5430875fbdfeSJames.Smart@Emulex.Com 	}
5431875fbdfeSJames.Smart@Emulex.Com 
5432c490850aSJames Smart 	if (phba->cfg_xri_rebalancing)
5433c490850aSJames Smart 		lpfc_keep_pvt_pool_above_lowwm(phba, lpfc_cmd->hdwq_no);
5434c490850aSJames Smart 
5435dea3101eS 	return 0;
5436dea3101eS 
5437dea3101eS  out_host_busy_free_buf:
54381fbf9742SJames Smart 	idx = lpfc_cmd->hdwq_no;
5439bcf4dbfaSJames Smart 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
54404c47efc1SJames Smart 	if (phba->sli4_hba.hdwq) {
54414c47efc1SJames Smart 		switch (lpfc_cmd->fcp_cmnd->fcpCntl3) {
54424c47efc1SJames Smart 		case WRITE_DATA:
54434c47efc1SJames Smart 			phba->sli4_hba.hdwq[idx].scsi_cstat.output_requests--;
54444c47efc1SJames Smart 			break;
54454c47efc1SJames Smart 		case READ_DATA:
54464c47efc1SJames Smart 			phba->sli4_hba.hdwq[idx].scsi_cstat.input_requests--;
54474c47efc1SJames Smart 			break;
54484c47efc1SJames Smart 		default:
54494c47efc1SJames Smart 			phba->sli4_hba.hdwq[idx].scsi_cstat.control_requests--;
54504c47efc1SJames Smart 		}
54514c47efc1SJames Smart 	}
5452da255e2eSJames Smart  out_host_busy_release_buf:
54530bd4ca25SJames.Smart@Emulex.Com 	lpfc_release_scsi_buf(phba, lpfc_cmd);
5454dea3101eS  out_host_busy:
545502243836SJames Smart 	lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT, scsi_bufflen(cmnd),
545602243836SJames Smart 			     shost);
5457dea3101eS 	return SCSI_MLQUEUE_HOST_BUSY;
5458dea3101eS 
545902243836SJames Smart  out_tgt_busy2:
546002243836SJames Smart 	lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT, scsi_bufflen(cmnd),
546102243836SJames Smart 			     shost);
546202243836SJames Smart  out_tgt_busy1:
54633496343dSMike Christie 	return SCSI_MLQUEUE_TARGET_BUSY;
54643496343dSMike Christie 
54655e0e2318SJames Smart  out_fail_command_release_buf:
54665e0e2318SJames Smart 	lpfc_release_scsi_buf(phba, lpfc_cmd);
546702243836SJames Smart 	lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT, scsi_bufflen(cmnd),
546802243836SJames Smart 			     shost);
54695e0e2318SJames Smart 
5470dea3101eS  out_fail_command:
5471ca068c2cSBart Van Assche 	scsi_done(cmnd);
5472dea3101eS 	return 0;
5473dea3101eS }
5474dea3101eS 
54755e633302SGaurav Srivastava /*
54765e633302SGaurav Srivastava  * lpfc_vmid_vport_cleanup - cleans up the resources associated with a vport
54775e633302SGaurav Srivastava  * @vport: The virtual port for which this call is being executed.
54785e633302SGaurav Srivastava  */
lpfc_vmid_vport_cleanup(struct lpfc_vport * vport)54795e633302SGaurav Srivastava void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport)
54805e633302SGaurav Srivastava {
54815e633302SGaurav Srivastava 	u32 bucket;
54825e633302SGaurav Srivastava 	struct lpfc_vmid *cur;
54835e633302SGaurav Srivastava 
54845e633302SGaurav Srivastava 	if (vport->port_type == LPFC_PHYSICAL_PORT)
54855e633302SGaurav Srivastava 		del_timer_sync(&vport->phba->inactive_vmid_poll);
54865e633302SGaurav Srivastava 
54875e633302SGaurav Srivastava 	kfree(vport->qfpa_res);
54885e633302SGaurav Srivastava 	kfree(vport->vmid_priority.vmid_range);
54895e633302SGaurav Srivastava 	kfree(vport->vmid);
54905e633302SGaurav Srivastava 
54915e633302SGaurav Srivastava 	if (!hash_empty(vport->hash_table))
54925e633302SGaurav Srivastava 		hash_for_each(vport->hash_table, bucket, cur, hnode)
54935e633302SGaurav Srivastava 			hash_del(&cur->hnode);
54945e633302SGaurav Srivastava 
54955e633302SGaurav Srivastava 	vport->qfpa_res = NULL;
54965e633302SGaurav Srivastava 	vport->vmid_priority.vmid_range = NULL;
54975e633302SGaurav Srivastava 	vport->vmid = NULL;
54985e633302SGaurav Srivastava 	vport->cur_vmid_cnt = 0;
54995e633302SGaurav Srivastava }
5500f281233dSJeff Garzik 
55019bad7671SJames Smart /**
55023621a710SJames Smart  * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point
55039bad7671SJames Smart  * @cmnd: Pointer to scsi_cmnd data structure.
55049bad7671SJames Smart  *
55059bad7671SJames Smart  * This routine aborts @cmnd pending in base driver.
55069bad7671SJames Smart  *
55079bad7671SJames Smart  * Return code :
55089bad7671SJames Smart  *   0x2003 - Error
55099bad7671SJames Smart  *   0x2002 - Success
55109bad7671SJames Smart  **/
5511dea3101eS static int
lpfc_abort_handler(struct scsi_cmnd * cmnd)551263c59c3bSJames.Smart@Emulex.Com lpfc_abort_handler(struct scsi_cmnd *cmnd)
5513dea3101eS {
551463c59c3bSJames.Smart@Emulex.Com 	struct Scsi_Host  *shost = cmnd->device->host;
5515bb21fc99SHannes Reinecke 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
55162e0fef85SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
55172e0fef85SJames Smart 	struct lpfc_hba   *phba = vport->phba;
55180bd4ca25SJames.Smart@Emulex.Com 	struct lpfc_iocbq *iocb;
5519c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd;
55203a70730aSJames Smart 	int ret = SUCCESS, status = 0;
55218931c73bSJames Smart 	struct lpfc_sli_ring *pring_s4 = NULL;
5522db7531d2SJames Smart 	struct lpfc_sli_ring *pring = NULL;
5523895427bdSJames Smart 	int ret_val;
552459c68eaaSJames Smart 	unsigned long flags;
5525fa61a54eSJames Smart 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
55260bd4ca25SJames.Smart@Emulex.Com 
5527bb21fc99SHannes Reinecke 	status = fc_block_rport(rport);
5528908e18e4SJames Smart 	if (status != 0 && status != SUCCESS)
55293a70730aSJames Smart 		return status;
55304f2e66c6SJames Smart 
5531c2017260SJames Smart 	lpfc_cmd = (struct lpfc_io_buf *)cmnd->host_scribble;
5532c2017260SJames Smart 	if (!lpfc_cmd)
5533c2017260SJames Smart 		return ret;
5534c2017260SJames Smart 
553503cbbd7cSJames Smart 	/* Guard against IO completion being called at same time */
553603cbbd7cSJames Smart 	spin_lock_irqsave(&lpfc_cmd->buf_lock, flags);
553703cbbd7cSJames Smart 
553803cbbd7cSJames Smart 	spin_lock(&phba->hbalock);
55394f2e66c6SJames Smart 	/* driver queued commands are in process of being flushed */
5540e780c942SJustin Tee 	if (test_bit(HBA_IOQ_FLUSH, &phba->hba_flag)) {
55414f2e66c6SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
55424f2e66c6SJames Smart 			"3168 SCSI Layer abort requested I/O has been "
55434f2e66c6SJames Smart 			"flushed by LLD.\n");
5544c2017260SJames Smart 		ret = FAILED;
554503cbbd7cSJames Smart 		goto out_unlock_hba;
55464f2e66c6SJames Smart 	}
55474f2e66c6SJames Smart 
5548c2017260SJames Smart 	if (!lpfc_cmd->pCmd) {
5549eee8877eSJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
5550eee8877eSJames Smart 			 "2873 SCSI Layer I/O Abort Request IO CMPL Status "
55519cb78c16SHannes Reinecke 			 "x%x ID %d LUN %llu\n",
55523a70730aSJames Smart 			 SUCCESS, cmnd->device->id, cmnd->device->lun);
555303cbbd7cSJames Smart 		goto out_unlock_hba;
5554eee8877eSJames Smart 	}
5555dea3101eS 
55564f2e66c6SJames Smart 	iocb = &lpfc_cmd->cur_iocbq;
55578931c73bSJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4) {
55582be1d4f1SJustin Tee 		/* if the io_wq & pring are gone, the port was reset. */
55592be1d4f1SJustin Tee 		if (!phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq ||
55602be1d4f1SJustin Tee 		    !phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring) {
55612be1d4f1SJustin Tee 			lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
55622be1d4f1SJustin Tee 					 "2877 SCSI Layer I/O Abort Request "
55632be1d4f1SJustin Tee 					 "IO CMPL Status x%x ID %d LUN %llu "
55642be1d4f1SJustin Tee 					 "HBA_SETUP %d\n", FAILED,
55652be1d4f1SJustin Tee 					 cmnd->device->id,
55662be1d4f1SJustin Tee 					 (u64)cmnd->device->lun,
55672be1d4f1SJustin Tee 					 test_bit(HBA_SETUP, &phba->hba_flag));
55688931c73bSJames Smart 			ret = FAILED;
556903cbbd7cSJames Smart 			goto out_unlock_hba;
55708931c73bSJames Smart 		}
55712be1d4f1SJustin Tee 		pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
55728931c73bSJames Smart 		spin_lock(&pring_s4->ring_lock);
55738931c73bSJames Smart 	}
55744f2e66c6SJames Smart 	/* the command is in process of being cancelled */
5575a680a929SJames Smart 	if (!(iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ)) {
55764f2e66c6SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
55774f2e66c6SJames Smart 			"3169 SCSI Layer abort requested I/O has been "
55784f2e66c6SJames Smart 			"cancelled by LLD.\n");
5579c2017260SJames Smart 		ret = FAILED;
5580c2017260SJames Smart 		goto out_unlock_ring;
55814f2e66c6SJames Smart 	}
5582dea3101eS 	/*
5583c490850aSJames Smart 	 * If pCmd field of the corresponding lpfc_io_buf structure
55840bd4ca25SJames.Smart@Emulex.Com 	 * points to a different SCSI command, then the driver has
55850bd4ca25SJames.Smart@Emulex.Com 	 * already completed this command, but the midlayer did not
55864f2e66c6SJames Smart 	 * see the completion before the eh fired. Just return SUCCESS.
5587dea3101eS 	 */
55884f2e66c6SJames Smart 	if (lpfc_cmd->pCmd != cmnd) {
55894f2e66c6SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
55904f2e66c6SJames Smart 			"3170 SCSI Layer abort requested I/O has been "
55914f2e66c6SJames Smart 			"completed by LLD.\n");
5592c2017260SJames Smart 		goto out_unlock_ring;
55934f2e66c6SJames Smart 	}
5594dea3101eS 
5595d51cf5bdSJames Smart 	WARN_ON(iocb->io_buf != lpfc_cmd);
5596dea3101eS 
5597ee62021aSJames Smart 	/* abort issued in recovery is still in progress */
5598a680a929SJames Smart 	if (iocb->cmd_flag & LPFC_DRIVER_ABORTED) {
5599ee62021aSJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
5600ee62021aSJames Smart 			 "3389 SCSI Layer I/O Abort Request is pending\n");
56018931c73bSJames Smart 		if (phba->sli_rev == LPFC_SLI_REV4)
56028931c73bSJames Smart 			spin_unlock(&pring_s4->ring_lock);
560303cbbd7cSJames Smart 		spin_unlock(&phba->hbalock);
560403cbbd7cSJames Smart 		spin_unlock_irqrestore(&lpfc_cmd->buf_lock, flags);
5605ee62021aSJames Smart 		goto wait_for_cmpl;
5606ee62021aSJames Smart 	}
5607ee62021aSJames Smart 
56088931c73bSJames Smart 	lpfc_cmd->waitq = &waitq;
56097294a9bcSJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4) {
561059c68eaaSJames Smart 		spin_unlock(&pring_s4->ring_lock);
56117294a9bcSJames Smart 		ret_val = lpfc_sli4_issue_abort_iotag(phba, iocb,
56127294a9bcSJames Smart 						      lpfc_sli_abort_fcp_cmpl);
56137294a9bcSJames Smart 	} else {
5614db7531d2SJames Smart 		pring = &phba->sli.sli3_ring[LPFC_FCP_RING];
5615db7531d2SJames Smart 		ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb,
5616db7531d2SJames Smart 						     lpfc_sli_abort_fcp_cmpl);
56177294a9bcSJames Smart 	}
56184f2e66c6SJames Smart 
5619a22d73b6SJames Smart 	/* Make sure HBA is alive */
5620a22d73b6SJames Smart 	lpfc_issue_hb_tmo(phba);
5621a22d73b6SJames Smart 
5622db7531d2SJames Smart 	if (ret_val != IOCB_SUCCESS) {
56238931c73bSJames Smart 		/* Indicate the IO is not being aborted by the driver. */
56248931c73bSJames Smart 		lpfc_cmd->waitq = NULL;
56250bd4ca25SJames.Smart@Emulex.Com 		ret = FAILED;
562603cbbd7cSJames Smart 		goto out_unlock_hba;
5627dea3101eS 	}
5628dea3101eS 
562991a52b61SJames Smart 	/* no longer need the lock after this point */
563003cbbd7cSJames Smart 	spin_unlock(&phba->hbalock);
563103cbbd7cSJames Smart 	spin_unlock_irqrestore(&lpfc_cmd->buf_lock, flags);
5632c2017260SJames Smart 
5633875fbdfeSJames.Smart@Emulex.Com 	if (phba->cfg_poll & DISABLE_FCP_RING_INT)
563445ed1190SJames Smart 		lpfc_sli_handle_fast_ring_event(phba,
5635895427bdSJames Smart 			&phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ);
5636875fbdfeSJames.Smart@Emulex.Com 
5637ee62021aSJames Smart wait_for_cmpl:
5638db7531d2SJames Smart 	/*
5639a680a929SJames Smart 	 * cmd_flag is set to LPFC_DRIVER_ABORTED before we wait
5640db7531d2SJames Smart 	 * for abort to complete.
5641db7531d2SJames Smart 	 */
5642fa61a54eSJames Smart 	wait_event_timeout(waitq,
5643fa61a54eSJames Smart 			  (lpfc_cmd->pCmd != cmnd),
5644256ec0d0SJames Smart 			   msecs_to_jiffies(2*vport->cfg_devloss_tmo*1000));
5645ee62021aSJames Smart 
5646c2017260SJames Smart 	spin_lock(&lpfc_cmd->buf_lock);
5647dea3101eS 
56480bd4ca25SJames.Smart@Emulex.Com 	if (lpfc_cmd->pCmd == cmnd) {
56490bd4ca25SJames.Smart@Emulex.Com 		ret = FAILED;
5650372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
5651e8b62011SJames Smart 				 "0748 abort handler timed out waiting "
56524b160ae8SMilan P. Gandhi 				 "for aborting I/O (xri:x%x) to complete: "
56539cb78c16SHannes Reinecke 				 "ret %#x, ID %d, LUN %llu\n",
5654247ca945SJames Smart 				 iocb->sli4_xritag, ret,
5655247ca945SJames Smart 				 cmnd->device->id, cmnd->device->lun);
5656dea3101eS 	}
5657b9e5a2d9SJames Smart 
5658b9e5a2d9SJames Smart 	lpfc_cmd->waitq = NULL;
5659b9e5a2d9SJames Smart 
5660c2017260SJames Smart 	spin_unlock(&lpfc_cmd->buf_lock);
56614f2e66c6SJames Smart 	goto out;
5662dea3101eS 
5663c2017260SJames Smart out_unlock_ring:
5664c2017260SJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4)
5665c2017260SJames Smart 		spin_unlock(&pring_s4->ring_lock);
566603cbbd7cSJames Smart out_unlock_hba:
566703cbbd7cSJames Smart 	spin_unlock(&phba->hbalock);
566803cbbd7cSJames Smart 	spin_unlock_irqrestore(&lpfc_cmd->buf_lock, flags);
5669dea3101eS out:
5670e8b62011SJames Smart 	lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
5671e8b62011SJames Smart 			 "0749 SCSI Layer I/O Abort Request Status x%x ID %d "
56729cb78c16SHannes Reinecke 			 "LUN %llu\n", ret, cmnd->device->id,
56735cd049a5SChristoph Hellwig 			 cmnd->device->lun);
56740bd4ca25SJames.Smart@Emulex.Com 	return ret;
5675dea3101eS }
5676dea3101eS 
5677bbb9d180SJames Smart static char *
lpfc_taskmgmt_name(uint8_t task_mgmt_cmd)5678bbb9d180SJames Smart lpfc_taskmgmt_name(uint8_t task_mgmt_cmd)
5679bbb9d180SJames Smart {
5680bbb9d180SJames Smart 	switch (task_mgmt_cmd) {
5681bbb9d180SJames Smart 	case FCP_ABORT_TASK_SET:
5682bbb9d180SJames Smart 		return "ABORT_TASK_SET";
5683bbb9d180SJames Smart 	case FCP_CLEAR_TASK_SET:
5684bbb9d180SJames Smart 		return "FCP_CLEAR_TASK_SET";
5685bbb9d180SJames Smart 	case FCP_BUS_RESET:
5686bbb9d180SJames Smart 		return "FCP_BUS_RESET";
5687bbb9d180SJames Smart 	case FCP_LUN_RESET:
5688bbb9d180SJames Smart 		return "FCP_LUN_RESET";
5689bbb9d180SJames Smart 	case FCP_TARGET_RESET:
5690bbb9d180SJames Smart 		return "FCP_TARGET_RESET";
5691bbb9d180SJames Smart 	case FCP_CLEAR_ACA:
5692bbb9d180SJames Smart 		return "FCP_CLEAR_ACA";
5693bbb9d180SJames Smart 	case FCP_TERMINATE_TASK:
5694bbb9d180SJames Smart 		return "FCP_TERMINATE_TASK";
5695bbb9d180SJames Smart 	default:
5696bbb9d180SJames Smart 		return "unknown";
5697bbb9d180SJames Smart 	}
5698bbb9d180SJames Smart }
5699bbb9d180SJames Smart 
570053151bbbSJames Smart 
570153151bbbSJames Smart /**
570253151bbbSJames Smart  * lpfc_check_fcp_rsp - check the returned fcp_rsp to see if task failed
570353151bbbSJames Smart  * @vport: The virtual port for which this call is being executed.
5704c490850aSJames Smart  * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
570553151bbbSJames Smart  *
570653151bbbSJames Smart  * This routine checks the FCP RSP INFO to see if the tsk mgmt command succeded
570753151bbbSJames Smart  *
570853151bbbSJames Smart  * Return code :
570953151bbbSJames Smart  *   0x2003 - Error
571053151bbbSJames Smart  *   0x2002 - Success
571153151bbbSJames Smart  **/
571253151bbbSJames Smart static int
lpfc_check_fcp_rsp(struct lpfc_vport * vport,struct lpfc_io_buf * lpfc_cmd)5713c490850aSJames Smart lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd)
571453151bbbSJames Smart {
571553151bbbSJames Smart 	struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
571653151bbbSJames Smart 	uint32_t rsp_info;
571753151bbbSJames Smart 	uint32_t rsp_len;
571853151bbbSJames Smart 	uint8_t  rsp_info_code;
571953151bbbSJames Smart 	int ret = FAILED;
572053151bbbSJames Smart 
572153151bbbSJames Smart 
572253151bbbSJames Smart 	if (fcprsp == NULL)
572353151bbbSJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
572453151bbbSJames Smart 				 "0703 fcp_rsp is missing\n");
572553151bbbSJames Smart 	else {
572653151bbbSJames Smart 		rsp_info = fcprsp->rspStatus2;
572753151bbbSJames Smart 		rsp_len = be32_to_cpu(fcprsp->rspRspLen);
572853151bbbSJames Smart 		rsp_info_code = fcprsp->rspInfo3;
572953151bbbSJames Smart 
573053151bbbSJames Smart 
573153151bbbSJames Smart 		lpfc_printf_vlog(vport, KERN_INFO,
573253151bbbSJames Smart 				 LOG_FCP,
573353151bbbSJames Smart 				 "0706 fcp_rsp valid 0x%x,"
573453151bbbSJames Smart 				 " rsp len=%d code 0x%x\n",
573553151bbbSJames Smart 				 rsp_info,
573653151bbbSJames Smart 				 rsp_len, rsp_info_code);
573753151bbbSJames Smart 
5738996a02aeSJames Smart 		/* If FCP_RSP_LEN_VALID bit is one, then the FCP_RSP_LEN
5739996a02aeSJames Smart 		 * field specifies the number of valid bytes of FCP_RSP_INFO.
5740996a02aeSJames Smart 		 * The FCP_RSP_LEN field shall be set to 0x04 or 0x08
5741996a02aeSJames Smart 		 */
5742996a02aeSJames Smart 		if ((fcprsp->rspStatus2 & RSP_LEN_VALID) &&
5743996a02aeSJames Smart 		    ((rsp_len == 8) || (rsp_len == 4))) {
574453151bbbSJames Smart 			switch (rsp_info_code) {
574553151bbbSJames Smart 			case RSP_NO_FAILURE:
574653151bbbSJames Smart 				lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
574753151bbbSJames Smart 						 "0715 Task Mgmt No Failure\n");
574853151bbbSJames Smart 				ret = SUCCESS;
574953151bbbSJames Smart 				break;
575053151bbbSJames Smart 			case RSP_TM_NOT_SUPPORTED: /* TM rejected */
575153151bbbSJames Smart 				lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
575253151bbbSJames Smart 						 "0716 Task Mgmt Target "
575353151bbbSJames Smart 						"reject\n");
575453151bbbSJames Smart 				break;
575553151bbbSJames Smart 			case RSP_TM_NOT_COMPLETED: /* TM failed */
575653151bbbSJames Smart 				lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
575753151bbbSJames Smart 						 "0717 Task Mgmt Target "
575853151bbbSJames Smart 						"failed TM\n");
575953151bbbSJames Smart 				break;
576053151bbbSJames Smart 			case RSP_TM_INVALID_LU: /* TM to invalid LU! */
576153151bbbSJames Smart 				lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
576253151bbbSJames Smart 						 "0718 Task Mgmt to invalid "
576353151bbbSJames Smart 						"LUN\n");
576453151bbbSJames Smart 				break;
576553151bbbSJames Smart 			}
576653151bbbSJames Smart 		}
576753151bbbSJames Smart 	}
576853151bbbSJames Smart 	return ret;
576953151bbbSJames Smart }
577053151bbbSJames Smart 
577153151bbbSJames Smart 
5772bbb9d180SJames Smart /**
5773bbb9d180SJames Smart  * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler
5774bbb9d180SJames Smart  * @vport: The virtual port for which this call is being executed.
5775123a3af3SHannes Reinecke  * @rport: Pointer to remote port
5776bbb9d180SJames Smart  * @tgt_id: Target ID of remote device.
5777bbb9d180SJames Smart  * @lun_id: Lun number for the TMF
5778bbb9d180SJames Smart  * @task_mgmt_cmd: type of TMF to send
5779bbb9d180SJames Smart  *
5780bbb9d180SJames Smart  * This routine builds and sends a TMF (SCSI Task Mgmt Function) to
5781bbb9d180SJames Smart  * a remote port.
5782bbb9d180SJames Smart  *
5783bbb9d180SJames Smart  * Return Code:
5784bbb9d180SJames Smart  *   0x2003 - Error
5785bbb9d180SJames Smart  *   0x2002 - Success.
5786bbb9d180SJames Smart  **/
5787bbb9d180SJames Smart static int
lpfc_send_taskmgmt(struct lpfc_vport * vport,struct fc_rport * rport,unsigned int tgt_id,uint64_t lun_id,uint8_t task_mgmt_cmd)5788123a3af3SHannes Reinecke lpfc_send_taskmgmt(struct lpfc_vport *vport, struct fc_rport *rport,
5789eed695d7SJames Smart 		   unsigned int tgt_id, uint64_t lun_id,
5790bbb9d180SJames Smart 		   uint8_t task_mgmt_cmd)
5791bbb9d180SJames Smart {
5792bbb9d180SJames Smart 	struct lpfc_hba   *phba = vport->phba;
5793c490850aSJames Smart 	struct lpfc_io_buf *lpfc_cmd;
5794bbb9d180SJames Smart 	struct lpfc_iocbq *iocbq;
5795bbb9d180SJames Smart 	struct lpfc_iocbq *iocbqrsp;
5796eed695d7SJames Smart 	struct lpfc_rport_data *rdata;
5797eed695d7SJames Smart 	struct lpfc_nodelist *pnode;
5798bbb9d180SJames Smart 	int ret;
5799bbb9d180SJames Smart 	int status;
5800bbb9d180SJames Smart 
5801123a3af3SHannes Reinecke 	rdata = rport->dd_data;
5802307e3380SJames Smart 	if (!rdata || !rdata->pnode)
5803bbb9d180SJames Smart 		return FAILED;
5804eed695d7SJames Smart 	pnode = rdata->pnode;
5805bbb9d180SJames Smart 
58063512ac09SJames Smart 	lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode, NULL);
5807bbb9d180SJames Smart 	if (lpfc_cmd == NULL)
5808bbb9d180SJames Smart 		return FAILED;
58090c411222SJames Smart 	lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;
5810bbb9d180SJames Smart 	lpfc_cmd->rdata = rdata;
5811123a3af3SHannes Reinecke 	lpfc_cmd->pCmd = NULL;
58122a5b7d62SJames Smart 	lpfc_cmd->ndlp = pnode;
5813bbb9d180SJames Smart 
58143512ac09SJames Smart 	status = phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
5815bbb9d180SJames Smart 						    task_mgmt_cmd);
5816bbb9d180SJames Smart 	if (!status) {
5817bbb9d180SJames Smart 		lpfc_release_scsi_buf(phba, lpfc_cmd);
5818bbb9d180SJames Smart 		return FAILED;
5819bbb9d180SJames Smart 	}
5820bbb9d180SJames Smart 
5821bbb9d180SJames Smart 	iocbq = &lpfc_cmd->cur_iocbq;
5822bbb9d180SJames Smart 	iocbqrsp = lpfc_sli_get_iocbq(phba);
5823bbb9d180SJames Smart 	if (iocbqrsp == NULL) {
5824bbb9d180SJames Smart 		lpfc_release_scsi_buf(phba, lpfc_cmd);
5825bbb9d180SJames Smart 		return FAILED;
5826bbb9d180SJames Smart 	}
5827a680a929SJames Smart 	iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl;
58283512ac09SJames Smart 	iocbq->vport = vport;
5829bbb9d180SJames Smart 
5830bbb9d180SJames Smart 	lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
58319cb78c16SHannes Reinecke 			 "0702 Issue %s to TGT %d LUN %llu "
58326d368e53SJames Smart 			 "rpi x%x nlp_flag x%x Data: x%x x%x\n",
5833bbb9d180SJames Smart 			 lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id,
58346d368e53SJames Smart 			 pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag,
5835a680a929SJames Smart 			 iocbq->cmd_flag);
5836bbb9d180SJames Smart 
5837bbb9d180SJames Smart 	status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING,
5838bbb9d180SJames Smart 					  iocbq, iocbqrsp, lpfc_cmd->timeout);
583953151bbbSJames Smart 	if ((status != IOCB_SUCCESS) ||
58403512ac09SJames Smart 	    (get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_SUCCESS)) {
5841ae374a30SJames Smart 		if (status != IOCB_SUCCESS ||
58423512ac09SJames Smart 		    get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_FCP_RSP_ERROR)
5843372c187bSDick Kennedy 			lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
5844ae374a30SJames Smart 					 "0727 TMF %s to TGT %d LUN %llu "
5845a680a929SJames Smart 					 "failed (%d, %d) cmd_flag x%x\n",
5846bbb9d180SJames Smart 					 lpfc_taskmgmt_name(task_mgmt_cmd),
5847ae374a30SJames Smart 					 tgt_id, lun_id,
58483512ac09SJames Smart 					 get_job_ulpstatus(phba, iocbqrsp),
58493512ac09SJames Smart 					 get_job_word4(phba, iocbqrsp),
5850a680a929SJames Smart 					 iocbq->cmd_flag);
585153151bbbSJames Smart 		/* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */
585253151bbbSJames Smart 		if (status == IOCB_SUCCESS) {
58533512ac09SJames Smart 			if (get_job_ulpstatus(phba, iocbqrsp) ==
58543512ac09SJames Smart 			    IOSTAT_FCP_RSP_ERROR)
585553151bbbSJames Smart 				/* Something in the FCP_RSP was invalid.
585653151bbbSJames Smart 				 * Check conditions */
585753151bbbSJames Smart 				ret = lpfc_check_fcp_rsp(vport, lpfc_cmd);
58582a9bf3d0SJames Smart 			else
585953151bbbSJames Smart 				ret = FAILED;
58603512ac09SJames Smart 		} else if ((status == IOCB_TIMEDOUT) ||
58613512ac09SJames Smart 			   (status == IOCB_ABORTED)) {
586253151bbbSJames Smart 			ret = TIMEOUT_ERROR;
586353151bbbSJames Smart 		} else {
586453151bbbSJames Smart 			ret = FAILED;
586553151bbbSJames Smart 		}
586653151bbbSJames Smart 	} else
5867bbb9d180SJames Smart 		ret = SUCCESS;
5868bbb9d180SJames Smart 
5869bbb9d180SJames Smart 	lpfc_sli_release_iocbq(phba, iocbqrsp);
5870bbb9d180SJames Smart 
58713512ac09SJames Smart 	if (status != IOCB_TIMEDOUT)
5872bbb9d180SJames Smart 		lpfc_release_scsi_buf(phba, lpfc_cmd);
5873bbb9d180SJames Smart 
5874bbb9d180SJames Smart 	return ret;
5875bbb9d180SJames Smart }
5876bbb9d180SJames Smart 
5877bbb9d180SJames Smart /**
5878bbb9d180SJames Smart  * lpfc_chk_tgt_mapped -
5879bbb9d180SJames Smart  * @vport: The virtual port to check on
5880e81ce97fSHannes Reinecke  * @rport: Pointer to fc_rport data structure.
5881bbb9d180SJames Smart  *
5882bbb9d180SJames Smart  * This routine delays until the scsi target (aka rport) for the
5883bbb9d180SJames Smart  * command exists (is present and logged in) or we declare it non-existent.
5884bbb9d180SJames Smart  *
5885bbb9d180SJames Smart  * Return code :
5886bbb9d180SJames Smart  *  0x2003 - Error
5887bbb9d180SJames Smart  *  0x2002 - Success
5888bbb9d180SJames Smart  **/
5889bbb9d180SJames Smart static int
lpfc_chk_tgt_mapped(struct lpfc_vport * vport,struct fc_rport * rport)5890e81ce97fSHannes Reinecke lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct fc_rport *rport)
5891bbb9d180SJames Smart {
58921ba981fdSJames Smart 	struct lpfc_rport_data *rdata;
5893e81ce97fSHannes Reinecke 	struct lpfc_nodelist *pnode = NULL;
5894bbb9d180SJames Smart 	unsigned long later;
5895bbb9d180SJames Smart 
5896e81ce97fSHannes Reinecke 	rdata = rport->dd_data;
58971c6f4ef5SJames Smart 	if (!rdata) {
58981c6f4ef5SJames Smart 		lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
589932350664SJames Smart 			"0797 Tgt Map rport failure: rdata x%px\n", rdata);
59001c6f4ef5SJames Smart 		return FAILED;
59011c6f4ef5SJames Smart 	}
59021c6f4ef5SJames Smart 	pnode = rdata->pnode;
5903e81ce97fSHannes Reinecke 
5904bbb9d180SJames Smart 	/*
5905bbb9d180SJames Smart 	 * If target is not in a MAPPED state, delay until
5906bbb9d180SJames Smart 	 * target is rediscovered or devloss timeout expires.
5907bbb9d180SJames Smart 	 */
5908bbb9d180SJames Smart 	later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
5909bbb9d180SJames Smart 	while (time_after(later, jiffies)) {
5910307e3380SJames Smart 		if (!pnode)
5911bbb9d180SJames Smart 			return FAILED;
5912bbb9d180SJames Smart 		if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
5913bbb9d180SJames Smart 			return SUCCESS;
5914bbb9d180SJames Smart 		schedule_timeout_uninterruptible(msecs_to_jiffies(500));
5915e81ce97fSHannes Reinecke 		rdata = rport->dd_data;
5916bbb9d180SJames Smart 		if (!rdata)
5917bbb9d180SJames Smart 			return FAILED;
5918bbb9d180SJames Smart 		pnode = rdata->pnode;
5919bbb9d180SJames Smart 	}
5920307e3380SJames Smart 	if (!pnode || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
5921bbb9d180SJames Smart 		return FAILED;
5922bbb9d180SJames Smart 	return SUCCESS;
5923bbb9d180SJames Smart }
5924bbb9d180SJames Smart 
5925bbb9d180SJames Smart /**
5926bbb9d180SJames Smart  * lpfc_reset_flush_io_context -
5927bbb9d180SJames Smart  * @vport: The virtual port (scsi_host) for the flush context
5928bbb9d180SJames Smart  * @tgt_id: If aborting by Target contect - specifies the target id
5929bbb9d180SJames Smart  * @lun_id: If aborting by Lun context - specifies the lun id
5930bbb9d180SJames Smart  * @context: specifies the context level to flush at.
5931bbb9d180SJames Smart  *
5932bbb9d180SJames Smart  * After a reset condition via TMF, we need to flush orphaned i/o
5933bbb9d180SJames Smart  * contexts from the adapter. This routine aborts any contexts
5934bbb9d180SJames Smart  * outstanding, then waits for their completions. The wait is
5935bbb9d180SJames Smart  * bounded by devloss_tmo though.
5936bbb9d180SJames Smart  *
5937bbb9d180SJames Smart  * Return code :
5938bbb9d180SJames Smart  *  0x2003 - Error
5939bbb9d180SJames Smart  *  0x2002 - Success
5940bbb9d180SJames Smart  **/
5941bbb9d180SJames Smart static int
lpfc_reset_flush_io_context(struct lpfc_vport * vport,uint16_t tgt_id,uint64_t lun_id,lpfc_ctx_cmd context)5942bbb9d180SJames Smart lpfc_reset_flush_io_context(struct lpfc_vport *vport, uint16_t tgt_id,
5943bbb9d180SJames Smart 			uint64_t lun_id, lpfc_ctx_cmd context)
5944bbb9d180SJames Smart {
5945bbb9d180SJames Smart 	struct lpfc_hba   *phba = vport->phba;
5946bbb9d180SJames Smart 	unsigned long later;
5947bbb9d180SJames Smart 	int cnt;
5948bbb9d180SJames Smart 
5949bbb9d180SJames Smart 	cnt = lpfc_sli_sum_iocb(vport, tgt_id, lun_id, context);
5950bbb9d180SJames Smart 	if (cnt)
595198912ddaSJames Smart 		lpfc_sli_abort_taskmgmt(vport,
5952895427bdSJames Smart 					&phba->sli.sli3_ring[LPFC_FCP_RING],
5953bbb9d180SJames Smart 					tgt_id, lun_id, context);
5954bbb9d180SJames Smart 	later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
5955bbb9d180SJames Smart 	while (time_after(later, jiffies) && cnt) {
5956bbb9d180SJames Smart 		schedule_timeout_uninterruptible(msecs_to_jiffies(20));
5957bbb9d180SJames Smart 		cnt = lpfc_sli_sum_iocb(vport, tgt_id, lun_id, context);
5958bbb9d180SJames Smart 	}
5959bbb9d180SJames Smart 	if (cnt) {
5960372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
5961bbb9d180SJames Smart 			"0724 I/O flush failure for context %s : cnt x%x\n",
5962bbb9d180SJames Smart 			((context == LPFC_CTX_LUN) ? "LUN" :
5963bbb9d180SJames Smart 			 ((context == LPFC_CTX_TGT) ? "TGT" :
5964bbb9d180SJames Smart 			  ((context == LPFC_CTX_HOST) ? "HOST" : "Unknown"))),
5965bbb9d180SJames Smart 			cnt);
5966bbb9d180SJames Smart 		return FAILED;
5967bbb9d180SJames Smart 	}
5968bbb9d180SJames Smart 	return SUCCESS;
5969bbb9d180SJames Smart }
5970bbb9d180SJames Smart 
59719bad7671SJames Smart /**
59723621a710SJames Smart  * lpfc_device_reset_handler - scsi_host_template eh_device_reset entry point
59739bad7671SJames Smart  * @cmnd: Pointer to scsi_cmnd data structure.
59749bad7671SJames Smart  *
5975bbb9d180SJames Smart  * This routine does a device reset by sending a LUN_RESET task management
59769bad7671SJames Smart  * command.
59779bad7671SJames Smart  *
59789bad7671SJames Smart  * Return code :
59799bad7671SJames Smart  *  0x2003 - Error
59803621a710SJames Smart  *  0x2002 - Success
59819bad7671SJames Smart  **/
5982dea3101eS static int
lpfc_device_reset_handler(struct scsi_cmnd * cmnd)59837054a606SJames Smart lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
5984dea3101eS {
5985dea3101eS 	struct Scsi_Host  *shost = cmnd->device->host;
5986bb21fc99SHannes Reinecke 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
59872e0fef85SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
59881ba981fdSJames Smart 	struct lpfc_rport_data *rdata;
59891c6f4ef5SJames Smart 	struct lpfc_nodelist *pnode;
5990bbb9d180SJames Smart 	unsigned tgt_id = cmnd->device->id;
59919cb78c16SHannes Reinecke 	uint64_t lun_id = cmnd->device->lun;
5992ea2151b4SJames Smart 	struct lpfc_scsi_event_header scsi_event;
599353151bbbSJames Smart 	int status;
5994da09ae48SJames Smart 	u32 logit = LOG_FCP;
5995dea3101eS 
59966f808bd7SJames Smart 	if (!rport)
59976f808bd7SJames Smart 		return FAILED;
59986f808bd7SJames Smart 
5999bb21fc99SHannes Reinecke 	rdata = rport->dd_data;
6000ad490b6eSJames Smart 	if (!rdata || !rdata->pnode) {
6001372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
600232350664SJames Smart 				 "0798 Device Reset rdata failure: rdata x%px\n",
6003ad490b6eSJames Smart 				 rdata);
60041c6f4ef5SJames Smart 		return FAILED;
60051c6f4ef5SJames Smart 	}
60061c6f4ef5SJames Smart 	pnode = rdata->pnode;
6007bb21fc99SHannes Reinecke 	status = fc_block_rport(rport);
6008908e18e4SJames Smart 	if (status != 0 && status != SUCCESS)
6009589a52d6SJames Smart 		return status;
6010bbb9d180SJames Smart 
6011e81ce97fSHannes Reinecke 	status = lpfc_chk_tgt_mapped(vport, rport);
6012bbb9d180SJames Smart 	if (status == FAILED) {
6013372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
601432350664SJames Smart 			"0721 Device Reset rport failure: rdata x%px\n", rdata);
6015915caaafSJames Smart 		return FAILED;
6016bbb9d180SJames Smart 	}
6017bbb9d180SJames Smart 
6018bbb9d180SJames Smart 	scsi_event.event_type = FC_REG_SCSI_EVENT;
6019bbb9d180SJames Smart 	scsi_event.subcategory = LPFC_EVENT_LUNRESET;
6020bbb9d180SJames Smart 	scsi_event.lun = lun_id;
6021bbb9d180SJames Smart 	memcpy(scsi_event.wwpn, &pnode->nlp_portname, sizeof(struct lpfc_name));
6022bbb9d180SJames Smart 	memcpy(scsi_event.wwnn, &pnode->nlp_nodename, sizeof(struct lpfc_name));
6023bbb9d180SJames Smart 
6024bbb9d180SJames Smart 	fc_host_post_vendor_event(shost, fc_get_event_number(),
6025bbb9d180SJames Smart 		sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
6026bbb9d180SJames Smart 
6027123a3af3SHannes Reinecke 	status = lpfc_send_taskmgmt(vport, rport, tgt_id, lun_id,
6028bbb9d180SJames Smart 						FCP_LUN_RESET);
6029da09ae48SJames Smart 	if (status != SUCCESS)
6030da09ae48SJames Smart 		logit =  LOG_TRACE_EVENT;
6031bbb9d180SJames Smart 
6032da09ae48SJames Smart 	lpfc_printf_vlog(vport, KERN_ERR, logit,
60339cb78c16SHannes Reinecke 			 "0713 SCSI layer issued Device Reset (%d, %llu) "
6034bbb9d180SJames Smart 			 "return x%x\n", tgt_id, lun_id, status);
6035bbb9d180SJames Smart 
6036bbb9d180SJames Smart 	/*
6037bbb9d180SJames Smart 	 * We have to clean up i/o as : they may be orphaned by the TMF;
6038bbb9d180SJames Smart 	 * or if the TMF failed, they may be in an indeterminate state.
6039bbb9d180SJames Smart 	 * So, continue on.
6040bbb9d180SJames Smart 	 * We will report success if all the i/o aborts successfully.
6041bbb9d180SJames Smart 	 */
604253151bbbSJames Smart 	if (status == SUCCESS)
604353151bbbSJames Smart 		status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
6044bbb9d180SJames Smart 						LPFC_CTX_LUN);
604553151bbbSJames Smart 
604653151bbbSJames Smart 	return status;
6047bbb9d180SJames Smart }
6048bbb9d180SJames Smart 
6049bbb9d180SJames Smart /**
6050bbb9d180SJames Smart  * lpfc_target_reset_handler - scsi_host_template eh_target_reset entry point
6051bbb9d180SJames Smart  * @cmnd: Pointer to scsi_cmnd data structure.
6052bbb9d180SJames Smart  *
6053bbb9d180SJames Smart  * This routine does a target reset by sending a TARGET_RESET task management
6054bbb9d180SJames Smart  * command.
6055bbb9d180SJames Smart  *
6056bbb9d180SJames Smart  * Return code :
6057bbb9d180SJames Smart  *  0x2003 - Error
6058bbb9d180SJames Smart  *  0x2002 - Success
6059bbb9d180SJames Smart  **/
6060bbb9d180SJames Smart static int
lpfc_target_reset_handler(struct scsi_cmnd * cmnd)6061bbb9d180SJames Smart lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
6062bbb9d180SJames Smart {
6063bbb9d180SJames Smart 	struct Scsi_Host  *shost = cmnd->device->host;
6064bb21fc99SHannes Reinecke 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
6065bbb9d180SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
60661ba981fdSJames Smart 	struct lpfc_rport_data *rdata;
60671c6f4ef5SJames Smart 	struct lpfc_nodelist *pnode;
6068bbb9d180SJames Smart 	unsigned tgt_id = cmnd->device->id;
60699cb78c16SHannes Reinecke 	uint64_t lun_id = cmnd->device->lun;
6070bbb9d180SJames Smart 	struct lpfc_scsi_event_header scsi_event;
607153151bbbSJames Smart 	int status;
6072da09ae48SJames Smart 	u32 logit = LOG_FCP;
607321990d3dSJames Smart 	u32 dev_loss_tmo = vport->cfg_devloss_tmo;
607431051249SJames Smart 	unsigned long flags;
607531051249SJames Smart 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
6076bbb9d180SJames Smart 
60776f808bd7SJames Smart 	if (!rport)
60786f808bd7SJames Smart 		return FAILED;
60796f808bd7SJames Smart 
6080bb21fc99SHannes Reinecke 	rdata = rport->dd_data;
6081bbd3d738SJames Smart 	if (!rdata || !rdata->pnode) {
6082372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
608332350664SJames Smart 				 "0799 Target Reset rdata failure: rdata x%px\n",
6084bbd3d738SJames Smart 				 rdata);
60851c6f4ef5SJames Smart 		return FAILED;
60861c6f4ef5SJames Smart 	}
60871c6f4ef5SJames Smart 	pnode = rdata->pnode;
6088bb21fc99SHannes Reinecke 	status = fc_block_rport(rport);
6089908e18e4SJames Smart 	if (status != 0 && status != SUCCESS)
6090589a52d6SJames Smart 		return status;
6091bbb9d180SJames Smart 
6092e81ce97fSHannes Reinecke 	status = lpfc_chk_tgt_mapped(vport, rport);
6093bbb9d180SJames Smart 	if (status == FAILED) {
6094372c187bSDick Kennedy 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
609532350664SJames Smart 			"0722 Target Reset rport failure: rdata x%px\n", rdata);
609663e480fdSJames Smart 		if (pnode) {
609731051249SJames Smart 			spin_lock_irqsave(&pnode->lock, flags);
60988c50d25cSJames Smart 			pnode->nlp_flag &= ~NLP_NPR_ADISC;
60998c50d25cSJames Smart 			pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
610031051249SJames Smart 			spin_unlock_irqrestore(&pnode->lock, flags);
610163e480fdSJames Smart 		}
61028c50d25cSJames Smart 		lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
61038c50d25cSJames Smart 					  LPFC_CTX_TGT);
61048c50d25cSJames Smart 		return FAST_IO_FAIL;
6105dea3101eS 	}
6106ea2151b4SJames Smart 
6107ea2151b4SJames Smart 	scsi_event.event_type = FC_REG_SCSI_EVENT;
6108ea2151b4SJames Smart 	scsi_event.subcategory = LPFC_EVENT_TGTRESET;
6109ea2151b4SJames Smart 	scsi_event.lun = 0;
6110ea2151b4SJames Smart 	memcpy(scsi_event.wwpn, &pnode->nlp_portname, sizeof(struct lpfc_name));
6111ea2151b4SJames Smart 	memcpy(scsi_event.wwnn, &pnode->nlp_nodename, sizeof(struct lpfc_name));
6112ea2151b4SJames Smart 
6113bbb9d180SJames Smart 	fc_host_post_vendor_event(shost, fc_get_event_number(),
6114bbb9d180SJames Smart 		sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
6115ea2151b4SJames Smart 
6116123a3af3SHannes Reinecke 	status = lpfc_send_taskmgmt(vport, rport, tgt_id, lun_id,
61177054a606SJames Smart 					FCP_TARGET_RESET);
611821990d3dSJames Smart 	if (status != SUCCESS) {
6119da09ae48SJames Smart 		logit = LOG_TRACE_EVENT;
612021990d3dSJames Smart 
612121990d3dSJames Smart 		/* Issue LOGO, if no LOGO is outstanding */
612231051249SJames Smart 		spin_lock_irqsave(&pnode->lock, flags);
6123af984c87SJames Smart 		if (!(pnode->save_flags & NLP_WAIT_FOR_LOGO) &&
612431051249SJames Smart 		    !pnode->logo_waitq) {
612531051249SJames Smart 			pnode->logo_waitq = &waitq;
612631051249SJames Smart 			pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
612731051249SJames Smart 			pnode->nlp_flag |= NLP_ISSUE_LOGO;
6128af984c87SJames Smart 			pnode->save_flags |= NLP_WAIT_FOR_LOGO;
612931051249SJames Smart 			spin_unlock_irqrestore(&pnode->lock, flags);
613031051249SJames Smart 			lpfc_unreg_rpi(vport, pnode);
613131051249SJames Smart 			wait_event_timeout(waitq,
6132af984c87SJames Smart 					   (!(pnode->save_flags &
613321990d3dSJames Smart 					      NLP_WAIT_FOR_LOGO)),
613421990d3dSJames Smart 					   msecs_to_jiffies(dev_loss_tmo *
613531051249SJames Smart 							    1000));
613631051249SJames Smart 
6137af984c87SJames Smart 			if (pnode->save_flags & NLP_WAIT_FOR_LOGO) {
613821990d3dSJames Smart 				lpfc_printf_vlog(vport, KERN_ERR, logit,
613921990d3dSJames Smart 						 "0725 SCSI layer TGTRST "
614021990d3dSJames Smart 						 "failed & LOGO TMO (%d, %llu) "
614121990d3dSJames Smart 						 "return x%x\n",
614221990d3dSJames Smart 						 tgt_id, lun_id, status);
614331051249SJames Smart 				spin_lock_irqsave(&pnode->lock, flags);
6144af984c87SJames Smart 				pnode->save_flags &= ~NLP_WAIT_FOR_LOGO;
614531051249SJames Smart 			} else {
614631051249SJames Smart 				spin_lock_irqsave(&pnode->lock, flags);
614731051249SJames Smart 			}
614831051249SJames Smart 			pnode->logo_waitq = NULL;
614931051249SJames Smart 			spin_unlock_irqrestore(&pnode->lock, flags);
615031051249SJames Smart 			status = SUCCESS;
615121990d3dSJames Smart 
615231051249SJames Smart 		} else {
615331051249SJames Smart 			spin_unlock_irqrestore(&pnode->lock, flags);
615421990d3dSJames Smart 			status = FAILED;
615521990d3dSJames Smart 		}
615631051249SJames Smart 	}
6157dea3101eS 
6158da09ae48SJames Smart 	lpfc_printf_vlog(vport, KERN_ERR, logit,
61599cb78c16SHannes Reinecke 			 "0723 SCSI layer issued Target Reset (%d, %llu) "
6160bbb9d180SJames Smart 			 "return x%x\n", tgt_id, lun_id, status);
6161bbb9d180SJames Smart 
6162bbb9d180SJames Smart 	/*
6163bbb9d180SJames Smart 	 * We have to clean up i/o as : they may be orphaned by the TMF;
6164bbb9d180SJames Smart 	 * or if the TMF failed, they may be in an indeterminate state.
6165bbb9d180SJames Smart 	 * So, continue on.
6166bbb9d180SJames Smart 	 * We will report success if all the i/o aborts successfully.
6167bbb9d180SJames Smart 	 */
616853151bbbSJames Smart 	if (status == SUCCESS)
616953151bbbSJames Smart 		status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
6170915caaafSJames Smart 					  LPFC_CTX_TGT);
617153151bbbSJames Smart 	return status;
6172dea3101eS }
6173dea3101eS 
61749bad7671SJames Smart /**
617527b01b82SJames Smart  * lpfc_host_reset_handler - scsi_host_template eh_host_reset_handler entry pt
617627b01b82SJames Smart  * @cmnd: Pointer to scsi_cmnd data structure.
617727b01b82SJames Smart  *
617827b01b82SJames Smart  * This routine does host reset to the adaptor port. It brings the HBA
617927b01b82SJames Smart  * offline, performs a board restart, and then brings the board back online.
618027b01b82SJames Smart  * The lpfc_offline calls lpfc_sli_hba_down which will abort and local
618127b01b82SJames Smart  * reject all outstanding SCSI commands to the host and error returned
618227b01b82SJames Smart  * back to SCSI mid-level. As this will be SCSI mid-level's last resort
618327b01b82SJames Smart  * of error handling, it will only return error if resetting of the adapter
618427b01b82SJames Smart  * is not successful; in all other cases, will return success.
618527b01b82SJames Smart  *
618627b01b82SJames Smart  * Return code :
618727b01b82SJames Smart  *  0x2003 - Error
618827b01b82SJames Smart  *  0x2002 - Success
618927b01b82SJames Smart  **/
619027b01b82SJames Smart static int
lpfc_host_reset_handler(struct scsi_cmnd * cmnd)619127b01b82SJames Smart lpfc_host_reset_handler(struct scsi_cmnd *cmnd)
619227b01b82SJames Smart {
619327b01b82SJames Smart 	struct Scsi_Host *shost = cmnd->device->host;
619427b01b82SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
619527b01b82SJames Smart 	struct lpfc_hba *phba = vport->phba;
619627b01b82SJames Smart 	int rc, ret = SUCCESS;
619727b01b82SJames Smart 
6198da09ae48SJames Smart 	lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
6199a88dbb6aSJames Smart 			 "3172 SCSI layer issued Host Reset Data:\n");
6200a88dbb6aSJames Smart 
6201618a5230SJames Smart 	lpfc_offline_prep(phba, LPFC_MBX_WAIT);
620227b01b82SJames Smart 	lpfc_offline(phba);
620327b01b82SJames Smart 	rc = lpfc_sli_brdrestart(phba);
620427b01b82SJames Smart 	if (rc)
62058c24a4f6SJames Smart 		goto error;
62068c24a4f6SJames Smart 
6207d305c253SJames Smart 	/* Wait for successful restart of adapter */
6208d305c253SJames Smart 	if (phba->sli_rev < LPFC_SLI_REV4) {
6209d305c253SJames Smart 		rc = lpfc_sli_chipset_init(phba);
6210d305c253SJames Smart 		if (rc)
6211d305c253SJames Smart 			goto error;
6212d305c253SJames Smart 	}
6213d305c253SJames Smart 
6214a88dbb6aSJames Smart 	rc = lpfc_online(phba);
6215a88dbb6aSJames Smart 	if (rc)
62168c24a4f6SJames Smart 		goto error;
62178c24a4f6SJames Smart 
621827b01b82SJames Smart 	lpfc_unblock_mgmt_io(phba);
621927b01b82SJames Smart 
622027b01b82SJames Smart 	return ret;
62218c24a4f6SJames Smart error:
6222372c187bSDick Kennedy 	lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
62238c24a4f6SJames Smart 			 "3323 Failed host reset\n");
62248c24a4f6SJames Smart 	lpfc_unblock_mgmt_io(phba);
62258c24a4f6SJames Smart 	return FAILED;
622627b01b82SJames Smart }
622727b01b82SJames Smart 
622827b01b82SJames Smart /**
62293621a710SJames Smart  * lpfc_slave_alloc - scsi_host_template slave_alloc entry point
62309bad7671SJames Smart  * @sdev: Pointer to scsi_device.
62319bad7671SJames Smart  *
62329bad7671SJames Smart  * This routine populates the cmds_per_lun count + 2 scsi_bufs into  this host's
62339bad7671SJames Smart  * globally available list of scsi buffers. This routine also makes sure scsi
62349bad7671SJames Smart  * buffer is not allocated more than HBA limit conveyed to midlayer. This list
62359bad7671SJames Smart  * of scsi buffer exists for the lifetime of the driver.
62369bad7671SJames Smart  *
62379bad7671SJames Smart  * Return codes:
62389bad7671SJames Smart  *   non-0 - Error
62399bad7671SJames Smart  *   0 - Success
62409bad7671SJames Smart  **/
6241dea3101eS static int
lpfc_slave_alloc(struct scsi_device * sdev)6242dea3101eS lpfc_slave_alloc(struct scsi_device *sdev)
6243dea3101eS {
62442e0fef85SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
62452e0fef85SJames Smart 	struct lpfc_hba   *phba = vport->phba;
624619a7b4aeSJames.Smart@Emulex.Com 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
62473772a991SJames Smart 	uint32_t total = 0;
6248dea3101eS 	uint32_t num_to_alloc = 0;
62493772a991SJames Smart 	int num_allocated = 0;
6250d7c47992SJames Smart 	uint32_t sdev_cnt;
62511ba981fdSJames Smart 	struct lpfc_device_data *device_data;
62521ba981fdSJames Smart 	unsigned long flags;
62531ba981fdSJames Smart 	struct lpfc_name target_wwpn;
6254dea3101eS 
625519a7b4aeSJames.Smart@Emulex.Com 	if (!rport || fc_remote_port_chkready(rport))
6256dea3101eS 		return -ENXIO;
6257dea3101eS 
6258f38fa0bbSJames Smart 	if (phba->cfg_fof) {
62591ba981fdSJames Smart 
62601ba981fdSJames Smart 		/*
62611ba981fdSJames Smart 		 * Check to see if the device data structure for the lun
62621ba981fdSJames Smart 		 * exists.  If not, create one.
62631ba981fdSJames Smart 		 */
62641ba981fdSJames Smart 
62651ba981fdSJames Smart 		u64_to_wwn(rport->port_name, target_wwpn.u.wwn);
62661ba981fdSJames Smart 		spin_lock_irqsave(&phba->devicelock, flags);
62671ba981fdSJames Smart 		device_data = __lpfc_get_device_data(phba,
62681ba981fdSJames Smart 						     &phba->luns,
62691ba981fdSJames Smart 						     &vport->fc_portname,
62701ba981fdSJames Smart 						     &target_wwpn,
62711ba981fdSJames Smart 						     sdev->lun);
62721ba981fdSJames Smart 		if (!device_data) {
62731ba981fdSJames Smart 			spin_unlock_irqrestore(&phba->devicelock, flags);
62741ba981fdSJames Smart 			device_data = lpfc_create_device_data(phba,
62751ba981fdSJames Smart 							&vport->fc_portname,
62761ba981fdSJames Smart 							&target_wwpn,
6277b5749fe1SJames Smart 							sdev->lun,
6278b5749fe1SJames Smart 							phba->cfg_XLanePriority,
6279b5749fe1SJames Smart 							true);
62801ba981fdSJames Smart 			if (!device_data)
62811ba981fdSJames Smart 				return -ENOMEM;
62821ba981fdSJames Smart 			spin_lock_irqsave(&phba->devicelock, flags);
62831ba981fdSJames Smart 			list_add_tail(&device_data->listentry, &phba->luns);
62841ba981fdSJames Smart 		}
62851ba981fdSJames Smart 		device_data->rport_data = rport->dd_data;
62861ba981fdSJames Smart 		device_data->available = true;
62871ba981fdSJames Smart 		spin_unlock_irqrestore(&phba->devicelock, flags);
62881ba981fdSJames Smart 		sdev->hostdata = device_data;
62891ba981fdSJames Smart 	} else {
629019a7b4aeSJames.Smart@Emulex.Com 		sdev->hostdata = rport->dd_data;
62911ba981fdSJames Smart 	}
6292d7c47992SJames Smart 	sdev_cnt = atomic_inc_return(&phba->sdev_cnt);
6293dea3101eS 
62940794d601SJames Smart 	/* For SLI4, all IO buffers are pre-allocated */
62950794d601SJames Smart 	if (phba->sli_rev == LPFC_SLI_REV4)
62960794d601SJames Smart 		return 0;
62970794d601SJames Smart 
62980794d601SJames Smart 	/* This code path is now ONLY for SLI3 adapters */
62990794d601SJames Smart 
6300dea3101eS 	/*
6301dea3101eS 	 * Populate the cmds_per_lun count scsi_bufs into this host's globally
6302dea3101eS 	 * available list of scsi buffers.  Don't allocate more than the
6303a784efbfSJames.Smart@Emulex.Com 	 * HBA limit conveyed to the midlayer via the host structure.  The
6304a784efbfSJames.Smart@Emulex.Com 	 * formula accounts for the lun_queue_depth + error handlers + 1
6305a784efbfSJames.Smart@Emulex.Com 	 * extra.  This list of scsi bufs exists for the lifetime of the driver.
6306dea3101eS 	 */
6307dea3101eS 	total = phba->total_scsi_bufs;
63083de2a653SJames Smart 	num_to_alloc = vport->cfg_lun_queue_depth + 2;
630992d7f7b0SJames Smart 
6310d7c47992SJames Smart 	/* If allocated buffers are enough do nothing */
6311d7c47992SJames Smart 	if ((sdev_cnt * (vport->cfg_lun_queue_depth + 2)) < total)
6312d7c47992SJames Smart 		return 0;
6313d7c47992SJames Smart 
631492d7f7b0SJames Smart 	/* Allow some exchanges to be available always to complete discovery */
631592d7f7b0SJames Smart 	if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
6316e8b62011SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
6317e8b62011SJames Smart 				 "0704 At limitation of %d preallocated "
6318e8b62011SJames Smart 				 "command buffers\n", total);
6319dea3101eS 		return 0;
632092d7f7b0SJames Smart 	/* Allow some exchanges to be available always to complete discovery */
632192d7f7b0SJames Smart 	} else if (total + num_to_alloc >
632292d7f7b0SJames Smart 		phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
6323e8b62011SJames Smart 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
6324e8b62011SJames Smart 				 "0705 Allocation request of %d "
632592d7f7b0SJames Smart 				 "command buffers will exceed max of %d.  "
632692d7f7b0SJames Smart 				 "Reducing allocation request to %d.\n",
6327e8b62011SJames Smart 				 num_to_alloc, phba->cfg_hba_queue_depth,
6328a784efbfSJames.Smart@Emulex.Com 				 (phba->cfg_hba_queue_depth - total));
6329dea3101eS 		num_to_alloc = phba->cfg_hba_queue_depth - total;
6330dea3101eS 	}
63310794d601SJames Smart 	num_allocated = lpfc_new_scsi_buf_s3(vport, num_to_alloc);
63323772a991SJames Smart 	if (num_to_alloc != num_allocated) {
6333372c187bSDick Kennedy 			lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
63343772a991SJames Smart 					 "0708 Allocation request of %d "
63353772a991SJames Smart 					 "command buffers did not succeed.  "
63363772a991SJames Smart 					 "Allocated %d buffers.\n",
63373772a991SJames Smart 					 num_to_alloc, num_allocated);
6338dea3101eS 	}
63391c6f4ef5SJames Smart 	if (num_allocated > 0)
63401c6f4ef5SJames Smart 		phba->total_scsi_bufs += num_allocated;
6341dea3101eS 	return 0;
6342dea3101eS }
6343dea3101eS 
63449bad7671SJames Smart /**
63453621a710SJames Smart  * lpfc_slave_configure - scsi_host_template slave_configure entry point
63469bad7671SJames Smart  * @sdev: Pointer to scsi_device.
63479bad7671SJames Smart  *
63489bad7671SJames Smart  * This routine configures following items
63499bad7671SJames Smart  *   - Tag command queuing support for @sdev if supported.
63509bad7671SJames Smart  *   - Enable SLI polling for fcp ring if ENABLE_FCP_RING_POLLING flag is set.
63519bad7671SJames Smart  *
63529bad7671SJames Smart  * Return codes:
63539bad7671SJames Smart  *   0 - Success
63549bad7671SJames Smart  **/
6355dea3101eS static int
lpfc_slave_configure(struct scsi_device * sdev)6356dea3101eS lpfc_slave_configure(struct scsi_device *sdev)
6357dea3101eS {
63582e0fef85SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
63592e0fef85SJames Smart 	struct lpfc_hba   *phba = vport->phba;
6360dea3101eS 
6361db5ed4dfSChristoph Hellwig 	scsi_change_queue_depth(sdev, vport->cfg_lun_queue_depth);
6362dea3101eS 
6363875fbdfeSJames.Smart@Emulex.Com 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
636445ed1190SJames Smart 		lpfc_sli_handle_fast_ring_event(phba,
6365895427bdSJames Smart 			&phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ);
6366875fbdfeSJames.Smart@Emulex.Com 		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
6367875fbdfeSJames.Smart@Emulex.Com 			lpfc_poll_rearm_timer(phba);
6368875fbdfeSJames.Smart@Emulex.Com 	}
6369875fbdfeSJames.Smart@Emulex.Com 
6370dea3101eS 	return 0;
6371dea3101eS }
6372dea3101eS 
63739bad7671SJames Smart /**
63743621a710SJames Smart  * lpfc_slave_destroy - slave_destroy entry point of SHT data structure
63759bad7671SJames Smart  * @sdev: Pointer to scsi_device.
63769bad7671SJames Smart  *
63779bad7671SJames Smart  * This routine sets @sdev hostatdata filed to null.
63789bad7671SJames Smart  **/
6379dea3101eS static void
lpfc_slave_destroy(struct scsi_device * sdev)6380dea3101eS lpfc_slave_destroy(struct scsi_device *sdev)
6381dea3101eS {
6382d7c47992SJames Smart 	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
6383d7c47992SJames Smart 	struct lpfc_hba   *phba = vport->phba;
63841ba981fdSJames Smart 	unsigned long flags;
63851ba981fdSJames Smart 	struct lpfc_device_data *device_data = sdev->hostdata;
63861ba981fdSJames Smart 
6387d7c47992SJames Smart 	atomic_dec(&phba->sdev_cnt);
6388f38fa0bbSJames Smart 	if ((phba->cfg_fof) && (device_data)) {
63891ba981fdSJames Smart 		spin_lock_irqsave(&phba->devicelock, flags);
63901ba981fdSJames Smart 		device_data->available = false;
63911ba981fdSJames Smart 		if (!device_data->oas_enabled)
63921ba981fdSJames Smart 			lpfc_delete_device_data(phba, device_data);
63931ba981fdSJames Smart 		spin_unlock_irqrestore(&phba->devicelock, flags);
63941ba981fdSJames Smart 	}
6395dea3101eS 	sdev->hostdata = NULL;
6396dea3101eS 	return;
6397dea3101eS }
6398dea3101eS 
63991ba981fdSJames Smart /**
64001ba981fdSJames Smart  * lpfc_create_device_data - creates and initializes device data structure for OAS
6401eceee00eSLee Jones  * @phba: Pointer to host bus adapter structure.
64021ba981fdSJames Smart  * @vport_wwpn: Pointer to vport's wwpn information
64031ba981fdSJames Smart  * @target_wwpn: Pointer to target's wwpn information
64041ba981fdSJames Smart  * @lun: Lun on target
6405eceee00eSLee Jones  * @pri: Priority
64061ba981fdSJames Smart  * @atomic_create: Flag to indicate if memory should be allocated using the
64071ba981fdSJames Smart  *		  GFP_ATOMIC flag or not.
64081ba981fdSJames Smart  *
64091ba981fdSJames Smart  * This routine creates a device data structure which will contain identifying
64101ba981fdSJames Smart  * information for the device (host wwpn, target wwpn, lun), state of OAS,
64111ba981fdSJames Smart  * whether or not the corresponding lun is available by the system,
64121ba981fdSJames Smart  * and pointer to the rport data.
64131ba981fdSJames Smart  *
64141ba981fdSJames Smart  * Return codes:
64151ba981fdSJames Smart  *   NULL - Error
64161ba981fdSJames Smart  *   Pointer to lpfc_device_data - Success
64171ba981fdSJames Smart  **/
64181ba981fdSJames Smart struct lpfc_device_data*
lpfc_create_device_data(struct lpfc_hba * phba,struct lpfc_name * vport_wwpn,struct lpfc_name * target_wwpn,uint64_t lun,uint32_t pri,bool atomic_create)64191ba981fdSJames Smart lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
64201ba981fdSJames Smart 			struct lpfc_name *target_wwpn, uint64_t lun,
6421b5749fe1SJames Smart 			uint32_t pri, bool atomic_create)
64221ba981fdSJames Smart {
64231ba981fdSJames Smart 
64241ba981fdSJames Smart 	struct lpfc_device_data *lun_info;
64251ba981fdSJames Smart 	int memory_flags;
64261ba981fdSJames Smart 
64271ba981fdSJames Smart 	if (unlikely(!phba) || !vport_wwpn || !target_wwpn  ||
6428f38fa0bbSJames Smart 	    !(phba->cfg_fof))
64291ba981fdSJames Smart 		return NULL;
64301ba981fdSJames Smart 
64311ba981fdSJames Smart 	/* Attempt to create the device data to contain lun info */
64321ba981fdSJames Smart 
64331ba981fdSJames Smart 	if (atomic_create)
64341ba981fdSJames Smart 		memory_flags = GFP_ATOMIC;
64351ba981fdSJames Smart 	else
64361ba981fdSJames Smart 		memory_flags = GFP_KERNEL;
64371ba981fdSJames Smart 	lun_info = mempool_alloc(phba->device_data_mem_pool, memory_flags);
64381ba981fdSJames Smart 	if (!lun_info)
64391ba981fdSJames Smart 		return NULL;
64401ba981fdSJames Smart 	INIT_LIST_HEAD(&lun_info->listentry);
64411ba981fdSJames Smart 	lun_info->rport_data  = NULL;
64421ba981fdSJames Smart 	memcpy(&lun_info->device_id.vport_wwpn, vport_wwpn,
64431ba981fdSJames Smart 	       sizeof(struct lpfc_name));
64441ba981fdSJames Smart 	memcpy(&lun_info->device_id.target_wwpn, target_wwpn,
64451ba981fdSJames Smart 	       sizeof(struct lpfc_name));
64461ba981fdSJames Smart 	lun_info->device_id.lun = lun;
64471ba981fdSJames Smart 	lun_info->oas_enabled = false;
6448b5749fe1SJames Smart 	lun_info->priority = pri;
64491ba981fdSJames Smart 	lun_info->available = false;
64501ba981fdSJames Smart 	return lun_info;
64511ba981fdSJames Smart }
64521ba981fdSJames Smart 
64531ba981fdSJames Smart /**
64541ba981fdSJames Smart  * lpfc_delete_device_data - frees a device data structure for OAS
6455eceee00eSLee Jones  * @phba: Pointer to host bus adapter structure.
64561ba981fdSJames Smart  * @lun_info: Pointer to device data structure to free.
64571ba981fdSJames Smart  *
64581ba981fdSJames Smart  * This routine frees the previously allocated device data structure passed.
64591ba981fdSJames Smart  *
64601ba981fdSJames Smart  **/
64611ba981fdSJames Smart void
lpfc_delete_device_data(struct lpfc_hba * phba,struct lpfc_device_data * lun_info)64621ba981fdSJames Smart lpfc_delete_device_data(struct lpfc_hba *phba,
64631ba981fdSJames Smart 			struct lpfc_device_data *lun_info)
64641ba981fdSJames Smart {
64651ba981fdSJames Smart 
64661ba981fdSJames Smart 	if (unlikely(!phba) || !lun_info  ||
6467f38fa0bbSJames Smart 	    !(phba->cfg_fof))
64681ba981fdSJames Smart 		return;
64691ba981fdSJames Smart 
64701ba981fdSJames Smart 	if (!list_empty(&lun_info->listentry))
64711ba981fdSJames Smart 		list_del(&lun_info->listentry);
64721ba981fdSJames Smart 	mempool_free(lun_info, phba->device_data_mem_pool);
64731ba981fdSJames Smart 	return;
64741ba981fdSJames Smart }
64751ba981fdSJames Smart 
64761ba981fdSJames Smart /**
64771ba981fdSJames Smart  * __lpfc_get_device_data - returns the device data for the specified lun
6478eceee00eSLee Jones  * @phba: Pointer to host bus adapter structure.
64791ba981fdSJames Smart  * @list: Point to list to search.
64801ba981fdSJames Smart  * @vport_wwpn: Pointer to vport's wwpn information
64811ba981fdSJames Smart  * @target_wwpn: Pointer to target's wwpn information
64821ba981fdSJames Smart  * @lun: Lun on target
64831ba981fdSJames Smart  *
64841ba981fdSJames Smart  * This routine searches the list passed for the specified lun's device data.
64851ba981fdSJames Smart  * This function does not hold locks, it is the responsibility of the caller
64861ba981fdSJames Smart  * to ensure the proper lock is held before calling the function.
64871ba981fdSJames Smart  *
64881ba981fdSJames Smart  * Return codes:
64891ba981fdSJames Smart  *   NULL - Error
64901ba981fdSJames Smart  *   Pointer to lpfc_device_data - Success
64911ba981fdSJames Smart  **/
64921ba981fdSJames Smart struct lpfc_device_data*
__lpfc_get_device_data(struct lpfc_hba * phba,struct list_head * list,struct lpfc_name * vport_wwpn,struct lpfc_name * target_wwpn,uint64_t lun)64931ba981fdSJames Smart __lpfc_get_device_data(struct lpfc_hba *phba, struct list_head *list,
64941ba981fdSJames Smart 		       struct lpfc_name *vport_wwpn,
64951ba981fdSJames Smart 		       struct lpfc_name *target_wwpn, uint64_t lun)
64961ba981fdSJames Smart {
64971ba981fdSJames Smart 
64981ba981fdSJames Smart 	struct lpfc_device_data *lun_info;
64991ba981fdSJames Smart 
65001ba981fdSJames Smart 	if (unlikely(!phba) || !list || !vport_wwpn || !target_wwpn ||
6501f38fa0bbSJames Smart 	    !phba->cfg_fof)
65021ba981fdSJames Smart 		return NULL;
65031ba981fdSJames Smart 
65041ba981fdSJames Smart 	/* Check to see if the lun is already enabled for OAS. */
65051ba981fdSJames Smart 
65061ba981fdSJames Smart 	list_for_each_entry(lun_info, list, listentry) {
65071ba981fdSJames Smart 		if ((memcmp(&lun_info->device_id.vport_wwpn, vport_wwpn,
65081ba981fdSJames Smart 			    sizeof(struct lpfc_name)) == 0) &&
65091ba981fdSJames Smart 		    (memcmp(&lun_info->device_id.target_wwpn, target_wwpn,
65101ba981fdSJames Smart 			    sizeof(struct lpfc_name)) == 0) &&
65111ba981fdSJames Smart 		    (lun_info->device_id.lun == lun))
65121ba981fdSJames Smart 			return lun_info;
65131ba981fdSJames Smart 	}
65141ba981fdSJames Smart 
65151ba981fdSJames Smart 	return NULL;
65161ba981fdSJames Smart }
65171ba981fdSJames Smart 
65181ba981fdSJames Smart /**
65191ba981fdSJames Smart  * lpfc_find_next_oas_lun - searches for the next oas lun
6520eceee00eSLee Jones  * @phba: Pointer to host bus adapter structure.
65211ba981fdSJames Smart  * @vport_wwpn: Pointer to vport's wwpn information
65221ba981fdSJames Smart  * @target_wwpn: Pointer to target's wwpn information
65231ba981fdSJames Smart  * @starting_lun: Pointer to the lun to start searching for
65241ba981fdSJames Smart  * @found_vport_wwpn: Pointer to the found lun's vport wwpn information
65251ba981fdSJames Smart  * @found_target_wwpn: Pointer to the found lun's target wwpn information
65261ba981fdSJames Smart  * @found_lun: Pointer to the found lun.
65271ba981fdSJames Smart  * @found_lun_status: Pointer to status of the found lun.
6528eceee00eSLee Jones  * @found_lun_pri: Pointer to priority of the found lun.
65291ba981fdSJames Smart  *
65301ba981fdSJames Smart  * This routine searches the luns list for the specified lun
65311ba981fdSJames Smart  * or the first lun for the vport/target.  If the vport wwpn contains
65321ba981fdSJames Smart  * a zero value then a specific vport is not specified. In this case
65331ba981fdSJames Smart  * any vport which contains the lun will be considered a match.  If the
65341ba981fdSJames Smart  * target wwpn contains a zero value then a specific target is not specified.
65351ba981fdSJames Smart  * In this case any target which contains the lun will be considered a
65361ba981fdSJames Smart  * match.  If the lun is found, the lun, vport wwpn, target wwpn and lun status
65371ba981fdSJames Smart  * are returned.  The function will also return the next lun if available.
65381ba981fdSJames Smart  * If the next lun is not found, starting_lun parameter will be set to
65391ba981fdSJames Smart  * NO_MORE_OAS_LUN.
65401ba981fdSJames Smart  *
65411ba981fdSJames Smart  * Return codes:
65421ba981fdSJames Smart  *   non-0 - Error
65431ba981fdSJames Smart  *   0 - Success
65441ba981fdSJames Smart  **/
65451ba981fdSJames Smart bool
lpfc_find_next_oas_lun(struct lpfc_hba * phba,struct lpfc_name * vport_wwpn,struct lpfc_name * target_wwpn,uint64_t * starting_lun,struct lpfc_name * found_vport_wwpn,struct lpfc_name * found_target_wwpn,uint64_t * found_lun,uint32_t * found_lun_status,uint32_t * found_lun_pri)65461ba981fdSJames Smart lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
65471ba981fdSJames Smart 		       struct lpfc_name *target_wwpn, uint64_t *starting_lun,
65481ba981fdSJames Smart 		       struct lpfc_name *found_vport_wwpn,
65491ba981fdSJames Smart 		       struct lpfc_name *found_target_wwpn,
65501ba981fdSJames Smart 		       uint64_t *found_lun,
6551b5749fe1SJames Smart 		       uint32_t *found_lun_status,
6552b5749fe1SJames Smart 		       uint32_t *found_lun_pri)
65531ba981fdSJames Smart {
65541ba981fdSJames Smart 
65551ba981fdSJames Smart 	unsigned long flags;
65561ba981fdSJames Smart 	struct lpfc_device_data *lun_info;
65571ba981fdSJames Smart 	struct lpfc_device_id *device_id;
65581ba981fdSJames Smart 	uint64_t lun;
65591ba981fdSJames Smart 	bool found = false;
65601ba981fdSJames Smart 
65611ba981fdSJames Smart 	if (unlikely(!phba) || !vport_wwpn || !target_wwpn ||
65621ba981fdSJames Smart 	    !starting_lun || !found_vport_wwpn ||
65631ba981fdSJames Smart 	    !found_target_wwpn || !found_lun || !found_lun_status ||
65641ba981fdSJames Smart 	    (*starting_lun == NO_MORE_OAS_LUN) ||
6565f38fa0bbSJames Smart 	    !phba->cfg_fof)
65661ba981fdSJames Smart 		return false;
65671ba981fdSJames Smart 
65681ba981fdSJames Smart 	lun = *starting_lun;
65691ba981fdSJames Smart 	*found_lun = NO_MORE_OAS_LUN;
65701ba981fdSJames Smart 	*starting_lun = NO_MORE_OAS_LUN;
65711ba981fdSJames Smart 
65721ba981fdSJames Smart 	/* Search for lun or the lun closet in value */
65731ba981fdSJames Smart 
65741ba981fdSJames Smart 	spin_lock_irqsave(&phba->devicelock, flags);
65751ba981fdSJames Smart 	list_for_each_entry(lun_info, &phba->luns, listentry) {
65761ba981fdSJames Smart 		if (((wwn_to_u64(vport_wwpn->u.wwn) == 0) ||
65771ba981fdSJames Smart 		     (memcmp(&lun_info->device_id.vport_wwpn, vport_wwpn,
65781ba981fdSJames Smart 			    sizeof(struct lpfc_name)) == 0)) &&
65791ba981fdSJames Smart 		    ((wwn_to_u64(target_wwpn->u.wwn) == 0) ||
65801ba981fdSJames Smart 		     (memcmp(&lun_info->device_id.target_wwpn, target_wwpn,
65811ba981fdSJames Smart 			    sizeof(struct lpfc_name)) == 0)) &&
65821ba981fdSJames Smart 		    (lun_info->oas_enabled)) {
65831ba981fdSJames Smart 			device_id = &lun_info->device_id;
65841ba981fdSJames Smart 			if ((!found) &&
65851ba981fdSJames Smart 			    ((lun == FIND_FIRST_OAS_LUN) ||
65861ba981fdSJames Smart 			     (device_id->lun == lun))) {
65871ba981fdSJames Smart 				*found_lun = device_id->lun;
65881ba981fdSJames Smart 				memcpy(found_vport_wwpn,
65891ba981fdSJames Smart 				       &device_id->vport_wwpn,
65901ba981fdSJames Smart 				       sizeof(struct lpfc_name));
65911ba981fdSJames Smart 				memcpy(found_target_wwpn,
65921ba981fdSJames Smart 				       &device_id->target_wwpn,
65931ba981fdSJames Smart 				       sizeof(struct lpfc_name));
65941ba981fdSJames Smart 				if (lun_info->available)
65951ba981fdSJames Smart 					*found_lun_status =
65961ba981fdSJames Smart 						OAS_LUN_STATUS_EXISTS;
65971ba981fdSJames Smart 				else
65981ba981fdSJames Smart 					*found_lun_status = 0;
6599b5749fe1SJames Smart 				*found_lun_pri = lun_info->priority;
66001ba981fdSJames Smart 				if (phba->cfg_oas_flags & OAS_FIND_ANY_VPORT)
66011ba981fdSJames Smart 					memset(vport_wwpn, 0x0,
66021ba981fdSJames Smart 					       sizeof(struct lpfc_name));
66031ba981fdSJames Smart 				if (phba->cfg_oas_flags & OAS_FIND_ANY_TARGET)
66041ba981fdSJames Smart 					memset(target_wwpn, 0x0,
66051ba981fdSJames Smart 					       sizeof(struct lpfc_name));
66061ba981fdSJames Smart 				found = true;
66071ba981fdSJames Smart 			} else if (found) {
66081ba981fdSJames Smart 				*starting_lun = device_id->lun;
66091ba981fdSJames Smart 				memcpy(vport_wwpn, &device_id->vport_wwpn,
66101ba981fdSJames Smart 				       sizeof(struct lpfc_name));
66111ba981fdSJames Smart 				memcpy(target_wwpn, &device_id->target_wwpn,
66121ba981fdSJames Smart 				       sizeof(struct lpfc_name));
66131ba981fdSJames Smart 				break;
66141ba981fdSJames Smart 			}
66151ba981fdSJames Smart 		}
66161ba981fdSJames Smart 	}
66171ba981fdSJames Smart 	spin_unlock_irqrestore(&phba->devicelock, flags);
66181ba981fdSJames Smart 	return found;
66191ba981fdSJames Smart }
66201ba981fdSJames Smart 
66211ba981fdSJames Smart /**
66221ba981fdSJames Smart  * lpfc_enable_oas_lun - enables a lun for OAS operations
6623eceee00eSLee Jones  * @phba: Pointer to host bus adapter structure.
66241ba981fdSJames Smart  * @vport_wwpn: Pointer to vport's wwpn information
66251ba981fdSJames Smart  * @target_wwpn: Pointer to target's wwpn information
66261ba981fdSJames Smart  * @lun: Lun
6627eceee00eSLee Jones  * @pri: Priority
66281ba981fdSJames Smart  *
66291ba981fdSJames Smart  * This routine enables a lun for oas operations.  The routines does so by
66301ba981fdSJames Smart  * doing the following :
66311ba981fdSJames Smart  *
66321ba981fdSJames Smart  *   1) Checks to see if the device data for the lun has been created.
66331ba981fdSJames Smart  *   2) If found, sets the OAS enabled flag if not set and returns.
66341ba981fdSJames Smart  *   3) Otherwise, creates a device data structure.
66351ba981fdSJames Smart  *   4) If successfully created, indicates the device data is for an OAS lun,
66361ba981fdSJames Smart  *   indicates the lun is not available and add to the list of luns.
66371ba981fdSJames Smart  *
66381ba981fdSJames Smart  * Return codes:
66391ba981fdSJames Smart  *   false - Error
66401ba981fdSJames Smart  *   true - Success
66411ba981fdSJames Smart  **/
66421ba981fdSJames Smart bool
lpfc_enable_oas_lun(struct lpfc_hba * phba,struct lpfc_name * vport_wwpn,struct lpfc_name * target_wwpn,uint64_t lun,uint8_t pri)66431ba981fdSJames Smart lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
6644c92c841cSJames Smart 		    struct lpfc_name *target_wwpn, uint64_t lun, uint8_t pri)
66451ba981fdSJames Smart {
66461ba981fdSJames Smart 
66471ba981fdSJames Smart 	struct lpfc_device_data *lun_info;
66481ba981fdSJames Smart 	unsigned long flags;
66491ba981fdSJames Smart 
66501ba981fdSJames Smart 	if (unlikely(!phba) || !vport_wwpn || !target_wwpn ||
6651f38fa0bbSJames Smart 	    !phba->cfg_fof)
66521ba981fdSJames Smart 		return false;
66531ba981fdSJames Smart 
66541ba981fdSJames Smart 	spin_lock_irqsave(&phba->devicelock, flags);
66551ba981fdSJames Smart 
66561ba981fdSJames Smart 	/* Check to see if the device data for the lun has been created */
66571ba981fdSJames Smart 	lun_info = __lpfc_get_device_data(phba, &phba->luns, vport_wwpn,
66581ba981fdSJames Smart 					  target_wwpn, lun);
66591ba981fdSJames Smart 	if (lun_info) {
66601ba981fdSJames Smart 		if (!lun_info->oas_enabled)
66611ba981fdSJames Smart 			lun_info->oas_enabled = true;
6662b5749fe1SJames Smart 		lun_info->priority = pri;
66631ba981fdSJames Smart 		spin_unlock_irqrestore(&phba->devicelock, flags);
66641ba981fdSJames Smart 		return true;
66651ba981fdSJames Smart 	}
66661ba981fdSJames Smart 
66671ba981fdSJames Smart 	/* Create an lun info structure and add to list of luns */
66681ba981fdSJames Smart 	lun_info = lpfc_create_device_data(phba, vport_wwpn, target_wwpn, lun,
66692d71dc8eSJames Smart 					   pri, true);
66701ba981fdSJames Smart 	if (lun_info) {
66711ba981fdSJames Smart 		lun_info->oas_enabled = true;
6672c92c841cSJames Smart 		lun_info->priority = pri;
66731ba981fdSJames Smart 		lun_info->available = false;
66741ba981fdSJames Smart 		list_add_tail(&lun_info->listentry, &phba->luns);
66751ba981fdSJames Smart 		spin_unlock_irqrestore(&phba->devicelock, flags);
66761ba981fdSJames Smart 		return true;
66771ba981fdSJames Smart 	}
66781ba981fdSJames Smart 	spin_unlock_irqrestore(&phba->devicelock, flags);
66791ba981fdSJames Smart 	return false;
66801ba981fdSJames Smart }
66811ba981fdSJames Smart 
66821ba981fdSJames Smart /**
66831ba981fdSJames Smart  * lpfc_disable_oas_lun - disables a lun for OAS operations
6684eceee00eSLee Jones  * @phba: Pointer to host bus adapter structure.
66851ba981fdSJames Smart  * @vport_wwpn: Pointer to vport's wwpn information
66861ba981fdSJames Smart  * @target_wwpn: Pointer to target's wwpn information
66871ba981fdSJames Smart  * @lun: Lun
6688eceee00eSLee Jones  * @pri: Priority
66891ba981fdSJames Smart  *
66901ba981fdSJames Smart  * This routine disables a lun for oas operations.  The routines does so by
66911ba981fdSJames Smart  * doing the following :
66921ba981fdSJames Smart  *
66931ba981fdSJames Smart  *   1) Checks to see if the device data for the lun is created.
66941ba981fdSJames Smart  *   2) If present, clears the flag indicating this lun is for OAS.
66951ba981fdSJames Smart  *   3) If the lun is not available by the system, the device data is
66961ba981fdSJames Smart  *   freed.
66971ba981fdSJames Smart  *
66981ba981fdSJames Smart  * Return codes:
66991ba981fdSJames Smart  *   false - Error
67001ba981fdSJames Smart  *   true - Success
67011ba981fdSJames Smart  **/
67021ba981fdSJames Smart bool
lpfc_disable_oas_lun(struct lpfc_hba * phba,struct lpfc_name * vport_wwpn,struct lpfc_name * target_wwpn,uint64_t lun,uint8_t pri)67031ba981fdSJames Smart lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
6704b5749fe1SJames Smart 		     struct lpfc_name *target_wwpn, uint64_t lun, uint8_t pri)
67051ba981fdSJames Smart {
67061ba981fdSJames Smart 
67071ba981fdSJames Smart 	struct lpfc_device_data *lun_info;
67081ba981fdSJames Smart 	unsigned long flags;
67091ba981fdSJames Smart 
67101ba981fdSJames Smart 	if (unlikely(!phba) || !vport_wwpn || !target_wwpn ||
6711f38fa0bbSJames Smart 	    !phba->cfg_fof)
67121ba981fdSJames Smart 		return false;
67131ba981fdSJames Smart 
67141ba981fdSJames Smart 	spin_lock_irqsave(&phba->devicelock, flags);
67151ba981fdSJames Smart 
67161ba981fdSJames Smart 	/* Check to see if the lun is available. */
67171ba981fdSJames Smart 	lun_info = __lpfc_get_device_data(phba,
67181ba981fdSJames Smart 					  &phba->luns, vport_wwpn,
67191ba981fdSJames Smart 					  target_wwpn, lun);
67201ba981fdSJames Smart 	if (lun_info) {
67211ba981fdSJames Smart 		lun_info->oas_enabled = false;
6722b5749fe1SJames Smart 		lun_info->priority = pri;
67231ba981fdSJames Smart 		if (!lun_info->available)
67241ba981fdSJames Smart 			lpfc_delete_device_data(phba, lun_info);
67251ba981fdSJames Smart 		spin_unlock_irqrestore(&phba->devicelock, flags);
67261ba981fdSJames Smart 		return true;
67271ba981fdSJames Smart 	}
67281ba981fdSJames Smart 
67291ba981fdSJames Smart 	spin_unlock_irqrestore(&phba->devicelock, flags);
67301ba981fdSJames Smart 	return false;
67311ba981fdSJames Smart }
673292d7f7b0SJames Smart 
6733895427bdSJames Smart static int
lpfc_no_command(struct Scsi_Host * shost,struct scsi_cmnd * cmnd)6734895427bdSJames Smart lpfc_no_command(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
6735895427bdSJames Smart {
6736895427bdSJames Smart 	return SCSI_MLQUEUE_HOST_BUSY;
6737895427bdSJames Smart }
6738895427bdSJames Smart 
6739895427bdSJames Smart static int
lpfc_no_slave(struct scsi_device * sdev)6740895427bdSJames Smart lpfc_no_slave(struct scsi_device *sdev)
6741895427bdSJames Smart {
6742895427bdSJames Smart 	return -ENODEV;
6743895427bdSJames Smart }
6744895427bdSJames Smart 
6745895427bdSJames Smart struct scsi_host_template lpfc_template_nvme = {
6746895427bdSJames Smart 	.module			= THIS_MODULE,
6747895427bdSJames Smart 	.name			= LPFC_DRIVER_NAME,
6748895427bdSJames Smart 	.proc_name		= LPFC_DRIVER_NAME,
6749895427bdSJames Smart 	.info			= lpfc_info,
6750895427bdSJames Smart 	.queuecommand		= lpfc_no_command,
6751895427bdSJames Smart 	.slave_alloc		= lpfc_no_slave,
6752895427bdSJames Smart 	.slave_configure	= lpfc_no_slave,
6753895427bdSJames Smart 	.scan_finished		= lpfc_scan_finished,
6754895427bdSJames Smart 	.this_id		= -1,
6755895427bdSJames Smart 	.sg_tablesize		= 1,
6756895427bdSJames Smart 	.cmd_per_lun		= 1,
675708adfa75SBart Van Assche 	.shost_groups		= lpfc_hba_groups,
67587c30bb62SJames Smart 	.max_sectors		= 0xFFFFFFFF,
6759895427bdSJames Smart 	.vendor_id		= LPFC_NL_VENDOR_ID,
6760895427bdSJames Smart 	.track_queue_depth	= 0,
6761895427bdSJames Smart };
6762895427bdSJames Smart 
6763dea3101eS struct scsi_host_template lpfc_template = {
6764dea3101eS 	.module			= THIS_MODULE,
6765dea3101eS 	.name			= LPFC_DRIVER_NAME,
676608dcd4cfSJames Smart 	.proc_name		= LPFC_DRIVER_NAME,
6767dea3101eS 	.info			= lpfc_info,
6768dea3101eS 	.queuecommand		= lpfc_queuecommand,
6769b6a05c82SChristoph Hellwig 	.eh_timed_out		= fc_eh_timed_out,
67707f3a79a7SMuneendra Kumar 	.eh_should_retry_cmd    = fc_eh_should_retry_cmd,
6771dea3101eS 	.eh_abort_handler	= lpfc_abort_handler,
67727054a606SJames Smart 	.eh_device_reset_handler = lpfc_device_reset_handler,
6773bbb9d180SJames Smart 	.eh_target_reset_handler = lpfc_target_reset_handler,
677427b01b82SJames Smart 	.eh_host_reset_handler  = lpfc_host_reset_handler,
6775dea3101eS 	.slave_alloc		= lpfc_slave_alloc,
6776dea3101eS 	.slave_configure	= lpfc_slave_configure,
6777dea3101eS 	.slave_destroy		= lpfc_slave_destroy,
677847a8617cSJames Smart 	.scan_finished		= lpfc_scan_finished,
6779dea3101eS 	.this_id		= -1,
678083108bd3SJames Smart 	.sg_tablesize		= LPFC_DEFAULT_SG_SEG_CNT,
6781dea3101eS 	.cmd_per_lun		= LPFC_CMD_PER_LUN,
678208adfa75SBart Van Assche 	.shost_groups		= lpfc_hba_groups,
67837c30bb62SJames Smart 	.max_sectors		= 0xFFFFFFFF,
6784f1c3b0fcSJames Smart 	.vendor_id		= LPFC_NL_VENDOR_ID,
6785db5ed4dfSChristoph Hellwig 	.change_queue_depth	= scsi_change_queue_depth,
6786c40ecc12SChristoph Hellwig 	.track_queue_depth	= 1,
6787dea3101eS };
67886e5c5d24SJames Smart 
67896e5c5d24SJames Smart struct scsi_host_template lpfc_vport_template = {
67906e5c5d24SJames Smart 	.module			= THIS_MODULE,
67916e5c5d24SJames Smart 	.name			= LPFC_DRIVER_NAME,
67926e5c5d24SJames Smart 	.proc_name		= LPFC_DRIVER_NAME,
67936e5c5d24SJames Smart 	.info			= lpfc_info,
67946e5c5d24SJames Smart 	.queuecommand		= lpfc_queuecommand,
67956e5c5d24SJames Smart 	.eh_timed_out		= fc_eh_timed_out,
67966e5c5d24SJames Smart 	.eh_should_retry_cmd    = fc_eh_should_retry_cmd,
67976e5c5d24SJames Smart 	.eh_abort_handler	= lpfc_abort_handler,
67986e5c5d24SJames Smart 	.eh_device_reset_handler = lpfc_device_reset_handler,
67996e5c5d24SJames Smart 	.eh_target_reset_handler = lpfc_target_reset_handler,
68006e5c5d24SJames Smart 	.eh_bus_reset_handler	= NULL,
68016e5c5d24SJames Smart 	.eh_host_reset_handler	= NULL,
68026e5c5d24SJames Smart 	.slave_alloc		= lpfc_slave_alloc,
68036e5c5d24SJames Smart 	.slave_configure	= lpfc_slave_configure,
68046e5c5d24SJames Smart 	.slave_destroy		= lpfc_slave_destroy,
68056e5c5d24SJames Smart 	.scan_finished		= lpfc_scan_finished,
68066e5c5d24SJames Smart 	.this_id		= -1,
68076e5c5d24SJames Smart 	.sg_tablesize		= LPFC_DEFAULT_SG_SEG_CNT,
68086e5c5d24SJames Smart 	.cmd_per_lun		= LPFC_CMD_PER_LUN,
68096e5c5d24SJames Smart 	.shost_groups		= lpfc_vport_groups,
68106e5c5d24SJames Smart 	.max_sectors		= 0xFFFFFFFF,
68116e5c5d24SJames Smart 	.vendor_id		= 0,
68126e5c5d24SJames Smart 	.change_queue_depth	= scsi_change_queue_depth,
68136e5c5d24SJames Smart 	.track_queue_depth	= 1,
68146e5c5d24SJames Smart };
6815