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