[PATCH 03/15] lpfc: refactor mailbox structure context fields

2018-11-29 Thread James Smart
The driver data structure for managing a mailbox command contained
two context fields. Unfortunately, the context were considered "generic"
to be used at the whim of the command code.  Of course, one section of
code used fields this way, while another did it that way, and eventually
there were mixups.

Refactored the structure so that the generic contexts become a node
context and a buffer context and all code standardizes on their use.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c  | 10 ++---
 drivers/scsi/lpfc/lpfc_bsg.c   | 20 +-
 drivers/scsi/lpfc/lpfc_els.c   | 64 +++
 drivers/scsi/lpfc/lpfc_hbadisc.c   | 76 ++---
 drivers/scsi/lpfc/lpfc_init.c  |  6 +--
 drivers/scsi/lpfc/lpfc_mbox.c  | 38 +--
 drivers/scsi/lpfc/lpfc_mem.c   |  6 +--
 drivers/scsi/lpfc/lpfc_nportdisc.c | 18 -
 drivers/scsi/lpfc/lpfc_sli.c   | 78 --
 drivers/scsi/lpfc/lpfc_sli.h   |  6 +--
 drivers/scsi/lpfc/lpfc_vport.c |  4 +-
 11 files changed, 165 insertions(+), 161 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index fdc706fc0209..5f30e40bcc0a 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1688,7 +1688,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
pmb = >u.mb;
pmb->mbxCommand = MBX_READ_CONFIG;
pmb->mbxOwner = OWN_HOST;
-   pmboxq->context1 = NULL;
+   pmboxq->ctx_buf = NULL;
 
if (phba->pport->fc_flag & FC_OFFLINE_MODE)
rc = MBX_NOT_FINISHED;
@@ -6219,7 +6219,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
pmb = >u.mb;
pmb->mbxCommand = MBX_READ_STATUS;
pmb->mbxOwner = OWN_HOST;
-   pmboxq->context1 = NULL;
+   pmboxq->ctx_buf = NULL;
pmboxq->vport = vport;
 
if (vport->fc_flag & FC_OFFLINE_MODE)
@@ -6251,7 +6251,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
pmb->mbxCommand = MBX_READ_LNK_STAT;
pmb->mbxOwner = OWN_HOST;
-   pmboxq->context1 = NULL;
+   pmboxq->ctx_buf = NULL;
pmboxq->vport = vport;
 
if (vport->fc_flag & FC_OFFLINE_MODE)
@@ -6331,7 +6331,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
pmb->mbxCommand = MBX_READ_STATUS;
pmb->mbxOwner = OWN_HOST;
pmb->un.varWords[0] = 0x1; /* reset request */
-   pmboxq->context1 = NULL;
+   pmboxq->ctx_buf = NULL;
pmboxq->vport = vport;
 
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
@@ -6349,7 +6349,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
pmb->mbxCommand = MBX_READ_LNK_STAT;
pmb->mbxOwner = OWN_HOST;
-   pmboxq->context1 = NULL;
+   pmboxq->ctx_buf = NULL;
pmboxq->vport = vport;
 
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 9b8edfb06cb0..b573fd00e650 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2501,9 +2501,9 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, 
uint16_t *rpi)
return -ENOMEM;
}
 
-   dmabuff = (struct lpfc_dmabuf *) mbox->context1;
-   mbox->context1 = NULL;
-   mbox->context2 = NULL;
+   dmabuff = (struct lpfc_dmabuf *)mbox->ctx_buf;
+   mbox->ctx_buf = NULL;
+   mbox->ctx_ndlp = NULL;
status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
 
if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
@@ -3388,7 +3388,7 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *pmboxq)
unsigned long flags;
uint8_t *pmb, *pmb_buf;
 
-   dd_data = pmboxq->context1;
+   dd_data = pmboxq->ctx_ndlp;
 
/*
 * The outgoing buffer is readily referred from the dma buffer,
@@ -3573,7 +3573,7 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *pmboxq)
struct lpfc_sli_config_mbox *sli_cfg_mbx;
uint8_t *pmbx;
 
-   dd_data = pmboxq->context1;
+   dd_data = pmboxq->ctx_buf;
 
/* Determine if job has been aborted */
spin_lock_irqsave(>ct_ev_lock, flags);
@@ -3960,7 +3960,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, 
struct bsg_job *job,
pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl;
 
/* context fields to callback function */
-   pmboxq->context1 = dd_data;
+   pmboxq->ctx_buf = dd_data;
dd_data->type = TYPE_MBOX;
dd_data->set_job = job;
dd_data->context_un.mbox.pmboxq = pmboxq;
@@ -4131,7 +4131,7 @@ lpfc_bsg_sli_cfg_writ

[PATCH 14/15] lpfc: Fix dif and first burst use in write commands

2018-11-29 Thread James Smart
When dif and first burst is used in a write command wqe, the driver was
not properly setting fields in the io command request. This resulted
in no dif bytes being sent and invalid xfer_rdy's, resulting in the
io being aborted by the hardware.

Correct the wqe initializaton when both dif and first burst are used.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index e8c6f5de4440..14a62253b099 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -2734,6 +2734,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
int prot_group_type = 0;
int fcpdl;
+   struct lpfc_vport *vport = phba->pport;
 
/*
 * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd
@@ -2839,6 +2840,14 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
 */
iocb_cmd->un.fcpi.fcpi_parm = fcpdl;
 
+   /*
+* For First burst, we may need to adjust the initial transfer
+* length for DIF
+*/
+   if (iocb_cmd->un.fcpi.fcpi_XRdy &&
+   (fcpdl < vport->cfg_first_burst_size))
+   iocb_cmd->un.fcpi.fcpi_XRdy = fcpdl;
+
return 0;
 err:
if (lpfc_cmd->seg_cnt)
@@ -3403,6 +3412,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
int prot_group_type = 0;
int fcpdl;
+   struct lpfc_vport *vport = phba->pport;
 
/*
 * Start the lpfc command prep by bumping the sgl beyond fcp_cmnd
@@ -3519,6 +3529,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
iocb_cmd->un.fcpi.fcpi_parm = fcpdl;
 
/*
+* For First burst, we may need to adjust the initial transfer
+* length for DIF
+*/
+   if (iocb_cmd->un.fcpi.fcpi_XRdy &&
+   (fcpdl < vport->cfg_first_burst_size))
+   iocb_cmd->un.fcpi.fcpi_XRdy = fcpdl;
+
+   /*
 * If the OAS driver feature is enabled and the lun is enabled for
 * OAS, set the oas iocb related flags.
 */
-- 
2.13.7



[PATCH 11/15] lpfc: Correct code setting non existent bits in sli4 ABORT WQE

2018-11-29 Thread James Smart
Driver is setting bits in word 10 of the SLI4 ABORT WQE (the wqid).
The field was a carry over from a prior SLI revision. The field does
not exist in SLI4, and the action may result in an overlap with
future definition of the WQE.

Remove the setting of WQID in the ABORT WQE.

Also cleaned up WQE field settings - initialize to zero, don't bother
to set fields to zero.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nvme.c |  2 --
 drivers/scsi/lpfc/lpfc_sli.c  | 14 +++---
 2 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index ba831def9301..4c66b19e6199 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1855,7 +1855,6 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port 
*pnvme_lport,
bf_set(abort_cmd_criteria, _wqe->abort_cmd, T_XRI_TAG);
 
/* word 7 */
-   bf_set(wqe_ct, _wqe->abort_cmd.wqe_com, 0);
bf_set(wqe_cmnd, _wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
bf_set(wqe_class, _wqe->abort_cmd.wqe_com,
   nvmereq_wqe->iocb.ulpClass);
@@ -1870,7 +1869,6 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port 
*pnvme_lport,
   abts_buf->iotag);
 
/* word 10 */
-   bf_set(wqe_wqid, _wqe->abort_cmd.wqe_com, nvmereq_wqe->hba_wqidx);
bf_set(wqe_qosd, _wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_lenloc, _wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
 
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 9821ab81c2f9..760b819f690a 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -11328,19 +11328,12 @@ lpfc_sli4_abort_nvme_io(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
 
/* Complete prepping the abort wqe and issue to the FW. */
abts_wqe = >wqe;
-   bf_set(abort_cmd_ia, _wqe->abort_cmd, 0);
-   bf_set(abort_cmd_criteria, _wqe->abort_cmd, T_XRI_TAG);
-
-   /* Explicitly set reserved fields to zero.*/
-   abts_wqe->abort_cmd.rsrvd4 = 0;
-   abts_wqe->abort_cmd.rsrvd5 = 0;
 
-   /* WQE Common - word 6.  Context is XRI tag.  Set 0. */
-   bf_set(wqe_xri_tag, _wqe->abort_cmd.wqe_com, 0);
-   bf_set(wqe_ctxt_tag, _wqe->abort_cmd.wqe_com, 0);
+   /* Clear any stale WQE contents */
+   memset(abts_wqe, 0, sizeof(union lpfc_wqe));
+   bf_set(abort_cmd_criteria, _wqe->abort_cmd, T_XRI_TAG);
 
/* word 7 */
-   bf_set(wqe_ct, _wqe->abort_cmd.wqe_com, 0);
bf_set(wqe_cmnd, _wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
bf_set(wqe_class, _wqe->abort_cmd.wqe_com,
   cmdiocb->iocb.ulpClass);
@@ -11355,7 +11348,6 @@ lpfc_sli4_abort_nvme_io(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
   abtsiocbp->iotag);
 
/* word 10 */
-   bf_set(wqe_wqid, _wqe->abort_cmd.wqe_com, cmdiocb->hba_wqidx);
bf_set(wqe_qosd, _wqe->abort_cmd.wqe_com, 1);
bf_set(wqe_lenloc, _wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
 
-- 
2.13.7



[PATCH 05/15] lpfc: Fix a duplicate 0711 log message number.

2018-11-29 Thread James Smart
Renumber one of the 0711 log messages so there isn't a duplication.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 4fa6703a9ec9..e8c6f5de4440 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4163,7 +4163,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *pIocbIn,
/* If pCmd was set to NULL from abort path, do not call scsi_done */
if (xchg(_cmd->pCmd, NULL) == NULL) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
-"0711 FCP cmd already NULL, sid: 0x%06x, "
+"5688 FCP cmd already NULL, sid: 0x%06x, "
 "did: 0x%06x, oxid: 0x%04x\n",
 vport->fc_myDID,
 (pnode) ? pnode->nlp_DID : 0,
-- 
2.13.7



[PATCH 08/15] lpfc: rport port swap discovery issue.

2018-11-29 Thread James Smart
Two initiator ports were cable swapped and after swap both went down.
the driver internally swaps the nlp nodes based on matching node wwn's
but not the same nport id as before. After detecting a change in the nodes
RPI, the driver sends an UNREG_RPI command and clears the
NLP_RPI_REGISTERED flag, then swaps the node information with the other
node. But the other node's NLP_RPI_REGISTERED flag is also cleared, but
it is done so without an UNREG_RPI being sent, which causes the later
REG_RPI for that other node to fail as the hardware believes its still
registered.

Additionally, if the node swap occurred while the two nodes had PLOGI's
in flight, the fc4_types weren't properly getting swapped such that when
the PLOGIs commpleted and PRLI's were then sent, the PRLI's acted on bad
protocol types so the PRLI was for the wrong protocol. NVME devices saw
SCSI FCP PRLIs and vice versa.

Clean up the node swap so that the NLP_RPI_REGISTERED flag is handled
properly.

Fix the handling of the fc4_types when the nodes are swapped as well

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c | 43 +++
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 3f21338d95d1..e4cf648c951b 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1538,7 +1538,9 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
struct serv_parm *sp;
uint8_t  name[sizeof(struct lpfc_name)];
uint32_t rc, keepDID = 0, keep_nlp_flag = 0;
+   uint32_t keep_new_nlp_flag = 0;
uint16_t keep_nlp_state;
+   u32 keep_nlp_fc4_type = 0;
struct lpfc_nvme_rport *keep_nrport = NULL;
int  put_node;
int  put_rport;
@@ -1630,8 +1632,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
 * would have updated nlp_fc4_type in ndlp, so we must ensure
 * new_ndlp has the right value.
 */
-   if (vport->fc_flag & FC_FABRIC)
+   if (vport->fc_flag & FC_FABRIC) {
+   keep_nlp_fc4_type = new_ndlp->nlp_fc4_type;
new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type;
+   }
 
lpfc_unreg_rpi(vport, new_ndlp);
new_ndlp->nlp_DID = ndlp->nlp_DID;
@@ -1642,20 +1646,35 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, 
uint32_t *prsp,
   phba->cfg_rrq_xri_bitmap_sz);
 
spin_lock_irq(shost->host_lock);
-   keep_nlp_flag = new_ndlp->nlp_flag;
+   keep_new_nlp_flag = new_ndlp->nlp_flag;
+   keep_nlp_flag = ndlp->nlp_flag;
new_ndlp->nlp_flag = ndlp->nlp_flag;
 
/* if new_ndlp had NLP_UNREG_INP set, keep it */
-   if (keep_nlp_flag & NLP_UNREG_INP)
+   if (keep_new_nlp_flag & NLP_UNREG_INP)
new_ndlp->nlp_flag |= NLP_UNREG_INP;
else
new_ndlp->nlp_flag &= ~NLP_UNREG_INP;
 
+   /* if new_ndlp had NLP_RPI_REGISTERED set, keep it */
+   if (keep_new_nlp_flag & NLP_RPI_REGISTERED)
+   new_ndlp->nlp_flag |= NLP_RPI_REGISTERED;
+   else
+   new_ndlp->nlp_flag &= ~NLP_RPI_REGISTERED;
+
+   ndlp->nlp_flag = keep_new_nlp_flag;
+
/* if ndlp had NLP_UNREG_INP set, keep it */
-   if (ndlp->nlp_flag & NLP_UNREG_INP)
-   ndlp->nlp_flag = keep_nlp_flag | NLP_UNREG_INP;
+   if (keep_nlp_flag & NLP_UNREG_INP)
+   ndlp->nlp_flag |= NLP_UNREG_INP;
+   else
+   ndlp->nlp_flag &= ~NLP_UNREG_INP;
+
+   /* if ndlp had NLP_RPI_REGISTERED set, keep it */
+   if (keep_nlp_flag & NLP_RPI_REGISTERED)
+   ndlp->nlp_flag |= NLP_RPI_REGISTERED;
else
-   ndlp->nlp_flag = keep_nlp_flag & ~NLP_UNREG_INP;
+   ndlp->nlp_flag &= ~NLP_RPI_REGISTERED;
 
spin_unlock_irq(shost->host_lock);
 
@@ -1706,7 +1725,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
spin_unlock_irq(>ndlp_lock);
}
 
-   /* Two ndlps cannot have the same did on the nodelist */
+   /* Two ndlps cannot have the same did on the nodelist.
+* Note: for this case, ndlp has a NULL WWPN so setting
+* the nlp_fc4_type isn't required.
+*/
ndlp->nlp_DID = keepDID;
lpfc_nlp_set_state(vport, ndlp, keep_nlp_state);
if (phba->sli_rev == LPFC_SLI_REV4 &&
@@ -1725,8 +1747,13 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
 
lpfc_unreg_rpi(vport, ndlp);
 
-   /* Two ndlps cannot have the same did */
+   /* Two ndlps cannot have the same did and the fc4
+* type must be transfe

[PATCH 10/15] lpfc: Defer LS_ACC to FLOGI on point to point logins

2018-11-29 Thread James Smart
The current discovery state machine the driver treated FLOGI oddly.
When point to point, an FLOGI is to be exchanged by the two ports,
with the port with the most significant WWN then proceeding with PLOGI.
The implementation in the driver was keyed to closely with "what have I
sent", not with what has happened between the two endpoints. Thus, it
blatantly would ACC an FLOGI, but reject PLOGI's until it had its FLOGI
ACC'd. The problem is - the sending of FLOGI may be delayed for some
reason, or the response to FLOGI held off by the other side. In the
failing situation the other side sent an FLOGI, which was ACC'd, then
sent PLOGIs which were then rjt'd until the retry count for the PLOGIs
were exceeded and the port gave up. The FLOGI may have been very late
in transmit, or the response held off until the PLOGIs failed. Given
the other port had the higher WWN, no PLOGIs would occur and
communication stopped.

Correct the situation by changing the FLOGI handling. Defer any response
to an FLOGI until the driver has sent its FLOGI as well. Then, upon
either completion of the sent FLOGI, or upon sending an ACC to a
received FLOGI (which may be received before or just after FLOGI was
sent). the driver will act on who has the higher WWN. if the other port
does, the driver will noop any handling of an FLOGI response (if
outstanding) and wait for PLOGI.  If the local port does, the driver will
transition to sending PLOGI and will noop any action on responding to
an FLOGI (if not yet received).

Fortunately, to implement this, it only took another state flag and
deferring any FLOGI response if the FLOGI has yet to be transmit. All
subsequent actions were already in place.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h |  5 
 drivers/scsi/lpfc/lpfc_els.c | 56 +---
 drivers/scsi/lpfc/lpfc_hbadisc.c |  7 +
 3 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 35dcd6958fd0..ebdfe5b26937 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -731,6 +731,7 @@ struct lpfc_hba {
 * capability
 */
 #define HBA_NVME_IOQ_FLUSH  0x8 /* NVME IO queues flushed. */
+#define HBA_FLOGI_ISSUED   0x10 /* FLOGI was issued */
 
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
@@ -1127,6 +1128,10 @@ struct lpfc_hba {
uint16_t vlan_id;
struct list_head fcf_conn_rec_list;
 
+   bool defer_flogi_acc_flag;
+   uint16_t defer_flogi_acc_rx_id;
+   uint16_t defer_flogi_acc_ox_id;
+
spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */
struct list_head ct_ev_waiters;
struct unsol_rcv_ct_ctx ct_ctx[LPFC_CT_CTX_MAX];
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 48610bcd6962..103ee7049633 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1234,9 +1234,10 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
struct serv_parm *sp;
IOCB_t *icmd;
struct lpfc_iocbq *elsiocb;
+   struct lpfc_iocbq defer_flogi_acc;
uint8_t *pcmd;
uint16_t cmdsize;
-   uint32_t tmo;
+   uint32_t tmo, did;
int rc;
 
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
@@ -1308,6 +1309,35 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
phba->sli3_options, 0, 0);
 
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
+
+   phba->hba_flag |= HBA_FLOGI_ISSUED;
+
+   /* Check for a deferred FLOGI ACC condition */
+   if (phba->defer_flogi_acc_flag) {
+   did = vport->fc_myDID;
+   vport->fc_myDID = Fabric_DID;
+
+   memset(_flogi_acc, 0, sizeof(struct lpfc_iocbq));
+
+   defer_flogi_acc.iocb.ulpContext = phba->defer_flogi_acc_rx_id;
+   defer_flogi_acc.iocb.unsli3.rcvsli3.ox_id =
+   phba->defer_flogi_acc_ox_id;
+
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+"3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
+" ox_id: x%x, hba_flag x%x\n",
+phba->defer_flogi_acc_rx_id,
+phba->defer_flogi_acc_ox_id, phba->hba_flag);
+
+   /* Send deferred FLOGI ACC */
+   lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, _flogi_acc,
+ndlp, NULL);
+
+   phba->defer_flogi_acc_flag = false;
+
+   vport->fc_myDID = did;
+   }
+
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
 

[PATCH 07/15] lpfc: Cap NPIV vports to 256

2018-11-29 Thread James Smart
Depending on the chipset, the number of NPIV vports may vary and be in
excess of what most switches support (256). To avoid confusion with the
users, limit the reported NPIV vports to 256.

Additionally correct the 16G adapter which is reporting a bogus NPIV
vport number if the link is down.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h  |  3 ++-
 drivers/scsi/lpfc/lpfc_attr.c | 12 ++--
 drivers/scsi/lpfc/lpfc_init.c |  3 +++
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index b37e0caf0781..35dcd6958fd0 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1004,7 +1004,8 @@ struct lpfc_hba {
spinlock_t port_list_lock;  /* lock for port_list mutations */
struct lpfc_vport *pport;   /* physical lpfc_vport pointer */
uint16_t max_vpi;   /* Maximum virtual nports */
-#define LPFC_MAX_VPI 0x/* Max number of VPI supported */
+#define LPFC_MAX_VPI   0xFF/* Max number VPI supported 0 - 0xff */
+#define LPFC_MAX_VPORTS0x100   /* Max vports per port, with 
pport */
uint16_t max_vports;/*
 * For IOV HBAs max_vpi can change
 * after a reset. max_vports is max
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 5f30e40bcc0a..feaaa015150e 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1720,6 +1720,9 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
max_vpi = (bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) > 0) ?
(bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) - 1) : 0;
 
+   /* Limit the max we support */
+   if (max_vpi > LPFC_MAX_VPI)
+   max_vpi = LPFC_MAX_VPI;
if (mvpi)
*mvpi = max_vpi;
if (avpi)
@@ -1735,8 +1738,13 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
*axri = pmb->un.varRdConfig.avail_xri;
if (mvpi)
*mvpi = pmb->un.varRdConfig.max_vpi;
-   if (avpi)
-   *avpi = pmb->un.varRdConfig.avail_vpi;
+   if (avpi) {
+   /* avail_vpi is only valid if link is up and ready */
+   if (phba->link_state == LPFC_HBA_READY)
+   *avpi = pmb->un.varRdConfig.avail_vpi;
+   else
+   *avpi = pmb->un.varRdConfig.max_vpi;
+   }
}
 
mempool_free(pmboxq, phba->mbox_mem_pool);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 647a037d6f4d..716add289397 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -7958,6 +7958,9 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
bf_get(lpfc_mbx_rd_conf_xri_base, rd_config);
phba->sli4_hba.max_cfg_param.max_vpi =
bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config);
+   /* Limit the max we support */
+   if (phba->sli4_hba.max_cfg_param.max_vpi > LPFC_MAX_VPORTS)
+   phba->sli4_hba.max_cfg_param.max_vpi = LPFC_MAX_VPORTS;
phba->sli4_hba.max_cfg_param.vpi_base =
bf_get(lpfc_mbx_rd_conf_vpi_base, rd_config);
phba->sli4_hba.max_cfg_param.max_rpi =
-- 
2.13.7



[PATCH 09/15] lpfc: ls_rjt erroneus FLOGIs

2018-11-29 Thread James Smart
In some link initialization sequences, the fw generates an erroneous
FLOGI payload to the driver without an intervening link bounce.
The driver, when it sees a 2nd FLOGI without an intervening link bounce,
automatically performs a link bounce. In this, the link bounce causes
the situate to repeat and in a nasty loop of link bounces.

Resolve the issue by validating the FLOGI payload. The erroneous FLOGI
will contain VVL signatures that are not normal. When the driver sees
these, it will simply reject the flogi rather than bouncing the link.
The reject is consumed within the firmware.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c | 20 
 drivers/scsi/lpfc/lpfc_hw.h  |  1 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index e4cf648c951b..48610bcd6962 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -8042,8 +8042,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
struct ls_rjt stat;
uint32_t *payload;
uint32_t cmd, did, newnode;
+   uint32_t vid, flag;
uint8_t rjt_exp, rjt_err = 0, init_link = 0;
IOCB_t *icmd = >iocb;
+   struct serv_parm *sp;
LPFC_MBOXQ_t *mbox;
 
if (!vport || !(elsiocb->context2))
@@ -8193,6 +8195,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
did, vport->port_state, ndlp->nlp_flag);
 
phba->fc_stat.elsRcvFLOGI++;
+   sp = (struct serv_parm *)
+   ((uint8_t *)payload + sizeof(uint32_t));
+
+   /* Check to see if this is firmware generated */
+   if (sp->cmn.valid_vendor_ver_level) {
+   vid = be32_to_cpu(sp->un.vv.vid);
+   flag = be32_to_cpu(sp->un.vv.flags);
+   if (vid == LPFC_VV_BRCD_ID) {
+   /* Drop this FLOGI */
+   lpfc_printf_vlog(
+   vport, KERN_INFO, LOG_ELS,
+   "3316 Dropping rcv FLOGI: "
+   "flag x%x\n", flag);
+   goto lsrjt;
+   }
+   }
 
/* If the driver believes fabric discovery is done and is ready,
 * bounce the link.  There is some descrepancy.
@@ -8440,6 +8458,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
 * link and start over.
 */
if (init_link) {
+   lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+"3318 Resetting Link, multiple rcv FLOGIs\n");
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
return;
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index ec1227018913..eb49c720e042 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -525,6 +525,7 @@ struct serv_parm {  /* Structure is in Big Endian format */
struct {
uint32_t vid;
 #define LPFC_VV_EMLX_ID0x454d4c58  /* EMLX */
+#define LPFC_VV_BRCD_ID0x42524344  /* BRCD */
uint32_t flags;
 #define LPFC_VV_SUPPRESS_RSP   1
} vv;
-- 
2.13.7



[PATCH 12/15] lpfc: Correct topology type reporting on G7 adapters

2018-11-29 Thread James Smart
Driver missed classifying the chip type for G7 when reporting
supported topologies. This resulted in loop being shown as supported
on FC links that are not supported per the standard.

Add the chip classifications to the topology checks in the driver.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 5 +++--
 drivers/scsi/lpfc/lpfc_mbox.c | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index feaaa015150e..83924d66fd39 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3937,8 +3937,9 @@ lpfc_topology_store(struct device *dev, struct 
device_attribute *attr,
val);
return -EINVAL;
}
-   if (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
-   val == 4) {
+   if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
+phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
+   val == 4) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"3114 Loop mode not supported\n");
return -EINVAL;
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index b6aedc55be77..f6a5083a621e 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -513,9 +513,9 @@ lpfc_init_link(struct lpfc_hba * phba,
break;
}
 
-   if (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
-   mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
-   /* Failover is not tried for Lancer G6 */
+   if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
+phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
+   mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
phba->cfg_topology = FLAGS_TOPOLOGY_MODE_PT_PT;
}
-- 
2.13.7



[PATCH 06/15] lpfc: Fix kernel Oops due to null pring pointers

2018-11-29 Thread James Smart
Driver is hitting null pring pointers in lpfc_do_work().

Pointer assignment occurs based on SLI-revision. If recovering after
an error, its possible the sli revision for the port was cleared,
making the lpfc_phba_elsring() not return a ring pointer, thus
the null pointer.

Add SLI revision checking to lpfc_phba_elsring() and status checking
to all callers.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h  | 6 ++
 drivers/scsi/lpfc/lpfc_els.c  | 2 ++
 drivers/scsi/lpfc/lpfc_init.c | 7 ++-
 drivers/scsi/lpfc/lpfc_sli.c  | 2 ++
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index c23c29b451c2..b37e0caf0781 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1277,6 +1277,12 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
 static inline struct lpfc_sli_ring *
 lpfc_phba_elsring(struct lpfc_hba *phba)
 {
+   /* Return NULL if sli_rev has become invalid due to bad fw */
+   if (phba->sli_rev != LPFC_SLI_REV4  &&
+   phba->sli_rev != LPFC_SLI_REV3  &&
+   phba->sli_rev != LPFC_SLI_REV2)
+   return NULL;
+
if (phba->sli_rev == LPFC_SLI_REV4) {
if (phba->sli4_hba.els_wq)
return phba->sli4_hba.els_wq->pring;
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 902234a1fcfb..3f21338d95d1 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1343,6 +1343,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
Fabric_DID);
 
pring = lpfc_phba_elsring(phba);
+   if (unlikely(!pring))
+   return -EIO;
 
/*
 * Check the txcmplq for an iocb that matches the nport the driver is
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index e95a768575b0..647a037d6f4d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1797,7 +1797,12 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int 
mbx_action,
lpfc_offline(phba);
/* release interrupt for possible resource change */
lpfc_sli4_disable_intr(phba);
-   lpfc_sli_brdrestart(phba);
+   rc = lpfc_sli_brdrestart(phba);
+   if (rc) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+   "6309 Failed to restart board\n");
+   return rc;
+   }
/* request and enable interrupt */
intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) {
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 353652fbc954..9821ab81c2f9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -4687,6 +4687,8 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED;
 
rc = lpfc_sli4_brdreset(phba);
+   if (rc)
+   return rc;
 
spin_lock_irq(>hbalock);
phba->pport->stopped = 0;
-- 
2.13.7



[PATCH 15/15] lpfc: update driver version to 12.0.0.9

2018-11-29 Thread James Smart
Update the driver version to 12.0.0.9

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index d0b2dd9b737f..7b23895a7ed7 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.8"
+#define LPFC_DRIVER_VERSION "12.0.0.9"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.7



[PATCH 13/15] lpfc: Fix driver release of fw-logging buffers

2018-11-29 Thread James Smart
On driver termination, after the driver stops fw logging by writing a
register on the chip, the driver immediately unmaps and frees the logging
buffer, without confirming in any way that the chip has received the
write and terminated the logging. As termination on the chip is not
immediate, the chip may issue a dma request to the now unmapped dma
buffer, resulting in a iommu fault.

Change the driver to receive a confirmation that logging ahs been
terminated. As the driver always issues an SLI reset with the device
as part of shutdown, and as part of that is receiving confirmation that
the reset is complete - the driver was modified to perform the write to
disable fw logging prior to the SLI reset and only free the fw log buffer
after the SLI reset is complete. That guarantees use of the fw log buffer
is fully terminated when it is unmapped.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_bsg.c  | 22 ++
 drivers/scsi/lpfc/lpfc_crtn.h |  1 +
 drivers/scsi/lpfc/lpfc_init.c | 11 +--
 drivers/scsi/lpfc/lpfc_sli.c  | 19 +++
 4 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index b573fd00e650..cb18dac68e28 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -5381,25 +5381,6 @@ lpfc_bsg_get_ras_config(struct bsg_job *job)
 }
 
 /**
- * lpfc_ras_stop_fwlog: Disable FW logging by the adapter
- * @phba: Pointer to HBA context object.
- *
- * Disable FW logging into host memory on the adapter. To
- * be done before reading logs from the host memory.
- **/
-static void
-lpfc_ras_stop_fwlog(struct lpfc_hba *phba)
-{
-   struct lpfc_ras_fwlog *ras_fwlog = >ras_fwlog;
-
-   ras_fwlog->ras_active = false;
-
-   /* Disable FW logging to host memory */
-   writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
-  phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
-}
-
-/**
  * lpfc_bsg_set_ras_config: Set FW logging parameters
  * @job: fc_bsg_job to handle
  *
@@ -5519,7 +5500,8 @@ lpfc_bsg_get_ras_lwpd(struct bsg_job *job)
if (!ras_fwlog->lwpd.virt) {
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
"6193 Restart FW Logging\n");
-   return -EINVAL;
+   rc = -EINVAL;
+   goto ras_job_error;
}
 
/* Get lwpd offset */
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 5edea80fd7f1..6a8c5b804c2d 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -551,6 +551,7 @@ void lpfc_sli4_ras_init(struct lpfc_hba *phba);
 void lpfc_sli4_ras_setup(struct lpfc_hba *phba);
 int  lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, uint32_t fwlog_level,
 uint32_t fwlog_enable);
+void lpfc_ras_stop_fwlog(struct lpfc_hba *phba);
 int lpfc_check_fwlog_support(struct lpfc_hba *phba);
 
 /* NVME interfaces. */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 716add289397..c56ef73463f2 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10690,12 +10690,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
kthread_stop(phba->worker_thread);
 
/* Disable FW logging to host memory */
-   writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
-  phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
-
-   /* Free RAS DMA memory */
-   if (phba->ras_fwlog.ras_enabled == true)
-   lpfc_sli4_ras_dma_free(phba);
+   lpfc_ras_stop_fwlog(phba);
 
/* Unset the queues shared with the hardware then release all
 * allocated resources.
@@ -10706,6 +10701,10 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
/* Reset SLI4 HBA FCoE function */
lpfc_pci_function_reset(phba);
 
+   /* Free RAS DMA memory */
+   if (phba->ras_fwlog.ras_enabled)
+   lpfc_sli4_ras_dma_free(phba);
+
/* Stop the SLI4 device port */
phba->pport->work_port_events = 0;
 }
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 760b819f690a..3826a32eec20 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -6198,6 +6198,25 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t 
*mbox,
 }
 
 /**
+ * lpfc_ras_stop_fwlog: Disable FW logging by the adapter
+ * @phba: Pointer to HBA context object.
+ *
+ * Disable FW logging into host memory on the adapter. To
+ * be done before reading logs from the host memory.
+ **/
+void
+lpfc_ras_stop_fwlog(struct lpfc_hba *phba)
+{
+   struct lpfc_ras_fwlog *ras_fwlog = >ras_fwlog;
+
+   ras_fwlog->ras_active = false;
+
+   /* Disable FW logging to host memory */
+   writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
+  phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
+}
+
+/**
  * lpfc

[PATCH 04/15] lpfc: Fix discovery failures during port failovers with lots of vports

2018-11-29 Thread James Smart
The driver is getting hit with 100s of RSCNs during remote port address
changes. Each of those RSCN's ends up generating UNREG_RPI and REG_PRI
mailbox commands.  The discovery engine within the driver doesn't wait
for the mailbox command completions. Instead it sets state flags and
moves forward. At some point, there's a massive backlog of mailbox
commands which take time for the adapter to process. Additionally, it
appears there were duplicate events from the switch so the driver
generated duplicate mailbox commands for the same remote port.
During this window, failures on PLOGI and PRLI ELS's are see as the
adapter is rejecting them as they are for remote ports that still
have pending mailbox commands.

Streamline the discovery engine so that PLOGI log checks for outstanding
UNREG_RPIs and defer the processing until the commands complete. This
better synchronizes the ELS transmission vs the RPI registrations.

Filter out multiple UNREG_RPIs being queued up for the same remote port.

Beef up log messages in this area.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_crtn.h  |  1 -
 drivers/scsi/lpfc/lpfc_debugfs.c   |  2 ++
 drivers/scsi/lpfc/lpfc_disc.h  |  4 ++-
 drivers/scsi/lpfc/lpfc_els.c   | 69 --
 drivers/scsi/lpfc/lpfc_hbadisc.c   | 62 ++
 drivers/scsi/lpfc/lpfc_nportdisc.c | 44 +++-
 drivers/scsi/lpfc/lpfc_sli.c   | 59 
 7 files changed, 207 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index a4b1bc2782eb..5edea80fd7f1 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -74,7 +74,6 @@ void lpfc_mbx_cmpl_read_topology(struct lpfc_hba *, 
LPFC_MBOXQ_t *);
 void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
 void lpfc_retry_pport_discovery(struct lpfc_hba *);
-void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t);
 int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
 void lpfc_free_iocb_list(struct lpfc_hba *phba);
 int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 0c8005bb0f53..a8fc3cf0fea1 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -645,6 +645,8 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
i, ndlp->cmd_qdepth);
outio += i;
}
+   len += snprintf(buf + len, size - len, "defer:%x ",
+   ndlp->nlp_defer_did);
len +=  snprintf(buf+len, size-len, "\n");
}
spin_unlock_irq(shost->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 28e2b60fc5c0..1c89c9f314fa 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -138,6 +138,7 @@ struct lpfc_nodelist {
 
uint32_t nvme_fb_size; /* NVME target's supported byte cnt */
 #define NVME_FB_BIT_SHIFT 9/* PRLI Rsp first burst in 512B units. */
+   uint32_t nlp_defer_did;
 };
 struct lpfc_node_rrq {
struct list_head list;
@@ -165,6 +166,7 @@ struct lpfc_node_rrq {
 #define NLP_ELS_SND_MASK   0x07e0  /* sent ELS request for this entry */
 #define NLP_NVMET_RECOV0x1000   /* NVMET auditing node for recovery. */
 #define NLP_FCP_PRLI_RJT   0x2000   /* Rport does not support FCP PRLI. */
+#define NLP_UNREG_INP  0x8000  /* UNREG_RPI cmd is in progress */
 #define NLP_DEFER_RM   0x0001  /* Remove this ndlp if no longer used */
 #define NLP_DELAY_TMO  0x0002  /* delay timeout is running for node */
 #define NLP_NPR_2B_DISC0x0004  /* node is included in num_disc_nodes */
@@ -293,4 +295,4 @@ struct lpfc_node_rrq {
 #define NLP_EVT_DEVICE_RM 0xb  /* Device not found in NS / ALPAmap */
 #define NLP_EVT_DEVICE_RECOVERY   0xc  /* Device existence unknown */
 #define NLP_EVT_MAX_EVENT 0xd
-
+#define NLP_EVT_NOTHING_PENDING   0xff
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index a2caa9e67890..902234a1fcfb 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -315,20 +315,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t 
expectRsp,
/* Xmit ELS command  to remote NPORT  */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 "0116 Xmit ELS command x%x to remote "
-"NPORT x%x I/O tag: x%x, port state:x%x"
-" fc_flag:x%x\n",
+"NPORT x%x I/O tag: x%x, port sta

[PATCH 00/15] lpfc updates for 12.0.0.9

2018-11-29 Thread James Smart
Update lpfc to revision 12.0.0.9

This patch contains lpfc bug fixes

The patches were cut against Martin's 4.21/scsi-queue tree


James Smart (15):
  lpfc: Fix panic when FW-log buffsize is not initialized
  lpfc: update manufacturer attribute to reflect Broadcom
  lpfc: refactor mailbox structure context fields
  lpfc: Fix discovery failures during port failovers with lots of vports
  lpfc: Fix a duplicate 0711 log message number.
  lpfc: Fix kernel Oops due to null pring pointers
  lpfc: Cap NPIV vports to 256
  lpfc: rport port swap discovery issue.
  lpfc: ls_rjt erroneus FLOGIs
  lpfc: Defer LS_ACC to FLOGI on point to point logins
  lpfc: Correct code setting non existent bits in sli4 ABORT WQE
  lpfc: Correct topology type reporting on G7 adapters
  lpfc: Fix driver release of fw-logging buffers
  lpfc: Fix dif and first burst use in write commands
  lpfc: update driver version to 12.0.0.9

 drivers/scsi/lpfc/lpfc.h   |  14 ++-
 drivers/scsi/lpfc/lpfc_attr.c  |  27 ++--
 drivers/scsi/lpfc/lpfc_bsg.c   |  56 -
 drivers/scsi/lpfc/lpfc_crtn.h  |   2 +-
 drivers/scsi/lpfc/lpfc_ct.c|   2 +-
 drivers/scsi/lpfc/lpfc_debugfs.c   |   2 +
 drivers/scsi/lpfc/lpfc_disc.h  |   4 +-
 drivers/scsi/lpfc/lpfc_els.c   | 246 +
 drivers/scsi/lpfc/lpfc_hbadisc.c   | 145 +++---
 drivers/scsi/lpfc/lpfc_hw.h|   1 +
 drivers/scsi/lpfc/lpfc_init.c  |  30 +++--
 drivers/scsi/lpfc/lpfc_mbox.c  |  44 +++
 drivers/scsi/lpfc/lpfc_mem.c   |   6 +-
 drivers/scsi/lpfc/lpfc_nportdisc.c |  62 +++---
 drivers/scsi/lpfc/lpfc_nvme.c  |   2 -
 drivers/scsi/lpfc/lpfc_scsi.c  |  20 ++-
 drivers/scsi/lpfc/lpfc_sli.c   | 186 +++-
 drivers/scsi/lpfc/lpfc_sli.h   |   6 +-
 drivers/scsi/lpfc/lpfc_version.h   |   2 +-
 drivers/scsi/lpfc/lpfc_vport.c |   4 +-
 20 files changed, 597 insertions(+), 264 deletions(-)

-- 
2.13.7



[PATCH 01/15] lpfc: Fix panic when FW-log buffsize is not initialized

2018-11-29 Thread James Smart
While trying to get adapter fw-log for a function
whose buffsize was set to 0, kernel panic occurred.

When buffsize is 0, the kernel buffer for the log won't be allocated.
When fw log usage was enabled, it failed to check the buffer size, and
log usage was started. Eventually the driver referenced the unallocated
log buffer.

Added checks of the buffer size before allowing fw logging to be enabled
and added check for valid buffer if enabling fw log.

Performed a couple other minor cleanups while fixing this:
- clarified log messages
- re-evaluated log message severity
- treat any error as an error, not only a couple codes

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_bsg.c  | 16 +++-
 drivers/scsi/lpfc/lpfc_init.c |  3 ++-
 drivers/scsi/lpfc/lpfc_sli.c  | 14 --
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 43dcd1daa616..9b8edfb06cb0 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -5348,7 +5348,7 @@ lpfc_bsg_get_ras_config(struct bsg_job *job)
sizeof(struct fc_bsg_request) +
sizeof(struct lpfc_bsg_ras_req)) {
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
-   "6181 Received RAS_LOG request "
+   "6192 FW_LOG request received "
"below minimum size\n");
rc = -EINVAL;
goto ras_job_error;
@@ -5356,7 +5356,7 @@ lpfc_bsg_get_ras_config(struct bsg_job *job)
 
/* Check FW log status */
rc = lpfc_check_fwlog_support(phba);
-   if (rc == -EACCES || rc == -EPERM)
+   if (rc)
goto ras_job_error;
 
ras_reply = (struct lpfc_bsg_get_ras_config_reply *)
@@ -5430,7 +5430,7 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
 
/* Check FW log status */
rc = lpfc_check_fwlog_support(phba);
-   if (rc == -EACCES || rc == -EPERM)
+   if (rc)
goto ras_job_error;
 
ras_req = (struct lpfc_bsg_set_ras_config_req *)
@@ -5500,7 +5500,7 @@ lpfc_bsg_get_ras_lwpd(struct bsg_job *job)
int rc = 0;
 
rc = lpfc_check_fwlog_support(phba);
-   if (rc == -EACCES || rc == -EPERM)
+   if (rc)
goto ras_job_error;
 
if (job->request_len <
@@ -5516,6 +5516,12 @@ lpfc_bsg_get_ras_lwpd(struct bsg_job *job)
ras_reply = (struct lpfc_bsg_get_ras_lwpd *)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
 
+   if (!ras_fwlog->lwpd.virt) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
+   "6193 Restart FW Logging\n");
+   return -EINVAL;
+   }
+
/* Get lwpd offset */
lwpd_ptr = (uint32_t *)(ras_fwlog->lwpd.virt);
ras_reply->offset = be32_to_cpu(*lwpd_ptr & 0x);
@@ -5557,7 +5563,7 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
ras_fwlog = >ras_fwlog;
 
rc = lpfc_check_fwlog_support(phba);
-   if (rc == -EACCES || rc == -EPERM)
+   if (rc)
goto ras_job_error;
 
/* Logging to be stopped before reading */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7d8135591401..d20a55aa153b 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -12635,7 +12635,8 @@ lpfc_sli4_ras_init(struct lpfc_hba *phba)
case PCI_DEVICE_ID_LANCER_G6_FC:
case PCI_DEVICE_ID_LANCER_G7_FC:
phba->ras_fwlog.ras_hwsupport = true;
-   if (phba->cfg_ras_fwlog_func == PCI_FUNC(phba->pcidev->devfn))
+   if (phba->cfg_ras_fwlog_func == PCI_FUNC(phba->pcidev->devfn) &&
+   phba->cfg_ras_fwlog_buffsize)
phba->ras_fwlog.ras_enabled = true;
else
phba->ras_fwlog.ras_enabled = false;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 3912a2d0b95d..770cef54aaa4 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -6212,7 +6212,7 @@ lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba,
_fwlog->lwpd.phys,
GFP_KERNEL);
if (!ras_fwlog->lwpd.virt) {
-   lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6185 LWPD Memory Alloc Failed\n");
 
return -ENOMEM;
@@ -6274,11 +6274,13 @@ lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *pmb)
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, >response);
 
if (mb->mbxStatus != MBX_SUCCESS || shdr_status) {
-   lpfc_printf_log(phb

[PATCH 02/15] lpfc: update manufacturer attribute to reflect Broadcom

2018-11-29 Thread James Smart
Update manufacturer attribute to reflect Broadcom Inc, not Emulex

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_ct.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 6305ffeba7ea..deef1a174165 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1964,7 +1964,7 @@ lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport,
memset(ae, 0, 256);
 
strncpy(ae->un.AttrString,
-   "Emulex Corporation",
+   "Broadcom Inc.",
   sizeof(ae->un.AttrString));
len = strnlen(ae->un.AttrString,
  sizeof(ae->un.AttrString));
-- 
2.13.7



Re: [PATCH] scsi: lpfc: fix block guard enablement on SLI3 adapters

2018-11-27 Thread James Smart




On 11/12/2018 12:58 AM, Martin Wilck wrote:

Since f44ac12f1dcc, BG enablement is tracked with the
LPFC_SLI3_BG_ENABLED bit, which is set in lpfc_get_cfgparam
before lpfc_sli_config_sli_port() is called. The bit
shouldn't be cleared before checking the feature.
Based on problem analysis by David Bond.

Fixes: f44ac12f1dcc "scsi: lpfc: Memory allocation error during driver start-up on 
power8"
Tested-by: David Bond 
Signed-off-by: Martin Wilck 
Cc: sta...@vger.kernel.org # 4.17.x
Cc: sta...@vger.kernel.org # 4.18.x
Cc: sta...@vger.kernel.org # 4.19.x
---
  drivers/scsi/lpfc/lpfc_init.c | 6 +-
  drivers/scsi/lpfc/lpfc_sli.c  | 1 -
  2 files changed, 5 insertions(+), 2 deletions(-)



thanks

Signed-off-by:  James Smart 

-- james



Re: [PATCH v4 5/5] qla2xxx: Update driver version to 11.00.00.00-k

2018-11-19 Thread James Smart




On 10/31/2018 9:40 AM, Himanshu Madhani wrote:

Signed-off-by: Himanshu Madhani 
---
  


Reviewed-by:  James Smart  

-- james



Re: [PATCH v4 4/5] qla2xxx_nvmet: Add SysFS node for FC-NVMe Target

2018-11-19 Thread James Smart




On 10/31/2018 9:40 AM, Himanshu Madhani wrote:

From: Anil Gurumurthy 

This patch adds SysFS node for NVMe Target configuration

Signed-off-by: Anil Gurumurthy 
Signed-off-by: Himanshu Madhani 
---
  

looks good to me.

Reviewed-by:   James Smart  

-- james



Re: [PATCH v4 3/5] qla2xxx_nvmet: Add FC-NVMe Target handling

2018-11-19 Thread James Smart




On 10/31/2018 9:40 AM, Himanshu Madhani wrote:

From: Anil Gurumurthy 

This patch Adds following code in the driver to
support FC-NVMe Target

- Updated ql2xenablenvme to allow FC-NVMe Target operation
- Added Link Service Request handling for NVMe Target
- Added passthru IOCB for LS4 request
- Added CTIO for sending response to FW
- Added FC4 Registration for FC-NVMe Target
- Added PUREX IOCB support for login processing in FC-NVMe Target mode
- Added Continuation IOCB for PUREX
- Added Session creation with PUREX IOCB in FC-NVMe Target mode
- To enable FC-NVMe Target mode use ql2xnvmeenable=2 while loading driver

Signed-off-by: Anil Gurumurthy 
Signed-off-by: Giridhar Malavali 
Signed-off-by: Darren Trapp 
Signed-off-by: Himanshu Madhani 
---

  /* Values for srb_ctx type */
  #define SRB_LOGIN_CMD 1
  #define SRB_LOGOUT_CMD2
@@ -518,6 +526,8 @@ struct srb_iocb {
  #define SRB_NVME_ELS_RSP 24
  #define SRB_NVMET_LS   25
  #define SRB_NVMET_FCP  26
+#define SRB_NVMET_ABTS 27
+#define SRB_NVMET_SEND_ABTS28
Given that patch2 wouldn't have compiled without these two SRB_NVMET_xxx 
definitions, I recommend moving this to the prior patch, as well as any 
other dependencies.



diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 50c1e6c62e31..67a42d153f64 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -723,6 +723,269 @@ struct ct_entry_24xx {
uint32_t dseg_1_len;/* Data segment 1 length. */
  };
  
+/* NVME-T changes */

+/*
+ * Fibre Channel Header
+ * Little Endian format.  As received in PUREX and PURLS
+ */
+struct __fc_hdr {
+   uint16_tdid_lo;
+   uint8_t did_hi;
+   uint8_t r_ctl;
+   uint16_tsid_lo;
+   uint8_t sid_hi;
+   uint8_t cs_ctl;
+   uint16_tf_ctl_lo;
+   uint8_t f_ctl_hi;
+   uint8_t type;
+   uint16_tseq_cnt;
+   uint8_t df_ctl;
+   uint8_t seq_id;
+   uint16_trx_id;
+   uint16_tox_id;
+   uint32_tparam;
+};
+
+/*
+ * Fibre Channel LOGO acc
+ * In big endian format
+ */
+struct __fc_logo_acc {
+   uint8_t op_code;
+   uint8_t reserved[3];
+};
+
+struct __fc_lsrjt {
+   uint8_t op_code;
+   uint8_t reserved[3];
+   uint8_t reserved2;
+   uint8_t reason;
+   uint8_t exp;
+   uint8_t vendor;
+};
+
+/*
+ * Fibre Channel LOGO Frame
+ * Little Endian format. As received in PUREX
+ */
+struct __fc_logo {
+   struct __fc_hdr hdr;
+   uint16_treserved;
+   uint8_t reserved1;
+   uint8_t op_code;
+   uint16_tsid_lo;
+   uint8_t sid_hi;
+   uint8_t reserved2;
+   uint8_t pname[8];
+};
+
+/*
+ * Fibre Channel PRLI Frame
+ * Little Endian format. As received in PUREX
+ */
+struct __fc_prli {
+   struct  __fc_hdrhdr;
+   uint16_tpyld_length;  /* word 0 of prli */
+   uint8_t page_length;
+   uint8_t op_code;
+   uint16_tcommon;/* word 1.  1st word of SP page */
+   uint8_t type_ext;
+   uint8_t prli_type;
+#define PRLI_TYPE_FCP  0x8
+#define PRLI_TYPE_NVME 0x28
+   union {
+   struct {
+   uint32_treserved[2];
+   uint32_tsp_info;
+   } fcp;
+   struct {
+   uint32_treserved[2];
+   uint32_tsp_info;
+#define NVME_PRLI_DISC BIT_3
+#define NVME_PRLI_TRGT BIT_4
+#define NVME_PRLI_INIT BIT_5
+#define NVME_PRLI_CONFIRMATION BIT_7
+   uint32_treserved1;
+   } nvme;
+   };
+};
+
+/*
+ * Fibre Channel PLOGI Frame
+ * Little Endian format.  As received in PUREX
+ */
+struct __fc_plogi {
+   uint16_tdid_lo;
+   uint8_t did_hi;
+   uint8_t r_ctl;
+   uint16_tsid_lo;
+   uint8_t sid_hi;
+   uint8_t cs_ctl;
+   uint16_tf_ctl_lo;
+   uint8_t f_ctl_hi;
+   uint8_t type;
+   uint16_tseq_cnt;
+   uint8_t df_ctl;
+   uint8_t seq_id;
+   uint16_trx_id;
+   uint16_tox_id;
+   uint32_tparam;
+   uint8_t rsvd[3];
+   uint8_t op_code;
+   uint32_tcs_params[4]; /* common service params */
+   uint8_t pname[8]; /* port name */
+   uint8_t nname[8]; /* node name */
+   uint32_tclass1[4];/* class 1 service params */
+   uint32_tclass2[4];/* class 2 service params */
+   uint32_tclass3[4];/* class 3 service params */
+   uint32_tclass4[4];
+   uint32_tvndr_vers[4];
+};


Don't redefine all these standard structures.  For new code, use the 

Re: [PATCH v4 2/5] qla2xxx_nvmet: Add files for FC-NVMe Target support

2018-11-19 Thread James Smart

a couple more comments

On 10/31/2018 9:40 AM, Himanshu Madhani wrote:

+/*
+ * qla_nvmet_handle_abts
+ * Handle an abort from the initiator
+ * Invoke nvmet_fc_rcv_fcp_abort to pass the abts to the nvmet
+ */
+int qla_nvmet_handle_abts(struct scsi_qla_host *vha,
+   struct abts_recv_from_24xx *abts)
+{
+   uint16_t ox_id = cpu_to_be16(abts->fcp_hdr_le.ox_id);
+   unsigned long flags;
+   struct qla_nvmet_cmd *cmd = NULL;
+
+   if (!IS_ENABLED(CONFIG_NVME_TARGET_FC))
+   return 0;
+
+   /* Retrieve the cmd from cmd list */
+   spin_lock_irqsave(>cmd_list_lock, flags);
+   list_for_each_entry(cmd, >qla_cmd_list, cmd_list) {
+   if (cmd->ox_id == ox_id)
+   break; /* Found the cmd */
+   }
+   spin_unlock_irqrestore(>cmd_list_lock, flags);
+   if (!cmd) {
+   ql_log(ql_log_warn, vha, 0x1100b,
+   "%s-%d - Command not found\n", __func__, __LINE__);
+   /* Send a RJT */
+   qla_nvmet_send_abts_ctio(vha, abts, 0);
+   return 0;
+   }
+
+   nvmet_fc_rcv_fcp_abort(vha->targetport, >cmd.fcp_req);
+   /* Send an ACC */
+   qla_nvmet_send_abts_ctio(vha, abts, 1);
+
+   return 0;
+}


The ACC shouldn't go back until the nvmet layer finishes the io through 
a call to req_release.  Things could still be changing on the back-end 
media in during the window and a new (retried io) to the same lba area 
could be problematic.


...


+/*
+ * qla_nvmet_send_resp_ctio
+ * Send the response CTIO to the firmware
+ */
+static void qla_nvmet_send_resp_ctio(struct qla_qpair *qpair,
+   struct qla_nvmet_cmd *cmd, struct nvmefc_tgt_fcp_req *rsp_buf)
+{
...
+   case NVMET_FCOP_READDATA:
+   case NVMET_FCOP_READDATA_RSP:
+   /* Populate the CTIO resp with the SGL present in the rsp */
+   ql_dbg(ql_dbg_nvme, vha, 0x1100c,
+   "op: %#x, ox_id=%x c_flags=%x transfer_length: %#x req_cnt: %#x, 
tot_dsds: %#x\n",
+   rsp_buf->op, ctio->ox_id, c_flags,
+   rsp_buf->transfer_length, req_cnt, tot_dsds);
+
+   avail_dsds = 1;
+   cur_dsd = (uint32_t *)
+   >u.nvme_status_mode0.dsd0[0];
+   sgl = rsp_buf->sg;
+
+   /* Load data segments */
+   for_each_sg(sgl, sg, tot_dsds, i) {
+   dma_addr_t  sle_dma;
+   cont_a64_entry_t *cont_pkt;
+
+   /* Allocate additional continuation packets? */
+   if (avail_dsds == 0) {
...
+   }
+
+   sle_dma = sg_dma_address(sg);
+   *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+   *cur_dsd++ = cpu_to_le32(MSD(sle_dma));


There was a recent patch to convert drivers from using their own 
upper/lower 32-bit addr masks and instead use the system version of it. 
I would assume that should apply to these' LSD/MSD references - both 
here and other places in the patch.


See
https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git/commit/?h=4.21/scsi-queue=3d5ca1e6fdfeb4bc9d0b2eb4e35717198af03d78

-- james



Re: [PATCH v4 2/5] qla2xxx_nvmet: Add files for FC-NVMe Target support

2018-11-19 Thread James Smart




On 10/31/2018 9:40 AM, Himanshu Madhani wrote:

From: Anil Gurumurthy 

This patch adds files to enable NVMe Target Support

Signed-off-by: Anil Gurumurthy 
Signed-off-by: Giridhar Malavali 
Signed-off-by: Darren Trapp 
Signed-off-by: Himanshu Madhani 
---
  drivers/scsi/qla2xxx/qla_nvmet.c | 795 +++
  drivers/scsi/qla2xxx/qla_nvmet.h | 129 +++
  2 files changed, 924 insertions(+)
  create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.c
  create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.h

diff --git a/drivers/scsi/qla2xxx/qla_nvmet.c b/drivers/scsi/qla2xxx/qla_nvmet.c
new file mode 100644
index ..caf72d5d627b
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_nvmet.c
@@ -0,0 +1,795 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2017 QLogic Corporation


Copyrights are out of date - general comment for the patches.


+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.


Where does one find such a file ?  How does one know this is GPL ? same 
for other patches (and seems to apply to existing files).




+ */
+static void
+qla_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
+{
+   struct qla_nvmet_tgtport *tport = targetport->private;
+
+   if (!IS_ENABLED(CONFIG_NVME_TARGET_FC))
+   return;


little odd to check enablement this way - but ok



+/*
+ * qla_nvmet_ls_rsp -
+ * Invoked by the nvme-t to complete the LS req.
+ * Prepare and send a response CTIO to the firmware.
+ */
+static int
+qla_nvmet_ls_rsp(struct nvmet_fc_target_port *tgtport,
+   struct nvmefc_tgt_ls_req *rsp)
+{
+   struct qla_nvmet_cmd *tgt_cmd =
+   container_of(rsp, struct qla_nvmet_cmd, cmd.ls_req);
+   struct scsi_qla_host *vha = tgt_cmd->vha;
+   struct srb_iocb   *nvme;
+   int rval = QLA_FUNCTION_FAILED;
+   srb_t *sp;
+
+   ql_dbg(ql_dbg_nvme + ql_dbg_buffer, vha, 0x11002,
+   "Dumping the NVMET-LS response buffer\n");
+   ql_dump_buffer(ql_dbg_nvme + ql_dbg_buffer, vha, 0x2075,
+   (uint8_t *)rsp->rspbuf, rsp->rsplen);
+
+   /* Alloc SRB structure */
+   sp = qla2x00_get_sp(vha, NULL, GFP_ATOMIC);


interesting you're doing atomic allocations in these places. I didn't 
think you were in interrupt context. same comment holds for other 
routines that may alloc.



+/*
+ * qla_nvmet_fcp_op -
+ * Invoked by the nvme-t to complete the IO.
+ * Prepare and send a response CTIO to the firmware.
+ */
+static int
+qla_nvmet_fcp_op(struct nvmet_fc_target_port *tgtport,
+   struct nvmefc_tgt_fcp_req *rsp)
+{
+   struct qla_nvmet_cmd *tgt_cmd =
+   container_of(rsp, struct qla_nvmet_cmd, cmd.fcp_req);
+   struct scsi_qla_host *vha = tgt_cmd->vha;
+
+   if (!IS_ENABLED(CONFIG_NVME_TARGET_FC))
+   return 0;


I would think you would at least return a -EINVAL or something. I would 
think this code could never be executed as the registration would never 
occur as the enablement checks would stop it. So the check is 
meaningless. Kinda pointing out why the checks seem odd. Same comment 
holds for other places.



+
+   /* Prepare and send CTIO 82h */
+   qla_nvmet_send_resp_ctio(vha->qpair, tgt_cmd, rsp);


I'm surprised this can't return an error

 ...

+/*
+ * qla_nvmet_fcp_abort -
+ * Invoked by the nvme-t to abort an IO
+ * Send an abort to the firmware
+ */
+static void
+qla_nvmet_fcp_abort(struct nvmet_fc_target_port *tgtport,
+   struct nvmefc_tgt_fcp_req *req)
+{
+   struct qla_nvmet_cmd *tgt_cmd =
+   container_of(req, struct qla_nvmet_cmd, cmd.fcp_req);
+   struct scsi_qla_host *vha = tgt_cmd->vha;
+   struct qla_hw_data *ha = vha->hw;
+   srb_t *sp;
+
+   if (!IS_ENABLED(CONFIG_NVME_TARGET_FC))
+   return;
+
+   /* Alloc SRB structure */
+   sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+   if (!sp) {
+   ql_log(ql_log_info, vha, 0x11005, "Failed to allocate SRB\n");
+   return;


There is more that needs to be done on this failure somehow  you 
need to terminate the exchange on the wire/in the adapter. If there was 
an op outstanding, it needs to complete somehow (consider an io timeout 
because target isn't responding, yet is still present) for anything to 
free up and allow recovery.



+   }
+
+   sp->type = SRB_NVMET_SEND_ABTS;
+   sp->done = qla_nvmet_fcp_abort_done;
+   sp->vha = vha;
+   sp->fcport = tgt_cmd->fcport;
+
+   ha->isp_ops->abort_command(sp);

always successful ?


...

+/*
+ * qla_nvmet_handle_ls -
+ * Handle a link service request from the initiator.
+ * Get the LS payload from the ATIO queue, invoke
+ * nvmet_fc_rcv_ls_req to pass the LS req to nvmet.
+ */
+int qla_nvmet_handle_ls(struct scsi_qla_host *vha,
+   struct pt_ls4_rx_unsol *pt_ls4, void *buf)
+{
+   ...
+
+   ret = 

Re: [PATCH v4 1/5] qla2xxx_nvmet: Add FC-NVMe Target Link Service request handling

2018-11-19 Thread James Smart




On 10/31/2018 9:40 AM, Himanshu Madhani wrote:

From: Anil Gurumurthy 

This patch provides link service pass through feature handling
in the driver. This feature is implemented mainly by the firmware
and the same implementation is handled in the driver via an
IOCB interface.

Signed-off-by: Anil Gurumurthy 
Signed-off-by: Giridhar Malavali 
Signed-off-by: Darren Trapp 
Signed-off-by: Himanshu Madhani 
---

+
+/*
+ * Used by FC-NVMe Target
+ */
+int qla_nvmet_ls(srb_t *sp, void *rsp_pkt);
+int qlt_send_els_resp(srb_t *sp, void *pkt);
+
...
  
+int qlt_send_els_resp(srb_t *sp, void *pkt)

+{
+   return 0;
+}
+
+int
+qla_nvmet_ls(srb_t *sp, void *rsp_pkt)
+{
+   return 0;
+}
+
  void qlt_response_pkt_all_vps(struct scsi_qla_host *vha,
struct rsp_que *rsp, response_t *pkt)
  {


Rather than add these 2 routines in now, only to remove them in patch 3 
- you can leave the stubs, just make the prototypes correct.  Then patch 
3 can flush them out.


- james




Re: [PATCH] qla2xxx: Add SysFS hook for FC-NVMe autoconnect

2018-11-15 Thread James Smart




On 11/15/2018 8:43 AM, Ewan D. Milne wrote:

On Thu, 2018-11-15 at 13:52 +0100, Hannes Reinecke wrote:

On 11/14/18 6:13 PM, Ewan D. Milne wrote:

On Tue, 2018-11-13 at 09:49 -0800, Bart Van Assche wrote:

On Tue, 2018-11-13 at 17:38 +, Madhani, Himanshu wrote:

On Nov 13, 2018, at 6:23 AM, Bart Van Assche  wrote:

On Tue, 2018-11-13 at 01:02 +, Madhani, Himanshu wrote:

I see other drivers also use similar information populated for NVMe
Connection at boot time.

Hi Himanshu,

Which other drivers are you referring to?

Thanks,

Bart.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/dri
vers/scsi/lpfc/lpfc_attr.c

Hello James,

Please either move the information exported by lpfc_nvme_info_show() into
debugfs or split the information exported by that function into multiple
sysfs attributes. Otherwise you will get flamed by Greg KH as soon as he
encounters that code because of not following the rules explained in
Documentation/filesystems/sysfs.txt.

Bart.

Better yet, is there some way we could get at least the connection
information needed for discovery moved into the NVMe/FC transport
layer so that we don't need to have separate implementations that
have to be parsed?


Sigh.

It's already been solved, there's no need for this attribute.

nvme-fc already sends a uevent whenever a new nvme rport is attached,
(check nvme_fc_register_remoteport()->nvme_fc_signal_discovery_scan().

James Smart added a sysfs entry for retriggering these uevents, and I've
posted a set of scripts (... at least I think I did :-) utilizing those.

Please do _NOT_ do this; better rely on common mechanisms here.

And please, next time please cc linux-nvme so that we can track it better.

Cheers,

Hannes

So, the uevent can take care of the discovery mechanism, however there
are other reasons why one would want to be able to know e.g. what the
WWPNs of the Initiator & Target ports of the NVMe connections are.
For example, we would typically want to capture this information when
troubleshooting a system remotely.  There are also SAN test environments
that have a need for this information, which is one of the reasons
for the original patch posting.  I don't think it matters too much how
we do it, but the information is needed somehow.

I suppose a udev rule could put the information into a file, but that
seems awkard, and the infomation neeeded is in kernel objects, so why
not make it visible?

The uevent is of course necessary as it signifies an event, but the
desired info here is the *state*.

-Ewan



Well - that's the intent of merging the nvme fc and scsi fc transports 
into a fc-specific transport.  I'd be glad to have help doing this, but 
it has taken a lower priority.  Right now, for lpfc, I instruct everyone 
to use the scsi fc transport port structures for state.


-- james



Re: [PATCH] qla2xxx: Add SysFS hook for FC-NVMe autoconnect

2018-11-15 Thread James Smart



On 11/15/2018 4:52 AM, Hannes Reinecke wrote:

On 11/14/18 6:13 PM, Ewan D. Milne wrote:

On Tue, 2018-11-13 at 09:49 -0800, Bart Van Assche wrote:

On Tue, 2018-11-13 at 17:38 +, Madhani, Himanshu wrote:
On Nov 13, 2018, at 6:23 AM, Bart Van Assche  
wrote:

On Tue, 2018-11-13 at 01:02 +, Madhani, Himanshu wrote:

I see other drivers also use similar information populated for NVMe
Connection at boot time.


Hi Himanshu,

Which other drivers are you referring to?

Thanks,

Bart.


https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/dri 


vers/scsi/lpfc/lpfc_attr.c


Hello James,

Please either move the information exported by lpfc_nvme_info_show() 
into
debugfs or split the information exported by that function into 
multiple
sysfs attributes. Otherwise you will get flamed by Greg KH as soon 
as he

encounters that code because of not following the rules explained in
Documentation/filesystems/sysfs.txt.

Bart.


Better yet, is there some way we could get at least the connection
information needed for discovery moved into the NVMe/FC transport
layer so that we don't need to have separate implementations that
have to be parsed?


Sigh.

It's already been solved, there's no need for this attribute.

nvme-fc already sends a uevent whenever a new nvme rport is attached,
(check nvme_fc_register_remoteport()->nvme_fc_signal_discovery_scan().

James Smart added a sysfs entry for retriggering these uevents, and 
I've posted a set of scripts (... at least I think I did :-) utilizing 
those.


Please do _NOT_ do this; better rely on common mechanisms here.

And please, next time please cc linux-nvme so that we can track it 
better.


Cheers,

Hannes


Yes - the attribute in lpfc needs to go. It's currently a temporary 
thing until we merge the nvme and scsi transports and informational only.


It *is not* used for autoconnect.  The nvme fc transport automatically 
generates udev events upon nvme remoteport registrations and, as Hannes 
points out, we added a transport attribute to regenerate connect events 
for a host:

http://git.infradead.org/nvme.git/commit/97faec531460c949d7120672b8c77e2f41f8d6d7

-- james



Re: [PATCH v4 0/5] qla2xxx: Add FC-NVMe Target support

2018-11-08 Thread James Smart

Madhani,

I'll be looking through it over the weekend.

-- james


On 11/8/2018 8:58 AM, Madhani, Himanshu wrote:

Hi James,

Any more review comments?


On Oct 31, 2018, at 9:40 AM, Himanshu Madhani  
wrote:

Hi Martin,

This series adds support for FC-NVMe Target.

Patch #1 adds infrastructure to support FC-NVMeT Link Service processing.
Patch #2 adds addes new qla_nvmet.[ch] files for FC-NVMe Target support.
Patch #3 has bulk of changes to add hooks into common code infrastucture and
 adds support for FC-NVMe Target LS4 processing via Purex path.
Patch #4 adds SysFS hook to enable NVMe Target for the port.

Please apply them to 4.21/scsi-queue at your earliest convenience.

Changes from v3 -> v4
o Rebased Series on current 4.20/scsi-queue
o Removed NVMET_FCTGTFEAT_{CMD|OPDONE}_IN_ISR as per James Smart's review 
comment.

Changes from v2 -> v3
o Reordered patches so that each patch compiles individually and is bisectable.

Changes from v1 -> v2
o Addressed all comments from Bart.
o Consolidated Patch 1 and Patch 2 into single patch.
o Fixed smatch warning reported by kbuild autommation.
o NVMe Target mode is exclusive at the moment. Cavium driver does not support 
both
  FCP Target and NVMe Target at the same time. This will be fixed in later 
updates.

Thanks,
Himanshu

Anil Gurumurthy (4):
  qla2xxx_nvmet: Add FC-NVMe Target Link Service request handling
  qla2xxx_nvmet: Add files for FC-NVMe Target support
  qla2xxx_nvmet: Add FC-NVMe Target handling
  qla2xxx_nvmet: Add SysFS node for FC-NVMe Target

Himanshu Madhani (1):
  qla2xxx: Update driver version to 11.00.00.00-k

drivers/scsi/qla2xxx/Makefile  |   3 +-
drivers/scsi/qla2xxx/qla_attr.c|  33 ++
drivers/scsi/qla2xxx/qla_dbg.c |   1 +
drivers/scsi/qla2xxx/qla_dbg.h |   2 +
drivers/scsi/qla2xxx/qla_def.h |  35 +-
drivers/scsi/qla2xxx/qla_fw.h  | 263 ++
drivers/scsi/qla2xxx/qla_gbl.h |  24 +-
drivers/scsi/qla2xxx/qla_gs.c  |  16 +-
drivers/scsi/qla2xxx/qla_init.c|  49 +-
drivers/scsi/qla2xxx/qla_iocb.c|   8 +-
drivers/scsi/qla2xxx/qla_isr.c | 112 -
drivers/scsi/qla2xxx/qla_mbx.c | 101 +++-
drivers/scsi/qla2xxx/qla_nvme.h|  33 --
drivers/scsi/qla2xxx/qla_nvmet.c   | 831 +++
drivers/scsi/qla2xxx/qla_nvmet.h   | 129 +
drivers/scsi/qla2xxx/qla_os.c  |  75 ++-
drivers/scsi/qla2xxx/qla_target.c  | 977 -
drivers/scsi/qla2xxx/qla_target.h  |  90 
drivers/scsi/qla2xxx/qla_version.h |   4 +-
19 files changed, 2711 insertions(+), 75 deletions(-)
create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.c
create mode 100644 drivers/scsi/qla2xxx/qla_nvmet.h

--
2.12.0


Hi Martin,

if there are no more review comments. Can we merge this into 4.21/scsi-queue.

Thanks,
- Himanshu





Re: [PATCH v3 2/5] qla2xxx_nvmet: Add files for FC-NVMe Target support

2018-10-25 Thread James Smart




On 9/28/2018 3:46 PM, Himanshu Madhani wrote:

+   .target_features= NVMET_FCTGTFEAT_READDATA_RSP |
+   NVMET_FCTGTFEAT_CMD_IN_ISR |
+   NVMET_FCTGTFEAT_OPDONE_IN_ISR,



Himanshu,

I'm looking at these but had a quick question.   Did you really want the 
IN_ISR flags set ?  they schedule processing vs calling the nvmet 
routines inline. The intent was the queueing was only needed if in the 
hard isr routine. Last contact I had with your group said you were in 
soft isr routines and inline calling would be used.  I'm asking because 
I had intended to remove these flags/features.


-- james



[PATCH 09/12] lpfc: Correct loss of fc4 type on remote port address change

2018-10-23 Thread James Smart
An address change for a remote port cause PRLI for the wrong
protocol to be sent.  The node copy done in the discovery code
skipped copying the fc4 protocols supported as well.

Fix the copy logic for the address change.
Beefed up log messages in this area as well.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c   | 27 +++
 drivers/scsi/lpfc/lpfc_nportdisc.c |  5 +++--
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index a200cdaf34a6..ebd6c7251ad8 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1556,8 +1556,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
 */
new_ndlp = lpfc_findnode_wwpn(vport, >portName);
 
+   /* return immediately if the WWPN matches ndlp */
if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp))
return ndlp;
+
if (phba->sli_rev == LPFC_SLI_REV4) {
active_rrqs_xri_bitmap = mempool_alloc(phba->active_rrq_pool,
   GFP_KERNEL);
@@ -1566,9 +1568,13 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
   phba->cfg_rrq_xri_bitmap_sz);
}
 
-   lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-"3178 PLOGI confirm: ndlp %p x%x: new_ndlp %p\n",
-ndlp, ndlp->nlp_DID, new_ndlp);
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_NODE,
+"3178 PLOGI confirm: ndlp x%x x%x x%x: "
+"new_ndlp x%x x%x x%x\n",
+ndlp->nlp_DID, ndlp->nlp_flag,  ndlp->nlp_fc4_type,
+(new_ndlp ? new_ndlp->nlp_DID : 0),
+(new_ndlp ? new_ndlp->nlp_flag : 0),
+(new_ndlp ? new_ndlp->nlp_fc4_type : 0));
 
if (!new_ndlp) {
rc = memcmp(>nlp_portname, name,
@@ -1617,6 +1623,14 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
   phba->cfg_rrq_xri_bitmap_sz);
}
 
+   /* At this point in this routine, we know new_ndlp will be
+* returned. however, any previous GID_FTs that were done
+* would have updated nlp_fc4_type in ndlp, so we must ensure
+* new_ndlp has the right value.
+*/
+   if (vport->fc_flag & FC_FABRIC)
+   new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type;
+
lpfc_unreg_rpi(vport, new_ndlp);
new_ndlp->nlp_DID = ndlp->nlp_DID;
new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
@@ -1666,7 +1680,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
if (ndlp->nrport) {
ndlp->nrport = NULL;
lpfc_nlp_put(ndlp);
-   new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type;
}
 
/* We shall actually free the ndlp with both nlp_DID and
@@ -1740,6 +1753,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t 
*prsp,
active_rrqs_xri_bitmap)
mempool_free(active_rrqs_xri_bitmap,
 phba->active_rrq_pool);
+
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_NODE,
+"3173 PLOGI confirm exit: new_ndlp x%x x%x x%x\n",
+new_ndlp->nlp_DID, new_ndlp->nlp_flag,
+new_ndlp->nlp_fc4_type);
+
return new_ndlp;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c 
b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 394ffbe9cb6d..6827ffef3261 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -2868,8 +2868,9 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
/* DSM in event  on NPort  in state  */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
 "0211 DSM in event x%x on NPort x%x in "
-"state %d Data: x%x\n",
-evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
+"state %d Data: x%x x%x\n",
+evt, ndlp->nlp_DID, cur_state,
+ndlp->nlp_flag, ndlp->nlp_fc4_type);
 
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
 "DSM in:  evt:%d ste:%d did:x%x",
-- 
2.13.1



[PATCH 04/12] lpfc: Reset link or adapter instead of doing infinite nameserver PLOGI retry

2018-10-23 Thread James Smart
Currently, PLOGI failures are infinitely delayed/retried.
There have been some fabric situations where the PLOGI's were to
the nameserver and it stopped responding. The retries would never
clear up.  A better resolution in this situation is to retry a
couple of times, then drop the link and reinit. This brings back
connectivity to the nameserver.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_crtn.h |  1 +
 drivers/scsi/lpfc/lpfc_els.c  | 83 ++-
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index e01136507780..e9b297a39e54 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -380,6 +380,7 @@ void lpfc_nvmet_buf_free(struct lpfc_hba *phba, void 
*virtp, dma_addr_t dma);
 
 void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
 void lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp);
+int lpfc_link_reset(struct lpfc_vport *vport);
 
 /* Function prototypes. */
 const char* lpfc_info(struct Scsi_Host *);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 8160a5ebad08..e3e851931394 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3242,6 +3242,62 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
 }
 
 /**
+ * lpfc_link_reset - Issue link reset
+ * @vport: pointer to a virtual N_Port data structure.
+ *
+ * This routine performs link reset by sending INIT_LINK mailbox command.
+ * For SLI-3 adapter, link attention interrupt is enabled before issuing
+ * INIT_LINK mailbox command.
+ *
+ * Return code
+ *   0 - Link reset initiated successfully
+ *   1 - Failed to initiate link reset
+ **/
+int
+lpfc_link_reset(struct lpfc_vport *vport)
+{
+   struct lpfc_hba *phba = vport->phba;
+   LPFC_MBOXQ_t *mbox;
+   uint32_t control;
+   int rc;
+
+   lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+"2851 Attempt link reset\n");
+   mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+   if (!mbox) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+   "2852 Failed to allocate mbox memory");
+   return 1;
+   }
+
+   /* Enable Link attention interrupts */
+   if (phba->sli_rev <= LPFC_SLI_REV3) {
+   spin_lock_irq(>hbalock);
+   phba->sli.sli_flag |= LPFC_PROCESS_LA;
+   control = readl(phba->HCregaddr);
+   control |= HC_LAINT_ENA;
+   writel(control, phba->HCregaddr);
+   readl(phba->HCregaddr); /* flush */
+   spin_unlock_irq(>hbalock);
+   }
+
+   lpfc_init_link(phba, mbox, phba->cfg_topology,
+  phba->cfg_link_speed);
+   mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+   mbox->vport = vport;
+   rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+   if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+   "2853 Failed to issue INIT_LINK "
+   "mbox command, rc:x%x\n", rc);
+   mempool_free(mbox, phba->mbox_mem_pool);
+   return 1;
+   }
+
+   return 0;
+}
+
+/**
  * lpfc_els_retry - Make retry decision on an els command iocb
  * @phba: pointer to lpfc hba data structure.
  * @cmdiocb: pointer to lpfc command iocb data structure.
@@ -3277,6 +,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq 
*cmdiocb,
int logerr = 0;
uint32_t cmd = 0;
uint32_t did;
+   int link_reset = 0, rc;
 
 
/* Note: context2 may be 0 for internal driver abort
@@ -3358,7 +3415,6 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq 
*cmdiocb,
retry = 1;
break;
 
-   case IOERR_SEQUENCE_TIMEOUT:
case IOERR_INVALID_RPI:
if (cmd == ELS_CMD_PLOGI &&
did == NameServer_DID) {
@@ -3369,6 +3425,18 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq 
*cmdiocb,
}
retry = 1;
break;
+
+   case IOERR_SEQUENCE_TIMEOUT:
+   if (cmd == ELS_CMD_PLOGI &&
+   did == NameServer_DID &&
+   (cmdiocb->retry + 1) == maxretry) {
+   /* Reset the Link */
+   link_reset = 1;
+   break;
+   }
+   retry = 1;
+   delay = 100;
+   break;
}
break;
 
@@ -3525,6 +3593,19 @@ lpfc

[PATCH 00/12] lpfc updates for 12.0.0.8

2018-10-23 Thread James Smart
This patch contains lpfc bug fixes and 2 enhancements.

The patches were cut against Martin's 4.20/scsi-queue tree


James Smart (12):
  lpfc: Correct speeds on SFP swap
  lpfc: Fix lpfc_sli4_read_config return value check
  lpfc: Fix LOGO/PLOGI handling when triggerd by ABTS Timeout event
  lpfc: Reset link or adapter instead of doing infinite nameserver PLOGI
retry
  lpfc: Correct errors accessing fw log
  lpfc: fcoe: Fix link down issue after 1000+ link bounces
  lpfc: Correct LCB RJT handling
  lpfc: Fix odd recovery in duplicate FLOGIs in point-to-point
  lpfc: Correct loss of fc4 type on remote port address change
  lpfc: Implement GID_PT on Nameserver query to support faster failover
  lpfc: add Trunking support
  lpfc: update driver version to 12.0.0.8

 drivers/scsi/lpfc/lpfc.h   |  15 +++
 drivers/scsi/lpfc/lpfc_attr.c  | 115 ++
 drivers/scsi/lpfc/lpfc_bsg.c   | 138 +++--
 drivers/scsi/lpfc/lpfc_bsg.h   |  38 ++
 drivers/scsi/lpfc/lpfc_crtn.h  |   2 +
 drivers/scsi/lpfc/lpfc_ct.c| 211 
 drivers/scsi/lpfc/lpfc_els.c   | 242 ++---
 drivers/scsi/lpfc/lpfc_hbadisc.c   |  59 +
 drivers/scsi/lpfc/lpfc_hw.h|   1 +
 drivers/scsi/lpfc/lpfc_hw4.h   |  68 +++
 drivers/scsi/lpfc/lpfc_init.c  | 213 +---
 drivers/scsi/lpfc/lpfc_nportdisc.c |  23 +++-
 drivers/scsi/lpfc/lpfc_scsi.h  |   4 +
 drivers/scsi/lpfc/lpfc_sli.c   |  22 ++--
 drivers/scsi/lpfc/lpfc_sli4.h  |  14 +++
 drivers/scsi/lpfc/lpfc_version.h   |   2 +-
 16 files changed, 1049 insertions(+), 118 deletions(-)

-- 
2.13.1



[PATCH 07/12] lpfc: Correct LCB RJT handling

2018-10-23 Thread James Smart
When LCB's are rejected, if beaconing was already in progress, the
Reason Code Explanation was not being set. Should have been set to
command in progress.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 25625c03a5b3..832e5e00c1c9 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5776,6 +5776,9 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
stat = (struct ls_rjt *)(pcmd + sizeof(uint32_t));
stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 
+   if (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)
+   stat->un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
+
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
phba->fc_stat.elsXmitLSRJT++;
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
-- 
2.13.1



[PATCH 12/12] lpfc: update driver version to 12.0.0.8

2018-10-23 Thread James Smart
Update the driver version to 12.0.0.8

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 5a0d512ff497..d0b2dd9b737f 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.7"
+#define LPFC_DRIVER_VERSION "12.0.0.8"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH 08/12] lpfc: Fix odd recovery in duplicate FLOGIs in point-to-point

2018-10-23 Thread James Smart
Testing a point-to-point topology and a case of re-FLOGI without
intervening link bouncing, showed an odd interaction with firmware
and a resulting scenario where the driver no longer probed after
accepting the new FLOGI.

Work around the firmware issue by issuing a link bounce if a FLOGI
is received after the link is already up and FLOGI's accepted.

While debugging the issue, realized that some debug traces should be
clarified to help in the future.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h |  1 +
 drivers/scsi/lpfc/lpfc_els.c | 66 
 drivers/scsi/lpfc/lpfc_hbadisc.c |  9 ++
 3 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 4fe04c00a390..1dfe71f0fcfd 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -490,6 +490,7 @@ struct lpfc_vport {
struct nvme_fc_local_port *localport;
uint8_t  nvmei_support; /* driver supports NVME Initiator */
uint32_t last_fcp_wqidx;
+   uint32_t rcv_flogi_cnt; /* How many unsol FLOGIs ACK'd. */
 };
 
 struct hbq_s {
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 832e5e00c1c9..a200cdaf34a6 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1057,9 +1057,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
goto flogifail;
 
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
-"0150 FLOGI failure Status:x%x/x%x TMO:x%x\n",
+"0150 FLOGI failure Status:x%x/x%x xri x%x 
TMO:x%x\n",
 irsp->ulpStatus, irsp->un.ulpWord[4],
-irsp->ulpTimeout);
+cmdiocb->sli4_xritag, irsp->ulpTimeout);
 
/* FLOGI failed, so there is no fabric */
spin_lock_irq(shost->host_lock);
@@ -1113,7 +1113,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
/* FLOGI completes successfully */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 "0101 FLOGI completes successfully, I/O tag:x%x, "
-"Data: x%x x%x x%x x%x x%x x%x\n", cmdiocb->iotag,
+"xri x%x Data: x%x x%x x%x x%x x%x %x\n",
+cmdiocb->iotag, cmdiocb->sli4_xritag,
 irsp->un.ulpWord[4], sp->cmn.e_d_tov,
 sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution,
 vport->port_state, vport->fc_flag);
@@ -4347,14 +4348,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
default:
return 1;
}
-   /* Xmit ELS ACC response tag  */
-   lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-"0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
-"DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x "
-"fc_flag x%x\n",
-elsiocb->iotag, elsiocb->iocb.ulpContext,
-ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
-ndlp->nlp_rpi, vport->fc_flag);
if (ndlp->nlp_flag & NLP_LOGO_ACC) {
spin_lock_irq(shost->host_lock);
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED ||
@@ -4523,6 +4516,15 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct 
lpfc_iocbq *oldiocb,
lpfc_els_free_iocb(phba, elsiocb);
return 1;
}
+
+   /* Xmit ELS ACC response tag  */
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+"0128 Xmit ELS ACC response Status: x%x, IoTag: x%x, "
+"XRI: x%x, DID: x%x, nlp_flag: x%x nlp_state: x%x "
+"RPI: x%x, fc_flag x%x\n",
+rc, elsiocb->iotag, elsiocb->sli4_xritag,
+ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ndlp->nlp_rpi, vport->fc_flag);
return 0;
 }
 
@@ -6533,6 +6535,11 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct 
lpfc_iocbq *cmdiocb,
port_state = vport->port_state;
vport->fc_flag |= FC_PT2PT;
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+
+   /* Acking an unsol FLOGI.  Count 1 for link bounce
+* work-around.
+*/
+   vport->rcv_flogi_cnt++;
spin_unlock_irq(shost->host_lock);
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 "3311 Rcv Flogi PS x%x new PS x%x "
@@ -7930,8 +7937,9 @@ lpfc_els_unsol_buffer(struct

[PATCH 10/12] lpfc: Implement GID_PT on Nameserver query to support faster failover

2018-10-23 Thread James Smart
The switches seem to respond faster to GID_PT vs GID_FT NameServer
queries.  Add support for GID_PT to be used over GID_FT to enable
faster storage failover detection. Includes addition of new module
parameter to select between GID_PT and GID_FT (GID_FT is default).

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h   |   1 +
 drivers/scsi/lpfc/lpfc_attr.c  |  14 +++
 drivers/scsi/lpfc/lpfc_crtn.h  |   1 +
 drivers/scsi/lpfc/lpfc_ct.c| 206 +
 drivers/scsi/lpfc/lpfc_els.c   |  10 +-
 drivers/scsi/lpfc/lpfc_hbadisc.c   |  29 ++
 drivers/scsi/lpfc/lpfc_hw.h|   1 +
 drivers/scsi/lpfc/lpfc_hw4.h   |   4 +
 drivers/scsi/lpfc/lpfc_nportdisc.c |  13 ++-
 9 files changed, 275 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 1dfe71f0fcfd..979366fc34d4 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -784,6 +784,7 @@ struct lpfc_hba {
 #define LPFC_FCF_PRIORITY 2/* Priority fcf failover */
uint32_t cfg_fcf_failover_policy;
uint32_t cfg_fcp_io_sched;
+   uint32_t cfg_ns_query;
uint32_t cfg_fcp2_no_tgt_reset;
uint32_t cfg_cr_delay;
uint32_t cfg_cr_count;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 73e2296796e6..159ede7032dc 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5065,6 +5065,18 @@ LPFC_ATTR_RW(fcp_io_sched, LPFC_FCP_SCHED_ROUND_ROBIN,
 "issuing commands [0] - Round Robin, [1] - Current CPU");
 
 /*
+ * lpfc_ns_query: Determine algrithmn for NameServer queries after RSCN
+ * range is [0,1]. Default value is 0.
+ * For [0], GID_FT is used for NameServer queries after RSCN (default)
+ * For [1], GID_PT is used for NameServer queries after RSCN
+ *
+ */
+LPFC_ATTR_RW(ns_query, LPFC_NS_QUERY_GID_FT,
+LPFC_NS_QUERY_GID_FT, LPFC_NS_QUERY_GID_PT,
+"Determine algorithm NameServer queries after RSCN "
+"[0] - GID_FT, [1] - GID_PT");
+
+/*
 # lpfc_fcp2_no_tgt_reset: Determine bus reset behavior
 # range is [0,1]. Default value is 0.
 # For [0], bus reset issues target reset to ALL devices
@@ -5509,6 +5521,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_lpfc_scan_down,
_attr_lpfc_link_speed,
_attr_lpfc_fcp_io_sched,
+   _attr_lpfc_ns_query,
_attr_lpfc_fcp2_no_tgt_reset,
_attr_lpfc_cr_delay,
_attr_lpfc_cr_count,
@@ -6559,6 +6572,7 @@ void
 lpfc_get_cfgparam(struct lpfc_hba *phba)
 {
lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
+   lpfc_ns_query_init(phba, lpfc_ns_query);
lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
lpfc_cr_delay_init(phba, lpfc_cr_delay);
lpfc_cr_count_init(phba, lpfc_cr_count);
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index e9b297a39e54..a4b1bc2782eb 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -175,6 +175,7 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *);
 void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
 struct lpfc_iocbq *);
 int lpfc_ct_handle_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
+int lpfc_issue_gidpt(struct lpfc_vport *vport);
 int lpfc_issue_gidft(struct lpfc_vport *vport);
 int lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *iocbq);
 int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 789ad1502534..62e8ae3b4685 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -832,6 +832,198 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
 }
 
 static void
+lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+   struct lpfc_iocbq *rspiocb)
+{
+   struct lpfc_vport *vport = cmdiocb->vport;
+   struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+   IOCB_t *irsp;
+   struct lpfc_dmabuf *outp;
+   struct lpfc_dmabuf *inp;
+   struct lpfc_sli_ct_request *CTrsp;
+   struct lpfc_sli_ct_request *CTreq;
+   struct lpfc_nodelist *ndlp;
+   int rc;
+
+   /* First save ndlp, before we overwrite it */
+   ndlp = cmdiocb->context_un.ndlp;
+
+   /* we pass cmdiocb to state machine which needs rspiocb as well */
+   cmdiocb->context_un.rsp_iocb = rspiocb;
+   inp = (struct lpfc_dmabuf *)cmdiocb->context1;
+   outp = (struct lpfc_dmabuf *)cmdiocb->context2;
+   irsp = >iocb;
+
+   lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+ "GID_PT cmpl: status:x%x/x%x rtry:%d",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+  

[PATCH 01/12] lpfc: Correct speeds on SFP swap

2018-10-23 Thread James Smart
Supported speeds is not updated when SFP is removed or replaced

Supported speed is obtained from lmt field in READ_CONFIG mailbox
response. Driver updates supported speeds only once from PCI probe
path. After that it is never updated. So, supported speeds remains
the same till reboot or driver reload.

When SFP is removed or inserted, driver gets SLI-Port Event ACQE.
If SFP is removed, lmt wil have value 0. If a different SFP is
inserted, lmt will have value according to its supported speeds.
So, afterr SLI-Port Event ACQE handling path, send READ_CONFIG mailbox
and update supported speeds. If READ_CONFIG fails, set supported
speeds to unknown and log.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_init.c | 63 +++
 1 file changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 323a32e87258..c78ae81b5701 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4102,6 +4102,30 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned 
long time)
return stat;
 }
 
+void lpfc_host_supported_speeds_set(struct Scsi_Host *shost)
+{
+   struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+   struct lpfc_hba   *phba = vport->phba;
+
+   fc_host_supported_speeds(shost) = 0;
+   if (phba->lmt & LMT_64Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_64GBIT;
+   if (phba->lmt & LMT_32Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_32GBIT;
+   if (phba->lmt & LMT_16Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_16GBIT;
+   if (phba->lmt & LMT_10Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT;
+   if (phba->lmt & LMT_8Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_8GBIT;
+   if (phba->lmt & LMT_4Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT;
+   if (phba->lmt & LMT_2Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_2GBIT;
+   if (phba->lmt & LMT_1Gb)
+   fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
+}
+
 /**
  * lpfc_host_attrib_init - Initialize SCSI host attributes on a FC port
  * @shost: pointer to SCSI host data structure.
@@ -4129,23 +4153,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
 sizeof fc_host_symbolic_name(shost));
 
-   fc_host_supported_speeds(shost) = 0;
-   if (phba->lmt & LMT_64Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_64GBIT;
-   if (phba->lmt & LMT_32Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_32GBIT;
-   if (phba->lmt & LMT_16Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_16GBIT;
-   if (phba->lmt & LMT_10Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT;
-   if (phba->lmt & LMT_8Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_8GBIT;
-   if (phba->lmt & LMT_4Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT;
-   if (phba->lmt & LMT_2Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_2GBIT;
-   if (phba->lmt & LMT_1Gb)
-   fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
+   lpfc_host_supported_speeds_set(shost);
 
fc_host_maxframe_size(shost) =
(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
@@ -4758,6 +4766,8 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct 
lpfc_acqe_sli *acqe_sli)
struct temp_event temp_event_data;
struct lpfc_acqe_misconfigured_event *misconfigured;
struct Scsi_Host  *shost;
+   struct lpfc_vport **vports;
+   int rc, i;
 
evt_type = bf_get(lpfc_trailer_type, acqe_sli);
 
@@ -4883,6 +4893,25 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct 
lpfc_acqe_sli *acqe_sli)
sprintf(message, "Unknown event status x%02x", status);
break;
}
+
+   /* Issue READ_CONFIG mbox command to refresh supported speeds */
+   rc = lpfc_sli4_read_config(phba);
+   if (rc == -EIO) {
+   phba->lmt = 0;
+   lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+   "3194 Unable to retrieve supported "
+   "speeds\n");
+   }
+   vports = lpfc_create_vport_work_array(phba);
+   if (vports != NULL) {
+   for (i = 

[PATCH 03/12] lpfc: Fix LOGO/PLOGI handling when triggerd by ABTS Timeout event

2018-10-23 Thread James Smart
After a LOGO in response to an ABTS timeout, a PLOGI wasn't issued
to re-establish the login.  A nlp_type check in the LOGO completion
handler failed to restart discovery for NVME targets.  Revised the
nlp_type check for NVME as well as SCSI.

While reviewing the LOGO handling a few other issues were seen and
were addressed:
- Better lock synchronization around ndlp data types
- When the ABTS times out, unregister the RPI before sending the
  LOGO so that all local exchange contexts are cleared and nothing
  received while awaiting LOGO/PLOGI handling will be accepted.
- LOGO handling optimized to:
   Wait only R_A_TOV for a response.
   It doesn't need to be retried on timeout. If there wasn't a
 response, a PLOGI will be sent, thus an implicit logout
 applies as well when the other port sees it.
   If there is a response, any kind of response is considered "good"
 and the XRI quarantined for a exchange qualifier window.
- PLOGI is issued as soon a LOGO state is resolved.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c   | 49 --
 drivers/scsi/lpfc/lpfc_nportdisc.c |  5 
 2 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index f1c1faa74b46..8160a5ebad08 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -242,6 +242,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t 
expectRsp,
icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
if (elscmd == ELS_CMD_FLOGI)
icmd->ulpTimeout = FF_DEF_RATOV * 2;
+   else if (elscmd == ELS_CMD_LOGO)
+   icmd->ulpTimeout = phba->fc_ratov;
else
icmd->ulpTimeout = phba->fc_ratov * 2;
} else {
@@ -2682,16 +2684,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
goto out;
}
 
+   /* The LOGO will not be retried on failure.  A LOGO was
+* issued to the remote rport and a ACC or RJT or no Answer are
+* all acceptable.  Note the failure and move forward with
+* discovery.  The PLOGI will retry.
+*/
if (irsp->ulpStatus) {
-   /* Check for retry */
-   if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
-   /* ELS command is being retried */
-   skip_recovery = 1;
-   goto out;
-   }
/* LOGO failed */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-"2756 LOGO failure DID:%06X Status:x%x/x%x\n",
+"2756 LOGO failure, No Retry DID:%06X 
Status:x%x/x%x\n",
 ndlp->nlp_DID, irsp->ulpStatus,
 irsp->un.ulpWord[4]);
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
@@ -2737,7 +2738,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
 * For any other port type, the rpi is unregistered as an implicit
 * LOGO.
 */
-   if ((ndlp->nlp_type & NLP_FCP_TARGET) && (skip_recovery == 0)) {
+   if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) &&
+   skip_recovery == 0) {
lpfc_cancel_retry_delay_tmo(vport, ndlp);
spin_lock_irqsave(shost->host_lock, flags);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -2770,6 +2772,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
  * will be stored into the context1 field of the IOCB for the completion
  * callback function to the LOGO ELS command.
  *
+ * Callers of this routine are expected to unregister the RPI first
+ *
  * Return code
  *   0 - successfully issued logo
  *   1 - failed to issue logo
@@ -2811,22 +2815,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
"Issue LOGO:  did:x%x",
ndlp->nlp_DID, 0, 0);
 
-   /*
-* If we are issuing a LOGO, we may try to recover the remote NPort
-* by issuing a PLOGI later. Even though we issue ELS cmds by the
-* VPI, if we have a valid RPI, and that RPI gets unreg'ed while
-* that ELS command is in-flight, the HBA returns a IOERR_INVALID_RPI
-* for that ELS cmd. To avoid this situation, lets get rid of the
-* RPI right now, before any ELS cmds are sent.
-*/
-   spin_lock_irq(shost->host_lock);
-   ndlp->nlp_flag |= NLP_ISSUE_LOGO;
-   spin_unlock_irq(shost->host_lock);
-   if (lpfc_unreg_rpi(vport, ndlp)) {
-   lpfc_els_free_iocb(phba, elsiocb);
-   return 0;
-   }
-
phba->fc_stat.elsXmitLOGO++;
elsiocb-&

[PATCH 06/12] lpfc: fcoe: Fix link down issue after 1000+ link bounces

2018-10-23 Thread James Smart
On FCoE adapters, when running link bounce test in a loop,
initiator failed to login with switch switch and required driver
reload to recover. Switch reached a point where all subsequent
FLOGIs would be LS_RJT'd. Further testing showed the condition to
be related to not performing FCF discovery between FLOGI's.

Fix by monitoring FLOGI failures and once a repeated error is
seen repeat FCF discovery.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c |  2 ++
 drivers/scsi/lpfc/lpfc_hbadisc.c | 20 
 drivers/scsi/lpfc/lpfc_init.c|  2 +-
 drivers/scsi/lpfc/lpfc_sli.c | 11 ++-
 drivers/scsi/lpfc/lpfc_sli4.h|  1 +
 5 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index e3e851931394..25625c03a5b3 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1157,6 +1157,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
phba->hba_flag &= ~(FCF_RR_INPROG | HBA_DEVLOSS_TMO);
spin_unlock_irq(>hbalock);
+   phba->fcf.fcf_redisc_attempted = 0; /* reset */
goto out;
}
if (!rc) {
@@ -1171,6 +1172,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
phba->hba_flag &= ~(FCF_RR_INPROG | HBA_DEVLOSS_TMO);
spin_unlock_irq(>hbalock);
+   phba->fcf.fcf_redisc_attempted = 0; /* reset */
goto out;
}
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index f4deb862efc6..a26db7e1d821 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1992,6 +1992,26 @@ int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *vport, 
uint16_t fcf_index)
"failover and change port state:x%x/x%x\n",
phba->pport->port_state, LPFC_VPORT_UNKNOWN);
phba->pport->port_state = LPFC_VPORT_UNKNOWN;
+
+   if (!phba->fcf.fcf_redisc_attempted) {
+   lpfc_unregister_fcf(phba);
+
+   rc = lpfc_sli4_redisc_fcf_table(phba);
+   if (!rc) {
+   lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+   "3195 Rediscover FCF table\n");
+   phba->fcf.fcf_redisc_attempted = 1;
+   lpfc_sli4_clear_fcf_rr_bmask(phba);
+   } else {
+   lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+   "3196 Rediscover FCF table "
+   "failed. Status:x%x\n", rc);
+   }
+   } else {
+   lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+   "3197 Already rediscover FCF table "
+   "attempted. No more retry\n");
+   }
goto stop_flogi_current_fcf;
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_ELS,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 098b5ef3e9b8..d0a1fba1fc74 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -5069,7 +5069,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
break;
}
/* If fast FCF failover rescan event is pending, do nothing */
-   if (phba->fcf.fcf_flag & FCF_REDISC_EVT) {
+   if (phba->fcf.fcf_flag & (FCF_REDISC_EVT | FCF_REDISC_PEND)) {
spin_unlock_irq(>hbalock);
break;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 783a1540cfbe..ee56ab63c657 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -18712,15 +18712,8 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
goto initial_priority;
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
"2844 No roundrobin failover FCF available\n");
-   if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
-   return LPFC_FCOE_FCF_NEXT_NONE;
-   else {
-   lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
-   "3063 Only

[PATCH 11/12] lpfc: add Trunking support

2018-10-23 Thread James Smart
Add trunking support to the driver. Trunking is found on more recent
asics. In general, trunking appears as a single "port" to the driver
and overall behavior doesn't differ. Link speed is reported as an
aggregate value, while link speed control is done on a per-physical
link basis with all links in the trunk symmetrical. Some commands
returning port information are updated to additionally provide
trunking information. And new ACQEs are generated to report physical
link events relative to the trunk.

This patch contains the following modifications:
Added link speed settings of 128GB and 256GB.
Added handling of trunk-related ACQEs, mainly logging and trapping
  of physical link statuses.
Added additional bsg interface to query trunk state by applications.
Augment link_state sysfs attribtute to display trunk link status

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h |  13 
 drivers/scsi/lpfc/lpfc_attr.c| 101 ++
 drivers/scsi/lpfc/lpfc_bsg.c |  74 
 drivers/scsi/lpfc/lpfc_bsg.h |  38 ++
 drivers/scsi/lpfc/lpfc_ct.c  |   5 ++
 drivers/scsi/lpfc/lpfc_els.c |   2 +
 drivers/scsi/lpfc/lpfc_hbadisc.c |   1 +
 drivers/scsi/lpfc/lpfc_hw4.h |  64 +
 drivers/scsi/lpfc/lpfc_init.c| 148 +++
 drivers/scsi/lpfc/lpfc_scsi.h|   4 ++
 drivers/scsi/lpfc/lpfc_sli.c |  11 +++
 drivers/scsi/lpfc/lpfc_sli4.h|  13 
 12 files changed, 474 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 979366fc34d4..de85f816ce07 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -335,6 +335,18 @@ enum hba_state {
LPFC_HBA_ERROR   =  -1
 };
 
+struct lpfc_trunk_link_state {
+   enum hba_state state;
+   uint8_t fault;
+};
+
+struct lpfc_trunk_link  {
+   struct lpfc_trunk_link_state link0,
+link1,
+link2,
+link3;
+};
+
 struct lpfc_vport {
struct lpfc_hba *phba;
struct list_head listentry;
@@ -684,6 +696,7 @@ struct lpfc_hba {
uint32_t iocb_cmd_size;
uint32_t iocb_rsp_size;
 
+   struct lpfc_trunk_link  trunk_link;
enum hba_state link_state;
uint32_t link_flag; /* link state flags */
 #define LS_LOOPBACK_MODE  0x1  /* NPort is in Loopback mode */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 159ede7032dc..9528c4932f55 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -883,6 +883,42 @@ lpfc_link_state_show(struct device *dev, struct 
device_attribute *attr,
}
}
 
+   if ((phba->sli_rev == LPFC_SLI_REV4) &&
+   ((bf_get(lpfc_sli_intf_if_type,
+>sli4_hba.sli_intf) ==
+LPFC_SLI_INTF_IF_TYPE_6))) {
+   struct lpfc_trunk_link link = phba->trunk_link;
+
+   if (bf_get(lpfc_conf_trunk_port0, >sli4_hba))
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "Trunk port 0: Link %s %s\n",
+   (link.link0.state == LPFC_LINK_UP) ?
+"Up" : "Down. ",
+   trunk_errmsg[link.link0.fault]);
+
+   if (bf_get(lpfc_conf_trunk_port1, >sli4_hba))
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "Trunk port 1: Link %s %s\n",
+   (link.link1.state == LPFC_LINK_UP) ?
+"Up" : "Down. ",
+   trunk_errmsg[link.link1.fault]);
+
+   if (bf_get(lpfc_conf_trunk_port2, >sli4_hba))
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "Trunk port 2: Link %s %s\n",
+   (link.link2.state == LPFC_LINK_UP) ?
+"Up" : "Down. ",
+   trunk_errmsg[link.link2.fault]);
+
+   if (bf_get(lpfc_conf_trunk_port3, >sli4_hba))
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "Trunk port 3: Link %s %s\n",
+   (link.link3.state == LPFC_LINK_UP) ?
+"Up" : "Down. ",
+   trunk_errmsg[link.link3.fault]);
+
+   }
+
return len;
 }
 
@@ -1430,6 +1466,66 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct 
device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
 }
 
+int
+lpfc_set_trunking(struct lpfc_hba *phba

[PATCH 02/12] lpfc: Fix lpfc_sli4_read_config return value check

2018-10-23 Thread James Smart
An error is an error - but not to the existing return value check.

Revise check to handle any failure, not just EIO.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_init.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index c78ae81b5701..098b5ef3e9b8 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4896,11 +4896,11 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct 
lpfc_acqe_sli *acqe_sli)
 
/* Issue READ_CONFIG mbox command to refresh supported speeds */
rc = lpfc_sli4_read_config(phba);
-   if (rc == -EIO) {
+   if (rc) {
phba->lmt = 0;
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3194 Unable to retrieve supported "
-   "speeds\n");
+   "speeds, rc = 0x%x\n", rc);
}
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) {
-- 
2.13.1



[PATCH 05/12] lpfc: Correct errors accessing fw log

2018-10-23 Thread James Smart
This patch corrects two issues:
- An oops would occur if reading based on a non-zero offset.
  Offset calculation was incorrect.
- Updates to ras config (logging level) were ignored if change
  was made while fw logging was enabled. Revise to dynamically
  update.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_bsg.c | 64 +---
 1 file changed, 25 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 7bd7ae86bed5..eb2e8c941b78 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -5416,7 +5416,7 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
struct lpfc_ras_fwlog *ras_fwlog = >ras_fwlog;
struct fc_bsg_reply *bsg_reply = job->reply;
uint8_t action = 0, log_level = 0;
-   int rc = 0;
+   int rc = 0, action_status = 0;
 
if (job->request_len <
sizeof(struct fc_bsg_request) +
@@ -5449,16 +5449,25 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
lpfc_ras_stop_fwlog(phba);
} else {
/*action = LPFC_RASACTION_START_LOGGING*/
-   if (ras_fwlog->ras_active == true) {
-   rc = -EINPROGRESS;
-   goto ras_job_error;
-   }
+
+   /* Even though FW-logging is active re-initialize
+* FW-logging with new log-level. Return status
+* "Logging already Running" to caller.
+**/
+   if (ras_fwlog->ras_active)
+   action_status = -EINPROGRESS;
 
/* Enable logging */
rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
  LPFC_RAS_ENABLE_LOGGING);
-   if (rc)
+   if (rc) {
rc = -EINVAL;
+   goto ras_job_error;
+   }
+
+   /* Check if FW-logging is re-initialized */
+   if (action_status == -EINPROGRESS)
+   rc = action_status;
}
 ras_job_error:
/* make error code available to userspace */
@@ -5487,8 +5496,7 @@ lpfc_bsg_get_ras_lwpd(struct bsg_job *job)
struct lpfc_hba *phba = vport->phba;
struct lpfc_ras_fwlog *ras_fwlog = >ras_fwlog;
struct fc_bsg_reply *bsg_reply = job->reply;
-   uint32_t lwpd_offset = 0;
-   uint64_t wrap_value = 0;
+   u32 *lwpd_ptr = NULL;
int rc = 0;
 
rc = lpfc_check_fwlog_support(phba);
@@ -5508,11 +5516,12 @@ lpfc_bsg_get_ras_lwpd(struct bsg_job *job)
ras_reply = (struct lpfc_bsg_get_ras_lwpd *)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
 
-   lwpd_offset = *((uint32_t *)ras_fwlog->lwpd.virt) & 0x;
-   ras_reply->offset = be32_to_cpu(lwpd_offset);
+   /* Get lwpd offset */
+   lwpd_ptr = (uint32_t *)(ras_fwlog->lwpd.virt);
+   ras_reply->offset = be32_to_cpu(*lwpd_ptr & 0x);
 
-   wrap_value = *((uint64_t *)ras_fwlog->lwpd.virt);
-   ras_reply->wrap_count = be32_to_cpu((wrap_value >> 32) & 0x);
+   /* Get wrap count */
+   ras_reply->wrap_count = be32_to_cpu(*(++lwpd_ptr) & 0x);
 
 ras_job_error:
/* make error code available to userspace */
@@ -5539,9 +5548,8 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
struct fc_bsg_request *bsg_request = job->request;
struct fc_bsg_reply *bsg_reply = job->reply;
struct lpfc_bsg_get_fwlog_req *ras_req;
-   uint32_t rd_offset, rd_index, offset, pending_wlen;
-   uint32_t boundary = 0, align_len = 0, write_len = 0;
-   void *dest, *src, *fwlog_buff;
+   u32 rd_offset, rd_index, offset;
+   void *src, *fwlog_buff;
struct lpfc_ras_fwlog *ras_fwlog = NULL;
struct lpfc_dmabuf *dmabuf, *next;
int rc = 0;
@@ -5581,8 +5589,6 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
 
rd_index = (rd_offset / LPFC_RAS_MAX_ENTRY_SIZE);
offset = (rd_offset % LPFC_RAS_MAX_ENTRY_SIZE);
-   pending_wlen = ras_req->read_size;
-   dest = fwlog_buff;
 
list_for_each_entry_safe(dmabuf, next,
  _fwlog->fwlog_buff_list, list) {
@@ -5590,29 +5596,9 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
if (dmabuf->buffer_tag < rd_index)
continue;
 
-   /* Align read to buffer size */
-   if (offset) {
-   boundary = ((dmabuf->buffer_tag + 1) *
-   LPFC_RAS_MAX_ENTRY_SIZE);
-
-   align_len = (boundary - offset);
-   write_len = min_t(u32, align_len,
- LPFC_RAS_MAX_ENTRY_SIZE);
-   } else {
- 

[PATCH v2] lpfc: Synchronize access to remoteport via rport

2018-09-13 Thread James Smart
The driver currently uses the ndlp to get the local rport which is
then used to get the nvme transport remoteport pointer. There can
be cases where a stale remoteport pointer is obtained as
synchronization isn't done through the different dereferences.

Correct by using locks to synchronize the dereferences.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 

---
v2:
  Needed to reinit nrport to NULL at start of every ndlp check
---
 drivers/scsi/lpfc/lpfc_attr.c| 15 ++-
 drivers/scsi/lpfc/lpfc_debugfs.c | 10 +-
 drivers/scsi/lpfc/lpfc_nvme.c| 11 ---
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 0169cd406518..dda7f450b96d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -360,12 +360,12 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
goto buffer_done;
 
list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
+   nrport = NULL;
+   spin_lock(>phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
-   if (!rport)
-   continue;
-
-   /* local short-hand pointer. */
-   nrport = rport->remoteport;
+   if (rport)
+   nrport = rport->remoteport;
+   spin_unlock(>phba->hbalock);
if (!nrport)
continue;
 
@@ -3386,6 +3386,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
struct lpfc_nodelist  *ndlp;
 #if (IS_ENABLED(CONFIG_NVME_FC))
struct lpfc_nvme_rport *rport;
+   struct nvme_fc_remote_port *remoteport = NULL;
 #endif
 
shost = lpfc_shost_from_vport(vport);
@@ -3396,8 +3397,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
 #if (IS_ENABLED(CONFIG_NVME_FC))
+   spin_lock(>phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
if (rport)
+   remoteport = rport->remoteport;
+   spin_unlock(>phba->hbalock);
+   if (remoteport)
nvme_fc_set_remoteport_devloss(rport->remoteport,
   vport->cfg_devloss_tmo);
 #endif
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 9df0c051349f..aec5b10a8c85 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -551,7 +551,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
unsigned char *statep;
struct nvme_fc_local_port *localport;
struct lpfc_nvmet_tgtport *tgtp;
-   struct nvme_fc_remote_port *nrport;
+   struct nvme_fc_remote_port *nrport = NULL;
struct lpfc_nvme_rport *rport;
 
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
@@ -696,11 +696,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
len += snprintf(buf + len, size - len, "\tRport List:\n");
list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
/* local short-hand pointer. */
+   spin_lock(>hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
-   if (!rport)
-   continue;
-
-   nrport = rport->remoteport;
+   if (rport)
+   nrport = rport->remoteport;
+   spin_unlock(>hbalock);
if (!nrport)
continue;
 
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 543873232d5a..23343a65530c 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2718,7 +2718,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp)
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
 
+   spin_lock_irq(>phba->hbalock);
oldrport = lpfc_ndlp_get_nrport(ndlp);
+   spin_unlock_irq(>phba->hbalock);
if (!oldrport)
lpfc_nlp_get(ndlp);
 
@@ -2833,7 +2835,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport;
-   struct nvme_fc_remote_port *remoteport;
+   struct nvme_fc_remote_port *remoteport = NULL;
 
localport = vport->localport;
 
@@ -2847,11 +2849,14 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
if (!lport)
goto input_err;
 
+   spin_lock_irq(>phba->hbalock);
rpo

Re: [PATCH] lpfc: Synchronize access to remoteport via rport

2018-09-13 Thread James Smart

On 9/12/2018 4:28 PM, James Smart wrote:

The driver currently uses the ndlp to get the local rport which is
then used to get the nvme transport remoteport pointer. There can
be cases where a stale remoteport pointer is obtained as
synchronization isn't done through the different dereferences.

Correct by using locks to synchronize the dereferences.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 


Please disregard. There was a slight error in this fix.

-- james



[PATCH] lpfc: Synchronize access to remoteport via rport

2018-09-12 Thread James Smart
The driver currently uses the ndlp to get the local rport which is
then used to get the nvme transport remoteport pointer. There can
be cases where a stale remoteport pointer is obtained as
synchronization isn't done through the different dereferences.

Correct by using locks to synchronize the dereferences.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c| 16 ++--
 drivers/scsi/lpfc/lpfc_debugfs.c | 10 +-
 drivers/scsi/lpfc/lpfc_nvme.c| 11 ---
 3 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 0169cd406518..5dbbf2a9bfa5 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -154,7 +154,7 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport;
struct lpfc_nodelist *ndlp;
-   struct nvme_fc_remote_port *nrport;
+   struct nvme_fc_remote_port *nrport = NULL;
struct lpfc_nvme_ctrl_stat *cstat;
uint64_t data1, data2, data3;
uint64_t totin, totout, tot;
@@ -360,12 +360,11 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
goto buffer_done;
 
list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
+   spin_lock(>phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
-   if (!rport)
-   continue;
-
-   /* local short-hand pointer. */
-   nrport = rport->remoteport;
+   if (rport)
+   nrport = rport->remoteport;
+   spin_unlock(>phba->hbalock);
if (!nrport)
continue;
 
@@ -3386,6 +3385,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
struct lpfc_nodelist  *ndlp;
 #if (IS_ENABLED(CONFIG_NVME_FC))
struct lpfc_nvme_rport *rport;
+   struct nvme_fc_remote_port *remoteport = NULL;
 #endif
 
shost = lpfc_shost_from_vport(vport);
@@ -3396,8 +3396,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
 #if (IS_ENABLED(CONFIG_NVME_FC))
+   spin_lock(>phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
if (rport)
+   remoteport = rport->remoteport;
+   spin_unlock(>phba->hbalock);
+   if (remoteport)
nvme_fc_set_remoteport_devloss(rport->remoteport,
   vport->cfg_devloss_tmo);
 #endif
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 9df0c051349f..aec5b10a8c85 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -551,7 +551,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
unsigned char *statep;
struct nvme_fc_local_port *localport;
struct lpfc_nvmet_tgtport *tgtp;
-   struct nvme_fc_remote_port *nrport;
+   struct nvme_fc_remote_port *nrport = NULL;
struct lpfc_nvme_rport *rport;
 
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
@@ -696,11 +696,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
len += snprintf(buf + len, size - len, "\tRport List:\n");
list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
/* local short-hand pointer. */
+   spin_lock(>hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
-   if (!rport)
-   continue;
-
-   nrport = rport->remoteport;
+   if (rport)
+   nrport = rport->remoteport;
+   spin_unlock(>hbalock);
if (!nrport)
continue;
 
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 543873232d5a..23343a65530c 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2718,7 +2718,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp)
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
 
+   spin_lock_irq(>phba->hbalock);
oldrport = lpfc_ndlp_get_nrport(ndlp);
+   spin_unlock_irq(>phba->hbalock);
if (!oldrport)
lpfc_nlp_get(ndlp);
 
@@ -2833,7 +2835,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport;
-   struct nvme_fc_remote_port *remotepo

[PATCH 10/11] lpfc: add support to retrieve firmware logs

2018-09-10 Thread James Smart
This patch adds the ability to read firmware logs from the
adapter. The driver registers a buffer with the adapter that
is then written to by the adapter. The adapter posts CQEs to
indicate content updates in the buffer. While the adapter is
writing to the buffer in a circular fashion, an application will
polls the driver to read the next amount of log data from the
buffer.

Driver log buffer size is configurable via the ras_fwlog_buffsize
sysfs attribute. Verbosity to be used by firmware when logging to
host memory is controlled through the ras_fwlog_level attribute.
The ras_fwlog_func attribute enables or disables loggy by firmware.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h  |  25 
 drivers/scsi/lpfc/lpfc_attr.c |  32 
 drivers/scsi/lpfc/lpfc_bsg.c  | 341 +-
 drivers/scsi/lpfc/lpfc_bsg.h  |  36 +
 drivers/scsi/lpfc/lpfc_crtn.h |   7 +
 drivers/scsi/lpfc/lpfc_hw4.h  |  45 ++
 drivers/scsi/lpfc/lpfc_init.c |  40 +
 drivers/scsi/lpfc/lpfc_sli.c  | 265 
 drivers/scsi/lpfc/lpfc_sli4.h |   1 +
 9 files changed, 790 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 327751447355..c1eb2b00ca7f 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -583,6 +583,25 @@ struct lpfc_mbox_ext_buf_ctx {
struct list_head ext_dmabuf_list;
 };
 
+struct lpfc_ras_fwlog {
+   uint8_t *fwlog_buff;
+   uint32_t fw_buffcount; /* Buffer size posted to FW */
+#define LPFC_RAS_BUFF_ENTERIES  16  /* Each entry can hold max of 64k */
+#define LPFC_RAS_MAX_ENTRY_SIZE (64 * 1024)
+#define LPFC_RAS_MIN_BUFF_POST_SIZE (256 * 1024)
+#define LPFC_RAS_MAX_BUFF_POST_SIZE (1024 * 1024)
+   uint32_t fw_loglevel; /* Log level set */
+   struct lpfc_dmabuf lwpd;
+   struct list_head fwlog_buff_list;
+
+   /* RAS support status on adapter */
+   bool ras_hwsupport; /* RAS Support available on HW or not */
+   bool ras_enabled;   /* Ras Enabled for the function */
+#define LPFC_RAS_DISABLE_LOGGING 0x00
+#define LPFC_RAS_ENABLE_LOGGING 0x01
+   bool ras_active;/* RAS logging running state */
+};
+
 struct lpfc_hba {
/* SCSI interface function jump table entries */
int (*lpfc_new_scsi_buf)
@@ -834,6 +853,9 @@ struct lpfc_hba {
 #define LPFC_FDMI_SUPPORT  1   /* FDMI supported? */
uint32_t cfg_enable_SmartSAN;
uint32_t cfg_enable_mds_diags;
+   uint32_t cfg_ras_fwlog_level;
+   uint32_t cfg_ras_fwlog_buffsize;
+   uint32_t cfg_ras_fwlog_func;
uint32_t cfg_enable_fc4_type;
uint32_t cfg_enable_bbcr;   /* Enable BB Credit Recovery */
uint32_t cfg_enable_dpp;/* Enable Direct Packet Push */
@@ -1094,6 +1116,9 @@ struct lpfc_hba {
struct unsol_rcv_ct_ctx ct_ctx[LPFC_CT_CTX_MAX];
uint32_t ctx_idx;
 
+   /* RAS Support */
+   struct lpfc_ras_fwlog ras_fwlog;
+
uint8_t menlo_flag; /* menlo generic flags */
 #define HBA_MENLO_SUPPORT  0x1 /* HBA supports menlo commands */
uint32_t iocb_cnt;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 9d2397b795f4..0169cd406518 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5431,6 +5431,31 @@ lpfc_sg_seg_cnt_init(struct lpfc_hba *phba, int val)
 LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
 
 /*
+ * lpfc_ras_fwlog_buffsize: Firmware logging host buffer size
+ * 0 = Disable firmware logging (default)
+ * [1-4] = Multiple of 1/4th Mb of host memory for FW logging
+ * Value range [0..4]. Default value is 0
+ */
+LPFC_ATTR_RW(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
+
+/*
+ * lpfc_ras_fwlog_level: Firmware logging verbosity level
+ * Valid only if firmware logging is enabled
+ * 0(Least Verbosity) 4 (most verbosity)
+ * Value range is [0..4]. Default value is 0
+ */
+LPFC_ATTR_RW(ras_fwlog_level, 0, 0, 4, "Firmware Logging Level");
+
+/*
+ * lpfc_ras_fwlog_func: Firmware logging enabled on function number
+ * Default function which has RAS support : 0
+ * Value Range is [0..7].
+ * FW logging is a global action and enablement is via a specific
+ * port.
+ */
+LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function");
+
+/*
  * lpfc_enable_bbcr: Enable BB Credit Recovery
  *   0  = BB Credit Recovery disabled
  *   1  = BB Credit Recovery enabled (default)
@@ -,6 +5580,9 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_protocol,
_attr_lpfc_xlane_supported,
_attr_lpfc_enable_mds_diags,
+   _attr_lpfc_ras_fwlog_buffsize,
+   _attr_lpfc_ras_fwlog_level,
+   _attr_lpfc_ras_fwlog_func,
_attr_lpfc_enable_bbcr,
_attr_lpfc_enable_dpp,
NULL,
@@ -6641,6 +6669,10 @@ lpfc_get_cfgparam(struct lp

[PATCH 11/11] lpfc: update driver version to 12.0.0.7

2018-09-10 Thread James Smart
Update the driver version to 12.0.0.7

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 501249509af4..5a0d512ff497 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.6"
+#define LPFC_DRIVER_VERSION "12.0.0.7"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH 08/11] lpfc: Fix errors in log messages.

2018-09-10 Thread James Smart
Message 6408 is displayed for each entry in an array, but the
cpu and queue numbers were incorrect for the entry.
Message 6001 includes an extraneous character.

Resolve both issues

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nvme.c  | 2 +-
 drivers/scsi/lpfc/lpfc_nvmet.c | 7 +++
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index a84299c36c9f..543873232d5a 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -282,7 +282,7 @@ lpfc_nvme_delete_queue(struct nvme_fc_local_port 
*pnvme_lport,
vport = lport->vport;
 
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME,
-   "6001 ENTER.  lpfc_pnvme %p, qidx x%xi qhandle %p\n",
+   "6001 ENTER.  lpfc_pnvme %p, qidx x%x qhandle %p\n",
lport, qidx, handle);
kfree(handle);
 }
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 4926ca6f0b8c..6245f442d784 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1339,15 +1339,14 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
idx = 0;
}
 
-   infop = phba->sli4_hba.nvmet_ctx_info;
-   for (j = 0; j < phba->cfg_nvmet_mrq; j++) {
-   for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
+   for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
+   for (j = 0; j < phba->cfg_nvmet_mrq; j++) {
+   infop = lpfc_get_ctx_list(phba, i, j);
lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_INIT,
"6408 TOTAL NVMET ctx for CPU %d "
"MRQ %d: cnt %d nextcpu %p\n",
i, j, infop->nvmet_ctx_list_cnt,
infop->nvmet_ctx_next_cpu);
-   infop++;
}
}
return 0;
-- 
2.13.1



[PATCH 07/11] lpfc: Correct invalid EQ doorbell write on if_type=6

2018-09-10 Thread James Smart
During attachment, the driver writes the EQ doorbell to disable
potential interrupts from an EQ. The current EQ doorbell format
used for clearing the interrupt is incorrect and uses an if_type=2
format, making the operation act on the wrong EQ.

Correct the code to use the proper if_type=6 EQ doorbell format.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_sli.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 495de99ed82d..99fddd056675 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -392,11 +392,7 @@ lpfc_sli4_if6_eq_clr_intr(struct lpfc_queue *q)
struct lpfc_register doorbell;
 
doorbell.word0 = 0;
-   bf_set(lpfc_eqcq_doorbell_eqci, , 1);
-   bf_set(lpfc_eqcq_doorbell_qt, , LPFC_QUEUE_TYPE_EVENT);
-   bf_set(lpfc_eqcq_doorbell_eqid_hi, ,
-   (q->queue_id >> LPFC_EQID_HI_FIELD_SHIFT));
-   bf_set(lpfc_eqcq_doorbell_eqid_lo, , q->queue_id);
+   bf_set(lpfc_if6_eq_doorbell_eqid, , q->queue_id);
writel(doorbell.word0, q->phba->sli4_hba.EQDBregaddr);
 }
 
-- 
2.13.1



[PATCH 09/11] lpfc: reduce locking when updating statistics

2018-09-10 Thread James Smart
Currently, on each io completion, the stats update routine
indiscriminately holds a lock. While holding the adapter-wide lock,
checks are made to check whether status are being tracked. When
disabled (the default), the locking wasted a lot of cycles.

Check for stats enablement before taking the lock.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 200b5bca1f5f..f2d5420be413 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -202,8 +202,8 @@ lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
 static void
 lpfc_update_stats(struct lpfc_hba *phba, struct  lpfc_scsi_buf *lpfc_cmd)
 {
-   struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
-   struct lpfc_nodelist *pnode = rdata->pnode;
+   struct lpfc_rport_data *rdata;
+   struct lpfc_nodelist *pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
unsigned long flags;
struct Scsi_Host  *shost = cmd->device->host;
@@ -211,17 +211,19 @@ lpfc_update_stats(struct lpfc_hba *phba, struct  
lpfc_scsi_buf *lpfc_cmd)
unsigned long latency;
int i;
 
-   if (cmd->result)
+   if (!vport->stat_data_enabled ||
+   vport->stat_data_blocked ||
+   (cmd->result))
return;
 
latency = jiffies_to_msecs((long)jiffies - (long)lpfc_cmd->start_time);
+   rdata = lpfc_cmd->rdata;
+   pnode = rdata->pnode;
 
spin_lock_irqsave(shost->host_lock, flags);
-   if (!vport->stat_data_enabled ||
-   vport->stat_data_blocked ||
-   !pnode ||
-   !pnode->lat_data ||
-   (phba->bucket_type == LPFC_NO_BUCKET)) {
+   if (!pnode ||
+   !pnode->lat_data ||
+   (phba->bucket_type == LPFC_NO_BUCKET)) {
spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
-- 
2.13.1



[PATCH 06/11] lpfc: Correct irq handling via locks when taking adapter offline

2018-09-10 Thread James Smart
When taking the board offline while performing i/o, unsafe locking
errors occurred and irq level isn't properly managed.

In lpfc_sli_hba_down, spin_lock_irqsave(>hbalock, flags) does
not disable softirqs raised from timer expiry.  It is possible that
a softirq is raised from the lpfc_els_retry_delay routine and
recursively requests the same phba->hbalock spinlock causing deadlock.

Address the deadlocks by creating a new port_list lock. The softirq
behavior can then be managed a level deeper into the calling sequences.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h |  1 +
 drivers/scsi/lpfc/lpfc_ct.c  |  6 +++---
 drivers/scsi/lpfc/lpfc_els.c |  3 +++
 drivers/scsi/lpfc/lpfc_hbadisc.c |  6 +++---
 drivers/scsi/lpfc/lpfc_init.c| 19 +++
 drivers/scsi/lpfc/lpfc_sli.c | 25 -
 drivers/scsi/lpfc/lpfc_vport.c   | 14 +++---
 7 files changed, 52 insertions(+), 22 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 322b24f826a4..327751447355 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -964,6 +964,7 @@ struct lpfc_hba {
uint32_t intr_mode;
 #define LPFC_INTR_ERROR0x
struct list_head port_list;
+   spinlock_t port_list_lock;  /* lock for port_list mutations */
struct lpfc_vport *pport;   /* physical lpfc_vport pointer */
uint16_t max_vpi;   /* Maximum virtual nports */
 #define LPFC_MAX_VPI 0x/* Max number of VPI supported */
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 0eae8051e920..789ad1502534 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -445,14 +445,14 @@ lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t 
did) {
struct lpfc_vport *vport_curr;
unsigned long flags;
 
-   spin_lock_irqsave(>hbalock, flags);
+   spin_lock_irqsave(>port_list_lock, flags);
list_for_each_entry(vport_curr, >port_list, listentry) {
if ((vport_curr->fc_myDID) && (vport_curr->fc_myDID == did)) {
-   spin_unlock_irqrestore(>hbalock, flags);
+   spin_unlock_irqrestore(>port_list_lock, flags);
return vport_curr;
}
}
-   spin_unlock_irqrestore(>hbalock, flags);
+   spin_unlock_irqrestore(>port_list_lock, flags);
return NULL;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 4dda969e947c..f1c1faa74b46 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -7673,8 +7673,11 @@ void
 lpfc_els_flush_all_cmd(struct lpfc_hba  *phba)
 {
struct lpfc_vport *vport;
+
+   spin_lock_irq(>port_list_lock);
list_for_each_entry(vport, >port_list, listentry)
lpfc_els_flush_cmd(vport);
+   spin_unlock_irq(>port_list_lock);
 
return;
 }
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 235abd50e530..f9a038ec5256 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -5938,14 +5938,14 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t 
vpi)
}
}
 
-   spin_lock_irqsave(>hbalock, flags);
+   spin_lock_irqsave(>port_list_lock, flags);
list_for_each_entry(vport, >port_list, listentry) {
if (vport->vpi == i) {
-   spin_unlock_irqrestore(>hbalock, flags);
+   spin_unlock_irqrestore(>port_list_lock, flags);
return vport;
}
}
-   spin_unlock_irqrestore(>hbalock, flags);
+   spin_unlock_irqrestore(>port_list_lock, flags);
return NULL;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 90fb83f88179..bb2bff7b56b4 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3988,9 +3988,9 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, 
struct device *dev)
if (error)
goto out_put_shost;
 
-   spin_lock_irq(>hbalock);
+   spin_lock_irq(>port_list_lock);
list_add_tail(>listentry, >port_list);
-   spin_unlock_irq(>hbalock);
+   spin_unlock_irq(>port_list_lock);
return vport;
 
 out_put_shost:
@@ -4016,9 +4016,9 @@ destroy_port(struct lpfc_vport *vport)
fc_remove_host(shost);
scsi_remove_host(shost);
 
-   spin_lock_irq(>hbalock);
+   spin_lock_irq(>port_list_lock);
list_del_init(>listentry);
-   spin_unlock_irq(>hbalock);
+   spin_unlock_irq(>port_list_lock);
 
lpfc_cleanup(vport);
return;
@@ -5621,7 +5621,10 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
/* I

[PATCH 04/11] lpfc: Correct race with abort on completion path

2018-09-10 Thread James Smart
On io completion, the driver is taking an adapter wide lock and
nulling the scsi command back pointer.  The nulling of the back
pointer is to signify the io was completed and the scsi_done()
routine was called.  However, the routine makes no check to see
if the abort routine had done the same thing and possibly
nulled the pointer. Thus it may doubly-complete the io.

Make the following mods:
- Check to make sure forward progress (call scsi_done()) only happens
  if the command pointer was non-null.
- As the taking of the lock, which is adapter wide, is very costly
  on a system under load, null the pointer using an xchg operation
  rather than under lock.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 5c7858e735c9..200b5bca1f5f 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4158,9 +4158,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *pIocbIn,
}
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 
-   spin_lock_irqsave(>hbalock, flags);
-   lpfc_cmd->pCmd = NULL;
-   spin_unlock_irqrestore(>hbalock, flags);
+   /* If pCmd was set to NULL from abort path, do not call scsi_done */
+   if (xchg(_cmd->pCmd, NULL) == NULL) {
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+"0711 FCP cmd already NULL, sid: 0x%06x, "
+"did: 0x%06x, oxid: 0x%04x\n",
+vport->fc_myDID,
+(pnode) ? pnode->nlp_DID : 0,
+phba->sli_rev == LPFC_SLI_REV4 ?
+lpfc_cmd->cur_iocbq.sli4_xritag : 0x);
+   return;
+   }
 
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
cmd->scsi_done(cmd);
-- 
2.13.1



[PATCH 05/11] lpfc: Correct soft lockup when running mds diagnostics

2018-09-10 Thread James Smart
When running an mds diagnostic that passes frames with the
switch, soft lockups are detected. The driver is in a CQE
processing loop and has sufficient amount of traffic that
it never exits the ring processing routine, thus the "lockup".

Cap the number of elements in the work processing routine to
64 elements. This ensures that the cpu will be given up and
the handler reschedule to process additional items.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_sli.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 9830bdb6e072..a95c823cd1a4 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -3797,6 +3797,7 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
struct hbq_dmabuf *dmabuf;
struct lpfc_cq_event *cq_event;
unsigned long iflag;
+   int count = 0;
 
spin_lock_irqsave(>hbalock, iflag);
phba->hba_flag &= ~HBA_SP_QUEUE_EVT;
@@ -3818,16 +3819,22 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba 
*phba,
if (irspiocbq)
lpfc_sli_sp_handle_rspiocb(phba, pring,
   irspiocbq);
+   count++;
break;
case CQE_CODE_RECEIVE:
case CQE_CODE_RECEIVE_V1:
dmabuf = container_of(cq_event, struct hbq_dmabuf,
  cq_event);
lpfc_sli4_handle_received_buffer(phba, dmabuf);
+   count++;
break;
default:
break;
}
+
+   /* Limit the number of events to 64 to avoid soft lockups */
+   if (count == 64)
+   break;
}
 }
 
-- 
2.13.1



[PATCH 02/11] lpfc: raise sg count for nvme to use available sg resources

2018-09-10 Thread James Smart
The driver allocates a sg list per io struture based on a fixed
maximum size. When it registers with the protocol transports and
indicates the max sg list size it supports, the driver manipulates
the fixed value to report a lesser amount so that it has reserved
space for sg elements that are used for DIF.

The driver initialization path sets the cfg_sg_seg_cnt field to
the manipulated value for scsi. NVME initialization ran afterward
and capped it's maximum by the manipulated value for SCSI. This
erroneously made NVME report the SCSI-reduce-for-DIF value that
reduced the max io size for nvme and wasted sg elements.

Rework the driver so that cfg_sg_seg_cnt becomes the overall
maximum size and allow the max size to be tunable.  A separate
(new) scsi sg count is then setup with the scsi-modified reduced
value. NVME then initializes based off the overall maximum.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h   |  3 +-
 drivers/scsi/lpfc/lpfc_attr.c  | 69 +++---
 drivers/scsi/lpfc/lpfc_init.c  | 42 ++---
 drivers/scsi/lpfc/lpfc_nvme.c  | 13 ++--
 drivers/scsi/lpfc/lpfc_nvmet.c | 13 ++--
 5 files changed, 103 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 43732e8d1347..322b24f826a4 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -52,7 +52,7 @@ struct lpfc_sli2_slim;
downloads using bsg */
 
 #define LPFC_MIN_SG_SLI4_BUF_SZ0x800   /* based on 
LPFC_DEFAULT_SG_SEG_CNT */
-#define LPFC_MAX_SG_SLI4_SEG_CNT_DIF 128 /* sg element count per scsi cmnd */
+#define LPFC_MAX_BG_SLI4_SEG_CNT_DIF 128 /* sg element count for BlockGuard */
 #define LPFC_MAX_SG_SEG_CNT_DIF 512/* sg element count per scsi cmnd  */
 #define LPFC_MAX_SG_SEG_CNT4096/* sg element count per scsi cmnd */
 #define LPFC_MIN_SG_SEG_CNT32  /* sg element count per scsi cmnd */
@@ -790,6 +790,7 @@ struct lpfc_hba {
uint32_t cfg_total_seg_cnt;
uint32_t cfg_sg_seg_cnt;
uint32_t cfg_nvme_seg_cnt;
+   uint32_t cfg_scsi_seg_cnt;
uint32_t cfg_sg_dma_buf_size;
uint64_t cfg_soft_wwnn;
uint64_t cfg_soft_wwpn;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 057a60abe664..7d81f44630ee 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5353,15 +5353,74 @@ LPFC_ATTR(delay_discovery, 0, 0, 1,
 
 /*
  * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
- * This value can be set to values between 64 and 4096. The default value is
- * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer
- * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE).
+ * This value can be set to values between 64 and 4096. The default value
+ * is 64, but may be increased to allow for larger Max I/O sizes. The scsi
+ * and nvme layers will allow I/O sizes up to (MAX_SEG_COUNT * SEG_SIZE).
  * Because of the additional overhead involved in setting up T10-DIF,
  * this parameter will be limited to 128 if BlockGuard is enabled under SLI4
  * and will be limited to 512 if BlockGuard is enabled under SLI3.
  */
-LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_MIN_SG_SEG_CNT,
-   LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count");
+static uint lpfc_sg_seg_cnt = LPFC_DEFAULT_SG_SEG_CNT;
+module_param(lpfc_sg_seg_cnt, uint, 0444);
+MODULE_PARM_DESC(lpfc_sg_seg_cnt, "Max Scatter Gather Segment Count");
+
+/**
+ * lpfc_sg_seg_cnt_show - Display the scatter/gather list sizes
+ *configured for the adapter
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains a string with the list sizes
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_sg_seg_cnt_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct Scsi_Host  *shost = class_to_shost(dev);
+   struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+   struct lpfc_hba   *phba = vport->phba;
+   int len;
+
+   len = snprintf(buf, PAGE_SIZE, "SGL sz: %d  total SGEs: %d\n",
+  phba->cfg_sg_dma_buf_size, phba->cfg_total_seg_cnt);
+
+   len += snprintf(buf + len, PAGE_SIZE, "Cfg: %d  SCSI: %d  NVME: %d\n",
+   phba->cfg_sg_seg_cnt, phba->cfg_scsi_seg_cnt,
+   phba->cfg_nvme_seg_cnt);
+   return len;
+}
+
+static DEVICE_ATTR_RO(lpfc_sg_seg_cnt);
+
+/**
+ * lpfc_sg_seg_cnt_init - Set the hba sg_seg_cnt initial value
+ * @phba: lpfc_hba pointer.
+ * @val: contains the initial value
+ *
+ * Description:
+ * Validates the initial value is within range and assigns it to the
+ * adapter. If not in range, an error message is posted and the
+ * default value is assign

[PATCH 03/11] lpfc: Raise nvme defaults to support a larger io and more connectivity

2018-09-10 Thread James Smart
When nvme is enabled, change the default for two parameters:
 sg_seg_cnt - raise the per-io sg list size so that 1MB ios are
 supported (based on a 4k buffer per element).
 iocb_cnt - raise the number of buffers used for things like
 NVME LS request/responses to allow more concurrent requests
 to for larger nvme configs.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 7d81f44630ee..9d2397b795f4 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -6641,6 +6641,16 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_sli_mode_init(phba, lpfc_sli_mode);
phba->cfg_enable_dss = 1;
lpfc_enable_mds_diags_init(phba, lpfc_enable_mds_diags);
+
+   /* If the NVME FC4 type is enabled, scale the sg_seg_cnt to
+* accommodate 512K and 1M IOs in a single nvme buf and supply
+* enough NVME LS iocb buffers for larger connectivity counts.
+*/
+   if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
+   phba->cfg_sg_seg_cnt = LPFC_MAX_NVME_SEG_CNT;
+   phba->cfg_iocb_cnt = 5;
+   }
+
return;
 }
 
-- 
2.13.1



[PATCH 00/11] lpfc updates for 12.0.0.7

2018-09-10 Thread James Smart
This patch contains lpfc bug fixes, a couple of performance
mods, and a new diagnostic ability

The patches were cut against Martin's 4.19/scsi-queue tree

James Smart (11):
  lpfc: Fix GFT_ID and PRLI logic for RSCN
  lpfc: raise sg count for nvme to use available sg resources
  lpfc: Raise nvme defaults to support a larger io and more connectivity
  lpfc: Correct race with abort on completion path
  lpfc: Correct soft lockup when running mds diagnostics.
  lpfc: Correct irq handling via locks when taking adapter offline
  lpfc: Correct invalid EQ doorbell write on if_type=6
  lpfc: Fix errors in log messages.
  lpfc: reduce locking when updating statistics
  lpfc: add support to retrieve firmware logs
  lpfc: update driver version to 12.0.0.7

 drivers/scsi/lpfc/lpfc.h   |  29 +++-
 drivers/scsi/lpfc/lpfc_attr.c  | 111 +++-
 drivers/scsi/lpfc/lpfc_bsg.c   | 341 -
 drivers/scsi/lpfc/lpfc_bsg.h   |  36 
 drivers/scsi/lpfc/lpfc_crtn.h  |   7 +
 drivers/scsi/lpfc/lpfc_ct.c|  11 +-
 drivers/scsi/lpfc/lpfc_els.c   |   3 +
 drivers/scsi/lpfc/lpfc_hbadisc.c   |   8 +-
 drivers/scsi/lpfc/lpfc_hw4.h   |  45 +
 drivers/scsi/lpfc/lpfc_init.c  | 101 ---
 drivers/scsi/lpfc/lpfc_nportdisc.c |   3 +
 drivers/scsi/lpfc/lpfc_nvme.c  |  15 +-
 drivers/scsi/lpfc/lpfc_nvmet.c |  20 +--
 drivers/scsi/lpfc/lpfc_scsi.c  |  32 ++--
 drivers/scsi/lpfc/lpfc_sli.c   | 303 +++-
 drivers/scsi/lpfc/lpfc_sli4.h  |   1 +
 drivers/scsi/lpfc/lpfc_version.h   |   2 +-
 drivers/scsi/lpfc/lpfc_vport.c |  14 +-
 18 files changed, 993 insertions(+), 89 deletions(-)

-- 
2.13.1



[PATCH 01/11] lpfc: Fix GFT_ID and PRLI logic for RSCN

2018-09-10 Thread James Smart
Driver only sends NVME PRLI to a device that also supports FCP.
This resuls in remote ports that don't have fc_remote_ports
created for them. The driver is clearing the nlp_fc4_type for a
ndlp at the wrong time.

Fix by moving the nlp_fc4_type clearing to the discovery engine in the
DEVICE_RECOVERY state. Also ensure that rport registration is done for
all nlp_fc4_types.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_ct.c| 5 -
 drivers/scsi/lpfc/lpfc_hbadisc.c   | 2 +-
 drivers/scsi/lpfc/lpfc_nportdisc.c | 3 +++
 3 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 1cbdc892ff95..0eae8051e920 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -471,11 +471,6 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t 
Did, uint8_t fc4_type)
"Parse GID_FTrsp: did:x%x flg:x%x x%x",
Did, ndlp->nlp_flag, vport->fc_flag);
 
-   /* Don't assume the rport is always the previous
-* FC4 type.
-*/
-   ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
-
/* By default, the driver expects to support FCP FC4 */
if (fc4_type == FC_TYPE_FCP)
ndlp->nlp_fc4_type |= NLP_FC4_FCP;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index eb71877f12f8..235abd50e530 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -4193,7 +4193,7 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
 
if (new_state ==  NLP_STE_MAPPED_NODE ||
new_state == NLP_STE_UNMAPPED_NODE) {
-   if (ndlp->nlp_fc4_type & NLP_FC4_FCP ||
+   if (ndlp->nlp_fc4_type ||
ndlp->nlp_DID == Fabric_DID ||
ndlp->nlp_DID == NameServer_DID ||
ndlp->nlp_DID == FDMI_DID) {
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c 
b/drivers/scsi/lpfc/lpfc_nportdisc.c
index bd9bce9d9974..269808e8480f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -2318,6 +2318,7 @@ lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+   ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
spin_unlock_irq(shost->host_lock);
lpfc_disc_set_adisc(vport, ndlp);
 
@@ -2395,6 +2396,7 @@ lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+   ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
spin_unlock_irq(shost->host_lock);
lpfc_disc_set_adisc(vport, ndlp);
return ndlp->nlp_state;
@@ -2652,6 +2654,7 @@ lpfc_device_recov_npr_node(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp,
lpfc_cancel_retry_delay_tmo(vport, ndlp);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+   ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
spin_unlock_irq(shost->host_lock);
return ndlp->nlp_state;
 }
-- 
2.13.1



[PATCH] lpfc: Correct MDS diag and nvmet configuration

2018-08-16 Thread James Smart
A recent change added some MDS processing in the lpfc_drain_txq
routine that relies on the fcp_wq being allocated. For nvmet operation
the fcp_wq is not allocated because it can only be an nvme-target.
When the original MDS support was added LS_MDS_LOOPBACK was
defined wrong, (0x16) it should have been 0x10 (decimal value used for
hex setting). This incorrect value allowed MDS_LOOPBACK to be set
simultaneously with LS_NPIV_FAB_SUPPORTED, causing the driver to
crash when it accesses the non-existent fcp_wq.

Correct the bad value setting for LS_MDS_LOOPBACK.

Fixes:  ae9e28f36a6c  ("lpfc: Add MDS Diagnostic support.")
Cc:  # 4.12
Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index e0d0da5f43d6..43732e8d1347 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -672,7 +672,7 @@ struct lpfc_hba {
 #define LS_NPIV_FAB_SUPPORTED 0x2  /* Fabric supports NPIV */
 #define LS_IGNORE_ERATT   0x4  /* intr handler should ignore ERATT */
 #define LS_MDS_LINK_DOWN  0x8  /* MDS Diagnostics Link Down */
-#define LS_MDS_LOOPBACK  0x16  /* MDS Diagnostics Link Up (Loopback) */
+#define LS_MDS_LOOPBACK  0x10  /* MDS Diagnostics Link Up (Loopback) */
 
uint32_t hba_flag;  /* hba generic flags */
 #define HBA_ERATT_HANDLED  0x1 /* This flag is set when eratt handled */
-- 
2.13.1



[PATCH] lpfc: Default fdmi_on to on

2018-08-14 Thread James Smart
Change default behavior for fdmi registration to on.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 5a25553415f8..057a60abe664 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5122,16 +5122,16 @@ LPFC_ATTR_R(enable_SmartSAN, 0, 0, 1, "Enable SmartSAN 
functionality");
 
 /*
 # lpfc_fdmi_on: Controls FDMI support.
-#   0   No FDMI support (default)
-#   1   Traditional FDMI support
+#   0   No FDMI support
+#   1   Traditional FDMI support (default)
 # Traditional FDMI support means the driver will assume FDMI-2 support;
 # however, if that fails, it will fallback to FDMI-1.
 # If lpfc_enable_SmartSAN is set to 1, the driver ignores lpfc_fdmi_on.
 # If lpfc_enable_SmartSAN is set 0, the driver uses the current value of
 # lpfc_fdmi_on.
-# Value range [0,1]. Default value is 0.
+# Value range [0,1]. Default value is 1.
 */
-LPFC_ATTR_R(fdmi_on, 0, 0, 1, "Enable FDMI support");
+LPFC_ATTR_R(fdmi_on, 1, 0, 1, "Enable FDMI support");
 
 /*
 # Specifies the maximum number of ELS cmds we can have outstanding (for
-- 
2.13.1



[PATCH 3/8] lpfc: Fix list corruption on the completion queue.

2018-07-31 Thread James Smart
Enabling list_debug showed the drivers txcmplq was suffering list
corruption. The systems will eventually crash because the
iocb free list gets crossed linked with the prings txcmplq.
Most systems will run for a while after the corruption, but will
eventually crash when a scsi eh reset occurs and the txcmplq is
attempted to be flushed. The flush gets stuck in an endless loop.

The problem is the abort handler does not hold the sli4 ring lock while
validating the IO so the IO could complete while the driver is still
preping the abort.  The erroneously generated, abort when it completes,
has pointers to the original io that has already completed, and the
io manipulation (for the second time) corrupts the list.

Correct by taking the ring lock early in the abort handler so the
erroneous abort won't be sent if the io has/is completing.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c | 44 +++
 1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 25ef2b6ccc34..51ce244cf10a 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4727,7 +4727,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
struct lpfc_scsi_buf *lpfc_cmd;
IOCB_t *cmd, *icmd;
int ret = SUCCESS, status = 0;
-   struct lpfc_sli_ring *pring_s4;
+   struct lpfc_sli_ring *pring_s4 = NULL;
int ret_val;
unsigned long flags;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
@@ -4757,8 +4757,25 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
}
 
iocb = _cmd->cur_iocbq;
+   if (phba->sli_rev == LPFC_SLI_REV4) {
+   if (!(phba->cfg_fof) ||
+   (!(iocb->iocb_flag & LPFC_IO_FOF))) {
+   pring_s4 =
+   phba->sli4_hba.fcp_wq[iocb->hba_wqidx]->pring;
+   } else {
+   iocb->hba_wqidx = 0;
+   pring_s4 = phba->sli4_hba.oas_wq->pring;
+   }
+   if (!pring_s4) {
+   ret = FAILED;
+   goto out_unlock;
+   }
+   spin_lock(_s4->ring_lock);
+   }
/* the command is in process of being cancelled */
if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
+   if (phba->sli_rev == LPFC_SLI_REV4)
+   spin_unlock(_s4->ring_lock);
spin_unlock_irqrestore(>hbalock, flags);
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"3169 SCSI Layer abort requested I/O has been "
@@ -4772,6 +4789,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
 * see the completion before the eh fired. Just return SUCCESS.
 */
if (lpfc_cmd->pCmd != cmnd) {
+   if (phba->sli_rev == LPFC_SLI_REV4)
+   spin_unlock(_s4->ring_lock);
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"3170 SCSI Layer abort requested I/O has been "
"completed by LLD.\n");
@@ -4784,6 +4803,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
 "3389 SCSI Layer I/O Abort Request is pending\n");
+   if (phba->sli_rev == LPFC_SLI_REV4)
+   spin_unlock(_s4->ring_lock);
spin_unlock_irqrestore(>hbalock, flags);
goto wait_for_cmpl;
}
@@ -4791,6 +4812,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
abtsiocb = __lpfc_sli_get_iocbq(phba);
if (abtsiocb == NULL) {
ret = FAILED;
+   if (phba->sli_rev == LPFC_SLI_REV4)
+   spin_unlock(_s4->ring_lock);
goto out_unlock;
}
 
@@ -4828,14 +4851,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
 
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
abtsiocb->vport = vport;
+   lpfc_cmd->waitq = 
if (phba->sli_rev == LPFC_SLI_REV4) {
-   pring_s4 = lpfc_sli4_calc_ring(phba, abtsiocb);
-   if (pring_s4 == NULL) {
-   ret = FAILED;
-   goto out_unlock;
-   }
/* Note: both hbalock and ring_lock must be set here */
-   spin_lock(_s4->ring_lock);
ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno,
abtsiocb, 0);
spin_unlock(_s4->ring_lock);
@@ -4848,6 +4866,17 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
 
 
if (ret_val == IOCB_ERROR) {
+   if (phba->sli_rev == LPFC_SLI_RE

[PATCH 7/8] lpfc: Remove lpfc_enable_pbde as module parameter

2018-07-31 Thread James Smart
Enablement of the PBDE optimization brought out some
incompatible behaviors under error scenarios.

Best to disable and remove the PBDE optimization.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 514513f837a8..5a25553415f8 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5387,14 +5387,6 @@ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC 
Recovery");
  */
 LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
 
-/*
- * lpfc_enable_pbde: Enable PBDE on PRISM - G7
- *   0  = PBDE on G7 disabled
- *   1  = PBDE on G7 enabled (default)
- * Value range is [0,1]. Default value is 1
- */
-LPFC_ATTR_R(enable_pbde, 1, 0, 1, "Enable PBDE support on PRISM");
-
 struct device_attribute *lpfc_hba_attrs[] = {
_attr_nvme_info,
_attr_bg_info,
@@ -5506,7 +5498,6 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_lpfc_enable_mds_diags,
_attr_lpfc_enable_bbcr,
_attr_lpfc_enable_dpp,
-   _attr_lpfc_enable_pbde,
NULL,
 };
 
@@ -6541,7 +6532,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
-   lpfc_enable_pbde_init(phba, lpfc_enable_pbde);
 
if (phba->sli_rev != LPFC_SLI_REV4) {
/* NVME only supported on SLI4 */
@@ -6558,6 +6548,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
phba->cfg_auto_imax = 0;
phba->initial_imax = phba->cfg_fcp_imax;
 
+   phba->cfg_enable_pbde = 0;
+
/* A value of 0 means use the number of CPUs found in the system */
if (phba->cfg_fcp_io_channel == 0)
phba->cfg_fcp_io_channel = phba->sli4_hba.num_present_cpu;
-- 
2.13.1



[PATCH 8/8] lpfc: update driver version to 12.0.0.6

2018-07-31 Thread James Smart
Update the driver version to 12.0.0.6

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index a669af45fce7..501249509af4 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.5"
+#define LPFC_DRIVER_VERSION "12.0.0.6"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH 2/8] lpfc: Fix sysfs Speed value on CNA ports

2018-07-31 Thread James Smart
CNA ports were showing speed as "unknown" even if the link
is up.

Add speed decoding for FCOE-based adapters

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 23a5a298d60e..514513f837a8 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5927,6 +5927,24 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
+   } else if (lpfc_is_link_up(phba) && (phba->hba_flag & HBA_FCOE_MODE)) {
+   switch (phba->fc_linkspeed) {
+   case LPFC_ASYNC_LINK_SPEED_10GBPS:
+   fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+   break;
+   case LPFC_ASYNC_LINK_SPEED_25GBPS:
+   fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
+   break;
+   case LPFC_ASYNC_LINK_SPEED_40GBPS:
+   fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
+   break;
+   case LPFC_ASYNC_LINK_SPEED_100GBPS:
+   fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
+   break;
+   default:
+   fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+   break;
+   }
} else
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 
-- 
2.13.1



[PATCH 6/8] lpfc: Correct LCB ACCept payload

2018-07-31 Thread James Smart
After memory allocation for the LCB response frame, the memory
wasn't zero initialized, and not all fields are set. Thus garbage
shows up in the payload.

Fix by zeroing the memory at allocation.
Also properly set the Capability field based on duration support.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index df655f1284d0..4dda969e947c 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5662,6 +5662,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
lcb_res = (struct fc_lcb_res_frame *)
(((struct lpfc_dmabuf *)elsiocb->context2)->virt);
 
+   memset(lcb_res, 0, sizeof(struct fc_lcb_res_frame));
icmd = >iocb;
icmd->ulpContext = lcb_context->rx_id;
icmd->unsli3.rcvsli3.ox_id = lcb_context->ox_id;
@@ -5670,6 +5671,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
*((uint32_t *)(pcmd)) = ELS_CMD_ACC;
lcb_res->lcb_sub_command = lcb_context->sub_command;
lcb_res->lcb_type = lcb_context->type;
+   lcb_res->capability = lcb_context->capability;
lcb_res->lcb_frequency = lcb_context->frequency;
lcb_res->lcb_duration = lcb_context->duration;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-- 
2.13.1



[PATCH 0/8] lpfc updates for 12.0.0.6

2018-07-31 Thread James Smart
This patch contains lpfc bug fixes 

The patches were cut against the Martin's 4.19/scsi-queue tree

James Smart (8):
  lpfc: Fix ELS abort on SLI-3 adapters
  lpfc: Fix sysfs Speed value on CNA ports
  lpfc: Fix list corruption on the completion queue.
  lpfc: Fix driver crash when re-registering NVME rports.
  lpfc: Limit tracking of tgt queue depth in fast path
  lpfc: Correct LCB ACCept payload
  lpfc: Remove lpfc_enable_pbde as module parameter
  lpfc: update driver version to 12.0.0.6

 drivers/scsi/lpfc/lpfc_attr.c  |  30 ++
 drivers/scsi/lpfc/lpfc_disc.h  |   3 +
 drivers/scsi/lpfc/lpfc_els.c   |   2 +
 drivers/scsi/lpfc/lpfc_nportdisc.c |   9 +--
 drivers/scsi/lpfc/lpfc_nvme.c  |  63 
 drivers/scsi/lpfc/lpfc_nvme.h  |   1 +
 drivers/scsi/lpfc/lpfc_scsi.c  | 118 +
 drivers/scsi/lpfc/lpfc_scsi.h  |   2 +
 drivers/scsi/lpfc/lpfc_sli.c   |  16 -
 drivers/scsi/lpfc/lpfc_version.h   |   2 +-
 10 files changed, 164 insertions(+), 82 deletions(-)

-- 
2.13.1



[PATCH 1/8] lpfc: Fix ELS abort on SLI-3 adapters

2018-07-31 Thread James Smart
For ABORT_XRI_CN command, firmware identifies XRI to abort by
IOTAG and RPI combination. For ELS aborts, driver specifies
IOTAG correctly but RPI is not specified.

Fix by setting RPI in WQE.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nportdisc.c |  3 +++
 drivers/scsi/lpfc/lpfc_sli.c   | 16 ++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c 
b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 1f0a7d7dbc54..843e765db86d 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1062,6 +1062,9 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp,
 {
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
 
+   /* Retrieve RPI from LOGO IOCB. RPI is used for CMD_ABORT_XRI_CN */
+   if (vport->phba->sli_rev == LPFC_SLI_REV3)
+   ndlp->nlp_rpi = cmdiocb->iocb.ulpIoTag;
/* software abort outstanding PLOGI */
lpfc_els_abort(vport->phba, ndlp);
 
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 72500dcb13a9..9830bdb6e072 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -10703,6 +10703,12 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
 
spin_lock_irq(>hbalock);
if (phba->sli_rev < LPFC_SLI_REV4) {
+   if (irsp->ulpCommand == CMD_ABORT_XRI_CX &&
+   irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+   irsp->un.ulpWord[4] == IOERR_ABORT_REQUESTED) {
+   spin_unlock_irq(>hbalock);
+   goto release_iocb;
+   }
if (abort_iotag != 0 &&
abort_iotag <= phba->sli.last_iotag)
abort_iocb =
@@ -10724,6 +10730,7 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdiocb,
 
spin_unlock_irq(>hbalock);
}
+release_iocb:
lpfc_sli_release_iocbq(phba, cmdiocb);
return;
 }
@@ -10780,6 +10787,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, 
struct lpfc_sli_ring *pring,
IOCB_t *iabt = NULL;
int retval;
unsigned long iflags;
+   struct lpfc_nodelist *ndlp;
 
lockdep_assert_held(>hbalock);
 
@@ -10810,9 +10818,13 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, 
struct lpfc_sli_ring *pring,
if (phba->sli_rev == LPFC_SLI_REV4) {
iabt->un.acxri.abortIoTag = cmdiocb->sli4_xritag;
iabt->un.acxri.abortContextTag = cmdiocb->iotag;
-   }
-   else
+   } else {
iabt->un.acxri.abortIoTag = icmd->ulpIoTag;
+   if (pring->ringno == LPFC_ELS_RING) {
+   ndlp = (struct lpfc_nodelist *)(cmdiocb->context1);
+   iabt->un.acxri.abortContextTag = ndlp->nlp_rpi;
+   }
+   }
iabt->ulpLe = 1;
iabt->ulpClass = icmd->ulpClass;
 
-- 
2.13.1



[PATCH 5/8] lpfc: Limit tracking of tgt queue depth in fast path

2018-07-31 Thread James Smart
Performance is effected when target queue depth is tracked.
An atomic counter is incremented on the submission path which
competes with it being decremented on the completion path.
In addition multiple CPUs can simultaniously be manipulating
this counter for the same ndlp.

Reduce the overhead by only performing the target increment/decrement
when the target queue depth is less than the overall adapter depth,
thus is actually meaningful.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_disc.h  |  3 ++
 drivers/scsi/lpfc/lpfc_nportdisc.c |  6 
 drivers/scsi/lpfc/lpfc_nvme.c  | 41 -
 drivers/scsi/lpfc/lpfc_nvme.h  |  1 +
 drivers/scsi/lpfc/lpfc_scsi.c  | 74 ++
 drivers/scsi/lpfc/lpfc_scsi.h  |  2 ++
 6 files changed, 74 insertions(+), 53 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 376f02819f20..28e2b60fc5c0 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -150,6 +150,9 @@ struct lpfc_node_rrq {
unsigned long rrq_stop_time;
 };
 
+#define lpfc_ndlp_check_qdepth(phba, ndlp) \
+   (ndlp->cmd_qdepth < phba->sli4_hba.max_cfg_param.max_xri)
+
 /* Defines for nlp_flag (uint32) */
 #define NLP_IGNR_REG_CMPL  0x0001 /* Rcvd rscn before we cmpl reg login */
 #define NLP_REG_LOGIN_SEND 0x0002   /* sent reglogin to adapter */
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c 
b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 843e765db86d..bd9bce9d9974 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1985,12 +1985,6 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp,
if (bf_get_be32(prli_disc, nvpr))
ndlp->nlp_type |= NLP_NVME_DISCOVERY;
 
-   /* This node is an NVME target.  Adjust the command
-* queue depth on this node to not exceed the available
-* xris.
-*/
-   ndlp->cmd_qdepth = phba->sli4_hba.nvme_xri_max;
-
/*
 * If prli_fba is set, the Target supports FirstBurst.
 * If prli_fb_sz is 0, the FirstBurst size is unlimited,
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 32053424d546..028462e5994d 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1135,9 +1135,6 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *pwqeIn,
else
lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
 
-   if (ndlp && NLP_CHK_NODE_ACT(ndlp))
-   atomic_dec(>cmd_pending);
-
/* Update stats and complete the IO.  There is
 * no need for dma unprep because the nvme_transport
 * owns the dma address.
@@ -1546,17 +1543,19 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
/* The node is shared with FCP IO, make sure the IO pending count does
 * not exceed the programmed depth.
 */
-   if ((atomic_read(>cmd_pending) >= ndlp->cmd_qdepth) &&
-   !expedite) {
-   lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
-"6174 Fail IO, ndlp qdepth exceeded: "
-"idx %d DID %x pend %d qdepth %d\n",
-lpfc_queue_info->index, ndlp->nlp_DID,
-atomic_read(>cmd_pending),
-ndlp->cmd_qdepth);
-   atomic_inc(>xmt_fcp_qdepth);
-   ret = -EBUSY;
-   goto out_fail;
+   if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
+   if ((atomic_read(>cmd_pending) >= ndlp->cmd_qdepth) &&
+   !expedite) {
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+"6174 Fail IO, ndlp qdepth exceeded: "
+"idx %d DID %x pend %d qdepth %d\n",
+lpfc_queue_info->index, ndlp->nlp_DID,
+atomic_read(>cmd_pending),
+ndlp->cmd_qdepth);
+   atomic_inc(>xmt_fcp_qdepth);
+   ret = -EBUSY;
+   goto out_fail;
+   }
}
 
lpfc_ncmd = lpfc_get_nvme_buf(phba, ndlp, expedite);
@@ -1614,8 +1613,6 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
goto out_free_nvme_buf;
}
 
-   atomic_inc(>cmd_pending);
-
lpfc_nvmeio_data(phba, "NVME FCP XMIT: xri x%x idx %d to %06

[PATCH 4/8] lpfc: Fix driver crash when re-registering NVME rports.

2018-07-31 Thread James Smart
During remote port loss fault testing, the driver crashed
with the following trace:

general protection fault:  [#1] SMP
RIP: ... lpfc_nvme_register_port+0x250/0x480 [lpfc]
Call Trace:
 lpfc_nlp_state_cleanup+0x1b3/0x7a0 [lpfc]
 lpfc_nlp_set_state+0xa6/0x1d0 [lpfc]
 lpfc_cmpl_prli_prli_issue+0x213/0x440
 lpfc_disc_state_machine+0x7e/0x1e0 [lpfc]
 lpfc_cmpl_els_prli+0x18a/0x200 [lpfc]
 lpfc_sli_sp_handle_rspiocb+0x3b5/0x6f0 [lpfc]
 lpfc_sli_handle_slow_ring_event_s4+0x161/0x240 [lpfc]
 lpfc_work_done+0x948/0x14c0 [lpfc]
 lpfc_do_work+0x16f/0x180 [lpfc]
 kthread+0xc9/0xe0
 ret_from_fork+0x55/0x80

After registering a new remoteport, the driver is pulling an
ndlp pointer from the lpfc rport associated with the private
area of a newly registered remoteport. The private area is
uninitialized, so it's garbage.

Correct by pulling the the lpfc rport pointer from the entering
ndlp point, then ndlp value from at rport. Note the entering
ndlp may be replacing by the rport->ndlp due to an address
change swap.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nvme.c | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 4cc6783b6a9f..32053424d546 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2687,7 +2687,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp)
struct lpfc_nvme_rport *oldrport;
struct nvme_fc_remote_port *remote_port;
struct nvme_fc_port_info rpinfo;
-   struct lpfc_nodelist *prev_ndlp;
+   struct lpfc_nodelist *prev_ndlp = NULL;
 
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC,
 "6006 Register NVME PORT. DID x%06x nlptype x%x\n",
@@ -2736,23 +2736,29 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
spin_unlock_irq(>phba->hbalock);
rport = remote_port->private;
if (oldrport) {
+   /* New remoteport record does not guarantee valid
+* host private memory area.
+*/
+   prev_ndlp = oldrport->ndlp;
if (oldrport == remote_port->private) {
-   /* Same remoteport.  Just reuse. */
+   /* Same remoteport - ndlp should match.
+* Just reuse.
+*/
lpfc_printf_vlog(ndlp->vport, KERN_INFO,
 LOG_NVME_DISC,
 "6014 Rebinding lport to "
 "remoteport %p wwpn 0x%llx, "
-"Data: x%x x%x %p x%x x%06x\n",
+"Data: x%x x%x %p %p x%x 
x%06x\n",
 remote_port,
 remote_port->port_name,
 remote_port->port_id,
 remote_port->port_role,
+prev_ndlp,
 ndlp,
 ndlp->nlp_type,
 ndlp->nlp_DID);
return 0;
}
-   prev_ndlp = rport->ndlp;
 
/* Sever the ndlp<->rport association
 * before dropping the ndlp ref from
@@ -2786,13 +2792,13 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
lpfc_printf_vlog(vport, KERN_INFO,
 LOG_NVME_DISC | LOG_NODE,
 "6022 Binding new rport to "
-"lport %p Remoteport %p  WWNN 0x%llx, "
+"lport %p Remoteport %p rport %p WWNN 0x%llx, "
 "Rport WWPN 0x%llx DID "
-"x%06x Role x%x, ndlp %p\n",
-lport, remote_port,
+"x%06x Role x%x, ndlp %p prev_ndlp %p\n",
+lport, remote_port, rport,
 rpinfo.node_name, rpinfo.port_name,
 rpinfo.port_id, rpinfo.port_role,
-ndlp);
+ndlp, prev_ndlp);
} else {
lpfc_printf_vlog(vport, KERN_ERR,
 LOG_NVME_DISC | LOG_NODE,
-- 
2.13.1



[PATCH 07/10] lpfc: Fix NVME Target crash in defer rcv logic

2018-06-26 Thread James Smart
Kernel occasionally crashed with the following
ops on NVME Target:
  BUG: unable to handle kernel NULL pointer dereference at 0058
  IP: [] lpfc_nvmet_defer_rcv+0x50/0x70 [lpfc]

Callback routine was called for deferred rcv when it should
be treated as a normal rcv.

Added code in callback routine to detect this condition and
log a message, then bail.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nvmet.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 3330973bd9c5..bc3c19f2338b 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -402,6 +402,7 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct 
lpfc_nvmet_ctxbuf *ctx_buf)
 
/* Process FCP command */
if (rc == 0) {
+   ctxp->rqb_buffer = NULL;
atomic_inc(>rcv_fcp_cmd_out);
nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
return;
@@ -1116,8 +1117,17 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port 
*tgtport,
lpfc_nvmeio_data(phba, "NVMET DEFERRCV: xri x%x sz %d CPU %02x\n",
 ctxp->oxid, ctxp->size, smp_processor_id());
 
+   if (!nvmebuf) {
+   lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
+   "6425 Defer rcv: no buffer xri x%x: "
+   "flg %x ste %x\n",
+   ctxp->oxid, ctxp->flag, ctxp->state);
+   return;
+   }
+
tgtp = phba->targetport->private;
-   atomic_inc(>rcv_fcp_cmd_defer);
+   if (tgtp)
+   atomic_inc(>rcv_fcp_cmd_defer);
 
/* Free the nvmebuf since a new buffer already replaced it */
nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
-- 
2.13.1



[PATCH 09/10] lpfc: update driver version to 12.0.0.5

2018-06-26 Thread James Smart
Update the driver version to 12.0.0.5

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 18c23afcf46b..30591e6364ec 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.4"
+#define LPFC_DRIVER_VERSION "12.0.0.5"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH 08/10] lpfc: devloss timeout race condition caused null pointer reference

2018-06-26 Thread James Smart
A race condition between the context of devloss timeout handler
and I/O completion caused devloss timeout handler de-referencing
pointer that had been released.

Added the check in lpfc_sli_validate_fcp_iocb() on
LPFC_IO_ON_TXCMPLQ to capture the race condition of I/O completion
and devloss timeout handler attemption for aborting the I/O. Also,
added check on lpfc_cmd->rdata pointer before de-referenceing
lpfc_cmd->rdata->pnode.

Also, added protection in lpfc_sli_abort_iocb() routine on driver
performed FCP I/O FLUSHING already under way before proceeding
to aborting I/Os.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c |  5 +
 drivers/scsi/lpfc/lpfc_sli.c  | 13 +
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c31c43f43553..5e4cad6a531a 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4538,6 +4538,11 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct 
scsi_cmnd *cmnd)
int err;
 
rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
+
+   /* sanity check on references */
+   if (unlikely(!rdata) || unlikely(!rport))
+   goto out_fail_command;
+
err = fc_remote_port_chkready(rport);
if (err) {
cmnd->result = err;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 3299913876ce..d4078fda11a5 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -11097,10 +11097,11 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, 
struct lpfc_vport *vport,
struct lpfc_scsi_buf *lpfc_cmd;
int rc = 1;
 
-   if (!(iocbq->iocb_flag &  LPFC_IO_FCP))
+   if (iocbq->vport != vport)
return rc;
 
-   if (iocbq->vport != vport)
+   if (!(iocbq->iocb_flag &  LPFC_IO_FCP) ||
+   !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ))
return rc;
 
lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
@@ -0,13 +1,13 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, 
struct lpfc_vport *vport,
 
switch (ctx_cmd) {
case LPFC_CTX_LUN:
-   if ((lpfc_cmd->rdata->pnode) &&
+   if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) &&
(lpfc_cmd->rdata->pnode->nlp_sid == tgt_id) &&
(scsilun_to_int(_cmd->fcp_cmnd->fcp_lun) == lun_id))
rc = 0;
break;
case LPFC_CTX_TGT:
-   if ((lpfc_cmd->rdata->pnode) &&
+   if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) &&
(lpfc_cmd->rdata->pnode->nlp_sid == tgt_id))
rc = 0;
break;
@@ -11231,6 +11232,10 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct 
lpfc_sli_ring *pring,
int errcnt = 0, ret_val = 0;
int i;
 
+   /* all I/Os are in process of being flushed */
+   if (phba->hba_flag & HBA_FCP_IOQ_FLUSH)
+   return errcnt;
+
for (i = 1; i <= phba->sli.last_iotag; i++) {
iocbq = phba->sli.iocbq_lookup[i];
 
-- 
2.13.1



[PATCH 10/10] lpfc: Revise copyright for new company language

2018-06-26 Thread James Smart
Change references from "Broadcom Limited" to "Broadcom Inc." in
the copyright message. Update copyright duration if not yet updated
for 2018.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/Makefile | 4 ++--
 drivers/scsi/lpfc/lpfc.h   | 2 +-
 drivers/scsi/lpfc/lpfc_attr.h  | 4 ++--
 drivers/scsi/lpfc/lpfc_bsg.c   | 2 +-
 drivers/scsi/lpfc/lpfc_bsg.h   | 4 ++--
 drivers/scsi/lpfc/lpfc_compat.h| 4 ++--
 drivers/scsi/lpfc/lpfc_crtn.h  | 2 +-
 drivers/scsi/lpfc/lpfc_ct.c| 2 +-
 drivers/scsi/lpfc/lpfc_debugfs.h   | 2 +-
 drivers/scsi/lpfc/lpfc_disc.h  | 4 ++--
 drivers/scsi/lpfc/lpfc_els.c   | 2 +-
 drivers/scsi/lpfc/lpfc_hbadisc.c   | 2 +-
 drivers/scsi/lpfc/lpfc_hw.h| 2 +-
 drivers/scsi/lpfc/lpfc_ids.h   | 2 +-
 drivers/scsi/lpfc/lpfc_logmsg.h| 4 ++--
 drivers/scsi/lpfc/lpfc_mbox.c  | 2 +-
 drivers/scsi/lpfc/lpfc_mem.c   | 2 +-
 drivers/scsi/lpfc/lpfc_nl.h| 4 ++--
 drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +-
 drivers/scsi/lpfc/lpfc_nvmet.c | 2 +-
 drivers/scsi/lpfc/lpfc_nvmet.h | 2 +-
 drivers/scsi/lpfc/lpfc_sli.h   | 4 ++--
 drivers/scsi/lpfc/lpfc_sli4.h  | 2 +-
 drivers/scsi/lpfc/lpfc_version.h   | 4 ++--
 drivers/scsi/lpfc/lpfc_vport.c | 4 ++--
 drivers/scsi/lpfc/lpfc_vport.h | 4 ++--
 26 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile
index cb6aa802c48e..092a971d066b 100644
--- a/drivers/scsi/lpfc/Makefile
+++ b/drivers/scsi/lpfc/Makefile
@@ -1,8 +1,8 @@
 #/***
 # * This file is part of the Emulex Linux Device Driver for *
 # * Fibre Channel Host Bus Adapters.*
-# * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
-# * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+# * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+# * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
 # * Copyright (C) 2004-2012 Emulex.  All rights reserved.   *
 # * EMULEX and SLI are trademarks of Emulex.*
 # * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index fc580a9b2bae..e0d0da5f43d6 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_attr.h b/drivers/scsi/lpfc/lpfc_attr.h
index 931db52692f5..9659a8fff971 100644
--- a/drivers/scsi/lpfc/lpfc_attr.h
+++ b/drivers/scsi/lpfc/lpfc_attr.h
@@ -1,8 +1,8 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index edb1a18a6414..90745feca808 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
  * Copyright (C) 2009-2015 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
index e7d95a4e8042..32347c87e3b4 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.h
+++ b/drivers/scsi/lpfc/lpfc_bsg.h
@@ -1,8 +1,8 @@
 /***
 

[PATCH 06/10] lpfc: Support duration field in Link Cable Beacon V1 command

2018-06-26 Thread James Smart
Current implementation missed setting the duration field.
Correct the code to set the field.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c  | 64 +++
 drivers/scsi/lpfc/lpfc_hw.h   | 18 +++-
 drivers/scsi/lpfc/lpfc_hw4.h  | 46 ---
 drivers/scsi/lpfc/lpfc_init.c |  1 +
 drivers/scsi/lpfc/lpfc_sli4.h |  3 ++
 5 files changed, 104 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 6d84a10fef07..4683154842f5 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5640,8 +5640,9 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
" mbx status x%x\n",
shdr_status, shdr_add_status, mb->mbxStatus);
 
-   if (mb->mbxStatus && !(shdr_status &&
-   shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)) {
+   if ((mb->mbxStatus != MBX_SUCCESS) || shdr_status ||
+   (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) ||
+   (shdr_add_status == ADD_STATUS_INVALID_REQUEST)) {
mempool_free(pmb, phba->mbox_mem_pool);
goto error;
}
@@ -5670,6 +5671,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
lcb_res->lcb_sub_command = lcb_context->sub_command;
lcb_res->lcb_type = lcb_context->type;
lcb_res->lcb_frequency = lcb_context->frequency;
+   lcb_res->lcb_duration = lcb_context->duration;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
phba->fc_stat.elsXmitACC++;
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
@@ -5712,6 +5714,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
 uint32_t beacon_state)
 {
struct lpfc_hba *phba = vport->phba;
+   union lpfc_sli4_cfg_shdr *cfg_shdr;
LPFC_MBOXQ_t *mbox = NULL;
uint32_t len;
int rc;
@@ -5720,6 +5723,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
if (!mbox)
return 1;
 
+   cfg_shdr = >u.mqe.un.sli4_config.header.cfg_shdr;
len = sizeof(struct lpfc_mbx_set_beacon_config) -
sizeof(struct lpfc_sli4_cfg_mhdr);
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
@@ -5732,8 +5736,40 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
   phba->sli4_hba.physical_port);
bf_set(lpfc_mbx_set_beacon_state, >u.mqe.un.beacon_config,
   beacon_state);
-   bf_set(lpfc_mbx_set_beacon_port_type, >u.mqe.un.beacon_config, 1);
-   bf_set(lpfc_mbx_set_beacon_duration, >u.mqe.un.beacon_config, 0);
+   mbox->u.mqe.un.beacon_config.word5 = 0; /* Reserved */
+
+   /*
+*  Check bv1s bit before issuing the mailbox
+*  if bv1s == 1, LCB V1 supported
+*  else, LCB V0 supported
+*/
+
+   if (phba->sli4_hba.pc_sli4_params.bv1s) {
+   /* COMMON_SET_BEACON_CONFIG_V1 */
+   cfg_shdr->request.word9 = BEACON_VERSION_V1;
+   lcb_context->capability |= LCB_CAPABILITY_DURATION;
+   bf_set(lpfc_mbx_set_beacon_port_type,
+  >u.mqe.un.beacon_config, 0);
+   bf_set(lpfc_mbx_set_beacon_duration_v1,
+  >u.mqe.un.beacon_config,
+  be16_to_cpu(lcb_context->duration));
+   } else {
+   /* COMMON_SET_BEACON_CONFIG_V0 */
+   if (be16_to_cpu(lcb_context->duration) != 0) {
+   mempool_free(mbox, phba->mbox_mem_pool);
+   return 1;
+   }
+   cfg_shdr->request.word9 = BEACON_VERSION_V0;
+   lcb_context->capability &=  ~(LCB_CAPABILITY_DURATION);
+   bf_set(lpfc_mbx_set_beacon_state,
+  >u.mqe.un.beacon_config, beacon_state);
+   bf_set(lpfc_mbx_set_beacon_port_type,
+  >u.mqe.un.beacon_config, 1);
+   bf_set(lpfc_mbx_set_beacon_duration,
+  >u.mqe.un.beacon_config,
+  be16_to_cpu(lcb_context->duration));
+   }
+
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
@@ -5784,24 +5820,16 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct 
lpfc_iocbq *cmdiocb,
beacon->lcb_frequency,
be16_to_cpu(beacon->lcb_duration));
 
-   if (phba->sli_rev < LPFC_SLI_REV4 ||
-   (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) !=
-   LPFC_SLI_INTF_IF_TYPE_2)) {
-   rjt_err = LSRJT_CMD_UNSUPPORTED;
-   goto rjt;
-   

[PATCH 05/10] lpfc: Make PBDE optimizations configurable

2018-06-26 Thread James Smart
the PBDE optimizations aren't supported in all firmware revs.

Make to optimizations configurable in case there's a side
effect on old firmware.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h   |  3 +--
 drivers/scsi/lpfc/lpfc_attr.c  | 10 ++
 drivers/scsi/lpfc/lpfc_init.c  | 22 +++---
 drivers/scsi/lpfc/lpfc_nvme.c  |  8 
 drivers/scsi/lpfc/lpfc_nvmet.c | 23 +--
 drivers/scsi/lpfc/lpfc_scsi.c  | 14 +++---
 drivers/scsi/lpfc/lpfc_sli.c   |  8 
 7 files changed, 50 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 20b249a649dd..fc580a9b2bae 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -840,8 +840,7 @@ struct lpfc_hba {
 #define LPFC_ENABLE_FCP  1
 #define LPFC_ENABLE_NVME 2
 #define LPFC_ENABLE_BOTH 3
-   uint32_t nvme_embed_pbde;
-   uint32_t fcp_embed_pbde;
+   uint32_t cfg_enable_pbde;
uint32_t io_channel_irqs;   /* number of irqs for io channels */
struct nvmet_fc_target_port *targetport;
lpfc_vpd_t vpd; /* vital product data */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3b839237ab50..ec537052bec4 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5387,6 +5387,14 @@ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC 
Recovery");
  */
 LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
 
+/*
+ * lpfc_enable_pbde: Enable PBDE on PRISM - G7
+ *   0  = PBDE on G7 disabled
+ *   1  = PBDE on G7 enabled (default)
+ * Value range is [0,1]. Default value is 1
+ */
+LPFC_ATTR_R(enable_pbde, 1, 0, 1, "Enable PBDE support on PRISM");
+
 struct device_attribute *lpfc_hba_attrs[] = {
_attr_nvme_info,
_attr_bg_info,
@@ -5498,6 +5506,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_lpfc_enable_mds_diags,
_attr_lpfc_enable_bbcr,
_attr_lpfc_enable_dpp,
+   _attr_lpfc_enable_pbde,
NULL,
 };
 
@@ -6520,6 +6529,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
+   lpfc_enable_pbde_init(phba, lpfc_enable_pbde);
 
if (phba->sli_rev != LPFC_SLI_REV4) {
/* NVME only supported on SLI4 */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 139a8baa6e4c..1bbf56efa07c 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10672,18 +10672,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
}
 
-   /* Only embed PBDE for if_type 6 */
-   if (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) ==
-   LPFC_SLI_INTF_IF_TYPE_6) {
-   phba->fcp_embed_pbde = 1;
-   phba->nvme_embed_pbde = 1;
-   }
-
-   /* PBDE support requires xib be set */
-   if (!bf_get(cfg_xib, mbx_sli4_parameters)) {
-   phba->fcp_embed_pbde = 0;
-   phba->nvme_embed_pbde = 0;
-   }
+   /* Only embed PBDE for if_type 6, PBDE support requires xib be set */
+   if ((bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) !=
+   LPFC_SLI_INTF_IF_TYPE_6) || (!bf_get(cfg_xib, mbx_sli4_parameters)))
+   phba->cfg_enable_pbde = 0;
 
/*
 * To support Suppress Response feature we must satisfy 3 conditions.
@@ -10717,10 +10709,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
phba->fcp_embed_io = 0;
 
lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME,
-   "6422 XIB %d: FCP %d %d NVME %d %d %d %d\n",
+   "6422 XIB %d PBDE %d: FCP %d NVME %d %d %d\n",
bf_get(cfg_xib, mbx_sli4_parameters),
-   phba->fcp_embed_pbde, phba->fcp_embed_io,
-   phba->nvme_support, phba->nvme_embed_pbde,
+   phba->cfg_enable_pbde,
+   phba->fcp_embed_io, phba->nvme_support,
phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
 
if ((bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) ==
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index ada5a2aaee82..4cc6783b6a9f 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1279,6 +1279,8 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
/* Word 9 */
bf_set(wqe_reqtag, >generic.wqe_com, pwqeq->iotag);
 
+   /* Words 13 14 15 are for PBDE support */
+
pwqeq->vport = vport;
return 0;
 }

[PATCH 00/10] lpfc updates for 12.0.0.5

2018-06-26 Thread James Smart
This patch contains lpfc bug fixes and some minor functional additions.

The patches were cut against the Martin's 4.18/scsi-queue tree

James Smart (10):
  lpfc: Add Buffer overflow check, when nvme_info larger than PAGE_SIZE
  lpfc: Fix driver not setting dpp bits correctly in doorbell word
  lpfc: Fix panic if driver unloaded when port is offline
  lpfc: Fix abort error path for NVMET
  lpfc: Make PBDE optimizations configurable
  lpfc: Support duration field in Link Cable Beacon V1 command
  lpfc: Fix NVME Target crash in defer rcv logic
  lpfc: devloss timeout race condition caused null pointer reference
  lpfc: update driver version to 12.0.0.5
  lpfc: Revise copyright for new company language

 drivers/scsi/lpfc/Makefile |   4 +-
 drivers/scsi/lpfc/lpfc.h   |   5 +-
 drivers/scsi/lpfc/lpfc_attr.c  | 442 ++---
 drivers/scsi/lpfc/lpfc_attr.h  |   4 +-
 drivers/scsi/lpfc/lpfc_bsg.c   |   2 +-
 drivers/scsi/lpfc/lpfc_bsg.h   |   4 +-
 drivers/scsi/lpfc/lpfc_compat.h|   4 +-
 drivers/scsi/lpfc/lpfc_crtn.h  |   2 +-
 drivers/scsi/lpfc/lpfc_ct.c|   2 +-
 drivers/scsi/lpfc/lpfc_debugfs.h   |   2 +-
 drivers/scsi/lpfc/lpfc_disc.h  |   4 +-
 drivers/scsi/lpfc/lpfc_els.c   |  66 --
 drivers/scsi/lpfc/lpfc_hbadisc.c   |   2 +-
 drivers/scsi/lpfc/lpfc_hw.h|  20 +-
 drivers/scsi/lpfc/lpfc_hw4.h   |  46 +++-
 drivers/scsi/lpfc/lpfc_ids.h   |   2 +-
 drivers/scsi/lpfc/lpfc_init.c  |  28 ++-
 drivers/scsi/lpfc/lpfc_logmsg.h|   4 +-
 drivers/scsi/lpfc/lpfc_mbox.c  |   2 +-
 drivers/scsi/lpfc/lpfc_mem.c   |   2 +-
 drivers/scsi/lpfc/lpfc_nl.h|   4 +-
 drivers/scsi/lpfc/lpfc_nportdisc.c |   2 +-
 drivers/scsi/lpfc/lpfc_nvme.c  |  13 +-
 drivers/scsi/lpfc/lpfc_nvmet.c |  52 +++--
 drivers/scsi/lpfc/lpfc_nvmet.h |   2 +-
 drivers/scsi/lpfc/lpfc_scsi.c  |  19 +-
 drivers/scsi/lpfc/lpfc_sli.c   |  30 ++-
 drivers/scsi/lpfc/lpfc_sli.h   |   4 +-
 drivers/scsi/lpfc/lpfc_sli4.h  |   5 +-
 drivers/scsi/lpfc/lpfc_version.h   |   6 +-
 drivers/scsi/lpfc/lpfc_vport.c |   4 +-
 drivers/scsi/lpfc/lpfc_vport.h |   4 +-
 32 files changed, 502 insertions(+), 290 deletions(-)

-- 
2.13.1



[PATCH 04/10] lpfc: Fix abort error path for NVMET

2018-06-26 Thread James Smart
rmmod of driver hangs

As driver instances were being unloaded, the NVME target port was
unloaded first. During the unload, the NVME initiator port sent a
heartbeat IO. Because of the target port state, that IO was scheduled
for an Abort; however, that abort subseqentially failed. The failure
was not cleaned up properly and lpfc_sli4_xri_exchange_busy_wait
silently hung forever.

Clean failed abort properly and make lpfc_sli4_xri_exchange_busy_wait
not hangs silently while waiting for aborts to complete.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_init.c  |  5 +
 drivers/scsi/lpfc/lpfc_nvmet.c | 15 +++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7ae343b14630..139a8baa6e4c 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10386,6 +10386,11 @@ lpfc_sli4_xri_exchange_busy_wait(struct lpfc_hba *phba)
while (!fcp_xri_cmpl || !els_xri_cmpl || !nvme_xri_cmpl ||
   !nvmet_xri_cmpl) {
if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) {
+   if (!nvmet_xri_cmpl)
+   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+   "6424 NVMET XRI exchange busy "
+   "wait time: %d seconds.\n",
+   wait_time/1000);
if (!nvme_xri_cmpl)
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6100 NVME XRI exchange busy "
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index 7271c9d885dd..102c970a00e6 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -1732,9 +1732,12 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
uint32_t *payload;
uint32_t size, oxid, sid, rc;
 
+   fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
+   oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+
if (!nvmebuf || !phba->targetport) {
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
-   "6154 LS Drop IO\n");
+   "6154 LS Drop IO x%x\n", oxid);
oxid = 0;
size = 0;
sid = 0;
@@ -1744,9 +1747,7 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
 
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
payload = (uint32_t *)(nvmebuf->dbuf.virt);
-   fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
size = bf_get(lpfc_rcqe_length,  >cq_event.cqe.rcqe_cmpl);
-   oxid = be16_to_cpu(fc_hdr->fh_ox_id);
sid = sli4_sid_from_fc_hdr(fc_hdr);
 
ctxp = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx), GFP_ATOMIC);
@@ -3105,11 +3106,17 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
}
 
 aerr:
-   ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+   spin_lock_irqsave(>ctxlock, flags);
+   if (ctxp->flag & LPFC_NVMET_CTX_RLS)
+   list_del(>list);
+   ctxp->flag &= ~(LPFC_NVMET_ABORT_OP | LPFC_NVMET_CTX_RLS);
+   spin_unlock_irqrestore(>ctxlock, flags);
+
atomic_inc(>xmt_abort_rsp_error);
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
"6135 Failed to Issue ABTS for oxid x%x. Status x%x\n",
ctxp->oxid, rc);
+   lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
return 1;
 }
 
-- 
2.13.1



[PATCH 02/10] lpfc: Fix driver not setting dpp bits correctly in doorbell word

2018-06-26 Thread James Smart
Driver is incorrectly formatting a register on new hardware, using
a format for an older chip. This can result in non-deterministic
behavior.

Ensure driver is not setting "workqueue index" in the WQ doorbell
when making a non-dpp doorbell write. The field must be zero when
non-dpp.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_sli.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 4b70d53acb72..74547f437813 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -145,6 +145,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 
*wqe)
uint32_t idx;
uint32_t i = 0;
uint8_t *tmp;
+   u32 if_type;
 
/* sanity check on queue memory */
if (unlikely(!q))
@@ -199,8 +200,14 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 
*wqe)
q->queue_id);
} else {
bf_set(lpfc_wq_db_list_fm_num_posted, , 1);
-   bf_set(lpfc_wq_db_list_fm_index, , host_index);
bf_set(lpfc_wq_db_list_fm_id, , q->queue_id);
+
+   /* Leave bits <23:16> clear for if_type 6 dpp */
+   if_type = bf_get(lpfc_sli_intf_if_type,
+>phba->sli4_hba.sli_intf);
+   if (if_type != LPFC_SLI_INTF_IF_TYPE_6)
+   bf_set(lpfc_wq_db_list_fm_index, ,
+  host_index);
}
} else if (q->db_format == LPFC_DB_RING_FORMAT) {
bf_set(lpfc_wq_db_ring_fm_num_posted, , 1);
-- 
2.13.1



[PATCH 03/10] lpfc: Fix panic if driver unloaded when port is offline

2018-06-26 Thread James Smart
System crashes when the lpfc module is unloaded after
making the port offline

The nvme queue pointers were freed during port offline,
but were later accessed in pci remove path.

Validate the pointers in pci remove path before accessing them.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nvme.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 76a5a99605aa..ada5a2aaee82 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2970,7 +2970,7 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba)
struct lpfc_sli_ring  *pring;
u32 i, wait_cnt = 0;
 
-   if (phba->sli_rev < LPFC_SLI_REV4)
+   if (phba->sli_rev < LPFC_SLI_REV4 || !phba->sli4_hba.nvme_wq)
return;
 
/* Cycle through all NVME rings and make sure all outstanding
@@ -2979,6 +2979,9 @@ lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba)
for (i = 0; i < phba->cfg_nvme_io_channel; i++) {
pring = phba->sli4_hba.nvme_wq[i]->pring;
 
+   if (!pring)
+   continue;
+
/* Retrieve everything on the txcmplq */
while (!list_empty(>txcmplq)) {
msleep(LPFC_XRI_EXCH_BUSY_WAIT_T1);
-- 
2.13.1



[PATCH 01/10] lpfc: Add Buffer overflow check, when nvme_info larger than PAGE_SIZE

2018-06-26 Thread James Smart
Kernel crashes during fill_read_buffer when nvme_info sysfs
file read.

With multiple NVME targets, approx 40, nvme_info may grow larger
than PAGE_SIZE bytes.  snprintf(buf + len, PAGE_SIZE - len, ...) logic
is flawed as PAGE_SIZE - len can be < 0 and is accepted by snprintf.
This results in buffer overflow, and is detected with check from
dev_attr_show and fill_read_buffer.

Change to use scnprintf to a tmp array, before calling
strlcat to ensure no buffer overflow over PAGE_SIZE bytes.

Message "6314" created as a new message indicating when
there is more nvme info, but is truncated to fit within
PAGE_SIZE bytes.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 432 +-
 1 file changed, 257 insertions(+), 175 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 729d343861f4..3b839237ab50 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -64,6 +64,9 @@
 #define LPFC_MIN_MRQ_POST  512
 #define LPFC_MAX_MRQ_POST  2048
 
+#define LPFC_MAX_NVME_INFO_TMP_LEN 100
+#define LPFC_NVME_INFO_MORE_STR"\nCould be more info...\n"
+
 /*
  * Write key size should be multiple of 4. If write key is changed
  * make sure that library write key is also changed.
@@ -158,14 +161,15 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
char *statep;
int i;
int len = 0;
+   char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
 
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
-   len += snprintf(buf, PAGE_SIZE, "NVME Disabled\n");
+   len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
return len;
}
if (phba->nvmet_support) {
if (!phba->targetport) {
-   len = snprintf(buf, PAGE_SIZE,
+   len = scnprintf(buf, PAGE_SIZE,
"NVME Target: x%llx is not allocated\n",
wwn_to_u64(vport->fc_portname.u.wwn));
return len;
@@ -175,135 +179,169 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
statep = "REGISTERED";
else
statep = "INIT";
-   len += snprintf(buf + len, PAGE_SIZE - len,
-   "NVME Target Enabled  State %s\n",
-   statep);
-   len += snprintf(buf + len, PAGE_SIZE - len,
-   "%s%d WWPN x%llx WWNN x%llx DID x%06x\n",
-   "NVME Target: lpfc",
-   phba->brd_no,
-   wwn_to_u64(vport->fc_portname.u.wwn),
-   wwn_to_u64(vport->fc_nodename.u.wwn),
-   phba->targetport->port_id);
-
-   len += snprintf(buf + len, PAGE_SIZE - len,
-   "\nNVME Target: Statistics\n");
+   scnprintf(tmp, sizeof(tmp),
+ "NVME Target Enabled  State %s\n",
+ statep);
+   if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+   goto buffer_done;
+
+   scnprintf(tmp, sizeof(tmp),
+ "%s%d WWPN x%llx WWNN x%llx DID x%06x\n",
+ "NVME Target: lpfc",
+ phba->brd_no,
+ wwn_to_u64(vport->fc_portname.u.wwn),
+ wwn_to_u64(vport->fc_nodename.u.wwn),
+ phba->targetport->port_id);
+   if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+   goto buffer_done;
+
+   if (strlcat(buf, "\nNVME Target: Statistics\n", PAGE_SIZE)
+   >= PAGE_SIZE)
+   goto buffer_done;
+
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-   len += snprintf(buf+len, PAGE_SIZE-len,
-   "LS: Rcv %08x Drop %08x Abort %08x\n",
-   atomic_read(>rcv_ls_req_in),
-   atomic_read(>rcv_ls_req_drop),
-   atomic_read(>xmt_ls_abort));
+   scnprintf(tmp, sizeof(tmp),
+ "LS: Rcv %08x Drop %08x Abort %08x\n",
+ atomic_read(>rcv_ls_req_in),
+ atomic_read(>rcv_ls_req_drop),
+ atomic_read(>xmt_ls_abort));
+   if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+  

[PATCH 2/6] lpfc: correct oversubscription of nvme io requests for an adapter

2018-05-24 Thread James Smart
Under large configurations, the driver would start to log
message 6065 - NVME out of buffers (exchanges).

The driver is using the ndlp cmd_qdepth value when determining
the max outstanding ios for an adapter. This value, by default,
is set to 65536, which exceeds the maximum exchange counts
supported on an adapter. The ndlp cmd_qdepth has no relevance
and outstanding io count should be capped at the max exchange
count with IO requests beyond that level getting bounced back
with an EBUSY status so that they are retried by the block layer.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_attr.c  |  7 +++
 drivers/scsi/lpfc/lpfc_nportdisc.c |  6 ++
 drivers/scsi/lpfc/lpfc_nvme.c  | 23 +++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index a66c4fbc7690..729d343861f4 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -297,6 +297,13 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
len = snprintf(buf, PAGE_SIZE, "NVME Initiator Enabled\n");
 
spin_lock_irq(shost->host_lock);
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "XRI Dist lpfc%d Total %d NVME %d SCSI %d ELS %d\n",
+   phba->brd_no,
+   phba->sli4_hba.max_cfg_param.max_xri,
+   phba->sli4_hba.nvme_xri_max,
+   phba->sli4_hba.scsi_xri_max,
+   lpfc_sli4_get_els_iocb_cnt(phba));
 
/* Port state is only one of two values for now. */
if (localport->port_id)
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c 
b/drivers/scsi/lpfc/lpfc_nportdisc.c
index e790c0bc64fc..1a803975bcbc 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1982,6 +1982,12 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp,
if (bf_get_be32(prli_disc, nvpr))
ndlp->nlp_type |= NLP_NVME_DISCOVERY;
 
+   /* This node is an NVME target.  Adjust the command
+* queue depth on this node to not exceed the available
+* xris.
+*/
+   ndlp->cmd_qdepth = phba->sli4_hba.nvme_xri_max;
+
/*
 * If prli_fba is set, the Target supports FirstBurst.
 * If prli_fb_sz is 0, the FirstBurst size is unlimited,
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index f5f90d19b215..288dd3caff8a 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -973,9 +973,22 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *pwqeIn,
 
/* Sanity check on return of outstanding command */
if (!lpfc_ncmd || !lpfc_ncmd->nvmeCmd || !lpfc_ncmd->nrport) {
+   if (!lpfc_ncmd) {
+   lpfc_printf_vlog(vport, KERN_ERR,
+LOG_NODE | LOG_NVME_IOERR,
+"6071 Null lpfc_ncmd pointer. No "
+"release, skip completion\n");
+   return;
+   }
+
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
-"6071 Completion pointers bad on wqe %p.\n",
-wcqe);
+"6066 Missing cmpl ptrs: lpfc_ncmd %p, "
+"nvmeCmd %p nrport %p\n",
+lpfc_ncmd, lpfc_ncmd->nvmeCmd,
+lpfc_ncmd->nrport);
+
+   /* Release the lpfc_ncmd regardless of the missing elements. */
+   lpfc_release_nvme_buf(phba, lpfc_ncmd);
return;
}
nCmd = lpfc_ncmd->nvmeCmd;
@@ -1537,8 +1550,10 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
!expedite) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
 "6174 Fail IO, ndlp qdepth exceeded: "
-"idx %d DID %x\n",
-lpfc_queue_info->index, ndlp->nlp_DID);
+"idx %d DID %x pend %d qdepth %d\n",
+lpfc_queue_info->index, ndlp->nlp_DID,
+atomic_read(>cmd_pending),
+ndlp->cmd_qdepth);
atomic_inc(>xmt_fcp_qdepth);
ret = -EBUSY;
goto out_fail;
-- 
2.13.1



[PATCH 5/6] lpfc: Fix port initialization failure.

2018-05-24 Thread James Smart
The driver exits port setup after failing the
lpfc_sli4_get_parameters command (messages 0356, 2541, & 1412).

The older CNA adapters do not support the MBX command. In the past
the code was allowed to fail and continue on with initialization.
However a nvme change moved a closing bracket and now makes all
failures terminal.

Revise the logic so that terminal failure only occurs if the command
failed on the newer adapters. Additionally, if parameters are set
that require information from the command and the command failed,
the parameters are erroneous and port set up should fail even on
the older adapters.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_init.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 48a5f067cec6..7ae343b14630 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -5850,6 +5850,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
int fof_vectors = 0;
int extra;
uint64_t wwn;
+   u32 if_type;
+   u32 if_fam;
 
phba->sli4_hba.num_online_cpu = num_online_cpus();
phba->sli4_hba.num_present_cpu = lpfc_present_cpu;
@@ -6171,15 +6173,28 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
 */
rc = lpfc_get_sli4_parameters(phba, mboxq);
if (rc) {
+   if_type = bf_get(lpfc_sli_intf_if_type,
+>sli4_hba.sli_intf);
+   if_fam = bf_get(lpfc_sli_intf_sli_family,
+   >sli4_hba.sli_intf);
if (phba->sli4_hba.extents_in_use &&
phba->sli4_hba.rpi_hdrs_in_use) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2999 Unsupported SLI4 Parameters "
"Extents and RPI headers enabled.\n");
+   if (if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
+   if_fam ==  LPFC_SLI_INTF_FAMILY_BE2) {
+   mempool_free(mboxq, phba->mbox_mem_pool);
+   rc = -EIO;
+   goto out_free_bsmbx;
+   }
+   }
+   if (!(if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
+ if_fam == LPFC_SLI_INTF_FAMILY_BE2)) {
+   mempool_free(mboxq, phba->mbox_mem_pool);
+   rc = -EIO;
+   goto out_free_bsmbx;
}
-   mempool_free(mboxq, phba->mbox_mem_pool);
-   rc = -EIO;
-   goto out_free_bsmbx;
}
 
mempool_free(mboxq, phba->mbox_mem_pool);
-- 
2.13.1



[PATCH 4/6] lpfc: Fix 16gb hbas failing cq create.

2018-05-24 Thread James Smart
The lancer G5 chip family fails the CQ create with 16k page size.
The hardware incorrectly reports it supports large page sizes
when it is actually limited to 4k pages.

A prior patch resolved this for the A0 chip revision only.
This patch excludes all revisions of the G5 asic from using
large page sizes. As knowing the actual chip revision is
unnecessary, the now unused definitions are removed

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_hw4.h  | 11 ---
 drivers/scsi/lpfc/lpfc_init.c |  9 +
 drivers/scsi/lpfc/lpfc_sli4.h |  1 -
 3 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 807901af9bbe..f43f0bacb77a 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -104,17 +104,6 @@ struct lpfc_sli_intf {
 #define LPFC_SLI_INTF_IF_TYPE_VIRT 1
 };
 
-struct lpfc_sli_asic_rev {
-   u32 word0;
-#define LPFC_SLI_ASIC_VER_A0x0
-#define LPFC_SLI_ASIC_VER_B0x1
-#define LPFC_SLI_ASIC_VER_C0x2
-#define LPFC_SLI_ASIC_VER_D0x3
-#define lpfc_sli_asic_ver_SHIFT4
-#define lpfc_sli_asic_ver_MASK 0x000F
-#define lpfc_sli_asic_ver_WORD word0
-};
-
 #define LPFC_SLI4_MBX_EMBEDtrue
 #define LPFC_SLI4_MBX_NEMBED   false
 
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 83bc8d849a0d..48a5f067cec6 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9545,11 +9545,6 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
return error;
}
 
-   if (pci_read_config_dword(pdev, LPFC_SLI_ASIC_VER,
- >sli4_hba.sli_asic_ver.word0)) {
-   return error;
-   }
-
/* There is no SLI3 failback for SLI4 devices. */
if (bf_get(lpfc_sli_intf_valid, >sli4_hba.sli_intf) !=
LPFC_SLI_INTF_VALID) {
@@ -10711,9 +10706,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
if ((bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) ==
LPFC_SLI_INTF_IF_TYPE_2) &&
(bf_get(lpfc_sli_intf_sli_family, >sli4_hba.sli_intf) ==
-LPFC_SLI_INTF_FAMILY_LNCR_A0) &&
-   (bf_get(lpfc_sli_asic_ver, >sli4_hba.sli_asic_ver) ==
-   LPFC_SLI_ASIC_VER_A))
+LPFC_SLI_INTF_FAMILY_LNCR_A0))
exp_wqcq_pages = false;
 
if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 179e870a00b4..cf64aca82bd0 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -592,7 +592,6 @@ struct lpfc_sli4_hba {
uint32_t ue_to_sr;
uint32_t ue_to_rp;
struct lpfc_register sli_intf;
-   struct lpfc_register sli_asic_ver;
struct lpfc_pc_sli4_params pc_sli4_params;
struct lpfc_bbscn_params bbscn_params;
struct lpfc_hba_eq_hdl *hba_eq_hdl; /* HBA per-WQ handle */
-- 
2.13.1



[PATCH 6/6] lpfc: update driver version to 12.0.0.4

2018-05-24 Thread James Smart
Update the driver version to 12.0.0.4

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 9fca71d7c297..18c23afcf46b 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.3"
+#define LPFC_DRIVER_VERSION "12.0.0.4"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH 3/6] lpfc: Fix crash in blk_mq layer when executing modprobe -r lpfc

2018-05-24 Thread James Smart
modprobe -r lpfc produces the following:

Call Trace:
 __blk_mq_run_hw_queue+0xa2/0xb0
 __blk_mq_delay_run_hw_queue+0x9d/0xb0
 ? blk_mq_hctx_has_pending+0x32/0x80
 blk_mq_run_hw_queue+0x50/0xd0
 blk_mq_sched_insert_request+0x110/0x1b0
 blk_execute_rq_nowait+0x76/0x180
 nvme_keep_alive_work+0x8a/0xd0 [nvme_core]
 process_one_work+0x17f/0x440
 worker_thread+0x126/0x3c0
 ? manage_workers.isra.24+0x2a0/0x2a0
 kthread+0xd1/0xe0
 ? insert_kthread_work+0x40/0x40
 ret_from_fork_nospec_begin+0x21/0x21
 ? insert_kthread_work+0x40/0x40

However, rmmod lpfc would run correctly.

When an nvme remoteport is unregistered with the host nvme
transport, it needs to set the remoteport->dev_loss_tmo value 0
to indicate an immediate termination of device loss and prevent
any further keep alives to that rport.  The driver was never
setting dev_loss_tmo causing the nvme transport to continue to
send the keep alive.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_nvme.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 288dd3caff8a..76a5a99605aa 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2862,6 +2862,15 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
 * The transport will update it.
 */
ndlp->upcall_flags |= NLP_WAIT_FOR_UNREG;
+
+   /* Don't let the host nvme transport keep sending keep-alives
+* on this remoteport. Vport is unloading, no recovery. The
+* return values is ignored.  The upcall is a courtesy to the
+* transport.
+*/
+   if (vport->load_flag & FC_UNLOADING)
+   (void)nvme_fc_set_remoteport_devloss(remoteport, 0);
+
ret = nvme_fc_unregister_remoteport(remoteport);
if (ret != 0) {
lpfc_nlp_put(ndlp);
-- 
2.13.1



[PATCH 0/6] lpfc updates for 12.0.0.4

2018-05-24 Thread James Smart
This patch contains lpfc bug fixes and a few message updates and
cleanups.

The patches were cut against the Martin's 4.18/scsi-queue tree


James Smart (6):
  lpfc: Fix MDS diagnostics failure (Rx < Tx)
  lpfc: correct oversubscription of nvme io requests for an adapter
  lpfc: Fix crash in blk_mq layer when executing modprobe -r lpfc
  lpfc: Fix 16gb hbas failing cq create.
  lpfc: Fix port initialization failure.
  lpfc: update driver version to 12.0.0.4

 drivers/scsi/lpfc/lpfc_attr.c  |  7 +++
 drivers/scsi/lpfc/lpfc_hbadisc.c   |  3 +--
 drivers/scsi/lpfc/lpfc_hw4.h   | 11 ---
 drivers/scsi/lpfc/lpfc_init.c  | 30 +++---
 drivers/scsi/lpfc/lpfc_nportdisc.c |  6 ++
 drivers/scsi/lpfc/lpfc_nvme.c  | 32 
 drivers/scsi/lpfc/lpfc_sli.c   | 19 ---
 drivers/scsi/lpfc/lpfc_sli4.h  |  1 -
 drivers/scsi/lpfc/lpfc_version.h   |  2 +-
 9 files changed, 78 insertions(+), 33 deletions(-)

-- 
2.13.1



[PATCH 1/6] lpfc: Fix MDS diagnostics failure (Rx < Tx)

2018-05-24 Thread James Smart
MDS diagnostics fail because of frame count mismatch.

Unavailability of SGL is the trigger for this issue. If ELS SGL
is not available to process MDS frame, IOCB is put in FCP txq
but not attempted to post afterwards. So, driver stops processing
incoming frames as it runs out of IOCB.  lpfc_drain_txq attempts
to submit IOCBS that are queued in ELS txq but MDS frames are
posted to FCP WQ.

Attempt to submit IOCBs that are present in FCP txq when MDS
loopback is running.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_hbadisc.c |  3 +--
 drivers/scsi/lpfc/lpfc_sli.c | 19 ---
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index cf2cbaa241b9..2fef54fab86d 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -708,8 +708,7 @@ lpfc_work_done(struct lpfc_hba *phba)
HA_RXMASK));
}
}
-   if ((phba->sli_rev == LPFC_SLI_REV4) &&
-(!list_empty(>txq)))
+   if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_drain_txq(phba);
/*
 * Turn on Ring interrupts
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 6b709cd4140b..4b70d53acb72 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -19069,9 +19069,22 @@ lpfc_drain_txq(struct lpfc_hba *phba)
struct lpfc_sglq *sglq;
union lpfc_wqe128 wqe;
uint32_t txq_cnt = 0;
+   struct lpfc_queue *wq;
 
-   pring = lpfc_phba_elsring(phba);
-   if (unlikely(!pring))
+   if (phba->link_flag & LS_MDS_LOOPBACK) {
+   /* MDS WQE are posted only to first WQ*/
+   wq = phba->sli4_hba.fcp_wq[0];
+   if (unlikely(!wq))
+   return 0;
+   pring = wq->pring;
+   } else {
+   wq = phba->sli4_hba.els_wq;
+   if (unlikely(!wq))
+   return 0;
+   pring = lpfc_phba_elsring(phba);
+   }
+
+   if (unlikely(!pring) || list_empty(>txq))
return 0;
 
spin_lock_irqsave(>ring_lock, iflags);
@@ -19112,7 +19125,7 @@ lpfc_drain_txq(struct lpfc_hba *phba)
fail_msg = "to convert bpl to sgl";
else if (lpfc_sli4_iocb2wqe(phba, piocbq, ))
fail_msg = "to convert iocb to wqe";
-   else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, ))
+   else if (lpfc_sli4_wq_put(wq, ))
fail_msg = " - Wq is full";
else
lpfc_sli_ringtxcmpl_put(phba, pring, piocbq);
-- 
2.13.1



[PATCH 01/10] lpfc: Change IO submit return to EBUSY if remote port is recovering

2018-05-04 Thread James Smart
I/O submission paths in the lpfc nvme path are rejecting the io with an
error code that reflects back to the callee as a hard io failure. Many
of these conditions are transient and would likely resolve if retried.

Correct by returning -EBUSY, which the FC transport triggers off of to
return busy status codes to the blk-mq layer.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_nvme.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 9e0345697e1b..2d80c7207869 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1452,8 +1452,8 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
 
if (unlikely(!hw_queue_handle)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS,
-"6129 Fail Abort, NULL hw_queue_handle\n");
-   ret = -EINVAL;
+"6117 Fail Abort, NULL hw_queue_handle\n");
+   ret = -EBUSY;
goto out_fail;
}
 
@@ -1499,7 +1499,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
 "6066 Missing node for DID %x\n",
 pnvme_rport->port_id);
atomic_inc(>xmt_fcp_bad_ndlp);
-   ret = -ENODEV;
+   ret = -EBUSY;
goto out_fail;
}
}
@@ -1509,11 +1509,12 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
(ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
 "6036 rport %p, DID x%06x not ready for "
-"IO. State x%x, Type x%x\n",
+"IO. State x%x, Type x%x Flg x%x\n",
 rport, pnvme_rport->port_id,
-ndlp->nlp_state, ndlp->nlp_type);
+ndlp->nlp_state, ndlp->nlp_type,
+ndlp->upcall_flags);
atomic_inc(>xmt_fcp_bad_ndlp);
-   ret = -ENODEV;
+   ret = -EBUSY;
goto out_fail;
 
}
-- 
2.13.1



[PATCH 04/10] lpfc: Handle new link fault code returned by adapter firmware.

2018-05-04 Thread James Smart
The driver encounters a link event ACQE with a fault code it doesn't
recognize, it logs an "Invalid" fault type and futher treats the
unknown value as a mailbox command failure.  First off, there is
no "invalid" value, only values that are unknown. Secondly, the
fault code doesn't indicate status - the rest of the ACQE contains
that status so there is no reason to "fail the commands".

Change the "Invalid" to "Unknown". There is no "invalid" code value.

Separate fault code parsing and message genaration from any mbx
handling status.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_hw4.h  |  1 +
 drivers/scsi/lpfc/lpfc_init.c | 31 ++-
 2 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 571099fbde28..eed8dea42f74 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -3924,6 +3924,7 @@ struct lpfc_acqe_link {
 #define LPFC_ASYNC_LINK_FAULT_NONE 0x0
 #define LPFC_ASYNC_LINK_FAULT_LOCAL0x1
 #define LPFC_ASYNC_LINK_FAULT_REMOTE   0x2
+#define LPFC_ASYNC_LINK_FAULT_LR_LRR   0x3
 #define lpfc_acqe_logical_link_speed_SHIFT 16
 #define lpfc_acqe_logical_link_speed_MASK  0x
 #define lpfc_acqe_logical_link_speed_WORD  word1
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 70583e1b227d..0ba49e605a61 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4279,32 +4279,24 @@ lpfc_sli4_fcf_redisc_wait_tmo(struct timer_list *t)
  * @phba: pointer to lpfc hba data structure.
  * @acqe_link: pointer to the async link completion queue entry.
  *
- * This routine is to parse the SLI4 link-attention link fault code and
- * translate it into the base driver's read link attention mailbox command
- * status.
- *
- * Return: Link-attention status in terms of base driver's coding.
+ * This routine is to parse the SLI4 link-attention link fault code.
  **/
-static uint16_t
+static void
 lpfc_sli4_parse_latt_fault(struct lpfc_hba *phba,
   struct lpfc_acqe_link *acqe_link)
 {
-   uint16_t latt_fault;
-
switch (bf_get(lpfc_acqe_link_fault, acqe_link)) {
case LPFC_ASYNC_LINK_FAULT_NONE:
case LPFC_ASYNC_LINK_FAULT_LOCAL:
case LPFC_ASYNC_LINK_FAULT_REMOTE:
-   latt_fault = 0;
+   case LPFC_ASYNC_LINK_FAULT_LR_LRR:
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "0398 Invalid link fault code: x%x\n",
+   "0398 Unknown link fault code: x%x\n",
bf_get(lpfc_acqe_link_fault, acqe_link));
-   latt_fault = MBXERR_ERROR;
break;
}
-   return latt_fault;
 }
 
 /**
@@ -4579,9 +4571,12 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
 * the READ_TOPOLOGY completion routine to continue without actually
 * sending the READ_TOPOLOGY mailbox command to the port.
 */
-   /* Parse and translate status field */
+   /* Initialize completion status */
mb = >u.mb;
-   mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link);
+   mb->mbxStatus = MBX_SUCCESS;
+
+   /* Parse port fault information field */
+   lpfc_sli4_parse_latt_fault(phba, acqe_link);
 
/* Parse and translate link attention fields */
la = (struct lpfc_mbx_read_top *) >u.mb.un.varReadTop;
@@ -4709,10 +4704,12 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct 
lpfc_acqe_fc_la *acqe_fc)
break;
}
 
-   /* Parse and translate status field */
+   /* Initialize completion status */
mb = >u.mb;
-   mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
-  (void *)acqe_fc);
+   mb->mbxStatus = MBX_SUCCESS;
+
+   /* Parse port fault information field */
+   lpfc_sli4_parse_latt_fault(phba, (void *)acqe_fc);
 
/* Parse and translate link attention fields */
la = (struct lpfc_mbx_read_top *)>u.mb.un.varReadTop;
-- 
2.13.1



[PATCH 06/10] lpfc: Check if SCSI scanning is complete, before allowing I/O commands

2018-05-04 Thread James Smart
A race condition is being seen. I/O is being issued to scsi targets
simultaneous to a short connectivity loss. The rport block/unblock is
occurring, but the unblock is allowing pending I/O commands to intermix
with the commands being used to scan the scsi bus. Thus the target
device is getting a read or write prior to transitioning to an ready
state, thus the device errors the io. The io error propagatest all the
way back to the application.

Resolve by augmenting the io submission with a check to see whether
transport is scanning the remote port or not. If not, then the io is
failed such that it will be retried. If so, then normal processing resumes.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_scsi.c | 48 +++
 drivers/scsi/lpfc/lpfc_scsi.h | 15 ++
 2 files changed, 63 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 7932bf30c8d7..303f1ad0c27f 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4506,6 +4506,43 @@ void lpfc_poll_timeout(struct timer_list *t)
 }
 
 /**
+ * lpfc_is_scan_cmd - check command code within opcode for scanning related cmd
+ * @opcode: opcode of scsi_cmnd data structure.
+ *
+ * scsi midlayer may submit I/O commands before scanning is complete caused by
+ * lip in transport layer.
+ * This routine checks if the scsi cmd is related to scanning following FCP-4
+ * discovery procedure.
+ *
+ * Return value :
+ *   0 - Not a scanning related command
+ *   1 - Is a scanning related command
+ **/
+static int
+lpfc_is_scan_cmd(uint8_t opcode)
+{
+   switch (opcode & 0x1f) {
+   case LPFC_INQUIRY_CMD_CODE:
+   case LPFC_LOG_SELECT_CMD_CODE:
+   case LPFC_LOG_SENSE_CMD_CODE:
+   case LPFC_MODE_SELECT_CMD_CODE:
+   case LPFC_MODE_SENSE_CMD_CODE:
+   case LPFC_REPORT_LUNS_CMD_CODE:
+   case LPFC_SEND_DIAGNOSTIC_CMD_CODE:
+   case LPFC_MAINTENANCE_IN_CMD_CODE:
+   case LPFC_MAINTENANCE_OUT_CMD_CODE:
+   case LPFC_PERSISTENT_RESERVE_IN_CMD_CODE:
+   case LPFC_PERSISTENT_RESERVE_OUT_CMD_CODE:
+   case LPFC_READ_BUFFER_CMD_CODE:
+   case LPFC_WRITE_BUFFER_CMD_CODE:
+   break;
+   default:
+   return 0;
+   }
+   return 1;
+}
+
+/**
  * lpfc_queuecommand - scsi_host_template queuecommand entry point
  * @cmnd: Pointer to scsi_cmnd data structure.
  * @done: Pointer to done routine.
@@ -4537,6 +4574,17 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct 
scsi_cmnd *cmnd)
}
ndlp = rdata->pnode;
 
+   if ((rport->flags & FC_RPORT_SCAN_PENDING) &&
+   !(lpfc_is_scan_cmd(cmnd->cmnd[0]))) {
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+"6423 scan still pending, "
+"command = 0x%02x to be "
+"retried\n",
+cmnd->cmnd[0]);
+   cmnd->result = DID_IMM_RETRY << 16;
+   goto out_fail_command;
+   }
+
if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) &&
(!(phba->sli3_options & LPFC_SLI3_BG_ENABLED))) {
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 8e38e0204c47..68c8a24c659c 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -194,5 +194,20 @@ struct lpfc_scsi_buf {
 
 #define TXRDY_PAYLOAD_LEN  12
 
+/* Safe command codes for scanning, excluding group code */
+#define LPFC_INQUIRY_CMD_CODE  (INQUIRY & 0x1f)
+#define LPFC_LOG_SELECT_CMD_CODE   (LOG_SELECT & 0x1f)
+#define LPFC_LOG_SENSE_CMD_CODE(LOG_SENSE & 0x1f)
+#define LPFC_MODE_SELECT_CMD_CODE  (MODE_SELECT & 0x1f)
+#define LPFC_MODE_SENSE_CMD_CODE   (MODE_SENSE & 0x1f)
+#define LPFC_REPORT_LUNS_CMD_CODE  (REPORT_LUNS & 0x1f)
+#define LPFC_SEND_DIAGNOSTIC_CMD_CODE  (SEND_DIAGNOSTIC & 0x1f)
+#define LPFC_MAINTENANCE_IN_CMD_CODE   (MAINTENANCE_IN & 0x1f)
+#define LPFC_MAINTENANCE_OUT_CMD_CODE  (MAINTENANCE_OUT & 0x1f)
+#define LPFC_PERSISTENT_RESERVE_IN_CMD_CODE(PERSISTENT_RESERVE_IN & 0x1f)
+#define LPFC_PERSISTENT_RESERVE_OUT_CMD_CODE   (PERSISTENT_RESERVE_OUT & 0x1f)
+#define LPFC_READ_BUFFER_CMD_CODE  (READ_BUFFER & 0x1f)
+#define LPFC_WRITE_BUFFER_CMD_CODE (WRITE_BUFFER & 0x1f)
+
 int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba,
  struct lpfc_scsi_buf *lpfc_cmd);
-- 
2.13.1



[PATCH 08/10] lpfc: Enhance log messages when reporting CQE errors

2018-05-04 Thread James Smart
Enhance log messages for CQEs as they were not reporting certain fields.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_sli.c | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 30480e47913f..48ba9eb8a96b 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -12972,6 +12972,17 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, 
struct lpfc_queue *cq,
int txcmplq_cnt = 0;
int fcp_txcmplq_cnt = 0;
 
+   /* Check for response status */
+   if (unlikely(bf_get(lpfc_wcqe_c_status, wcqe))) {
+   /* Log the error status */
+   lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+   "0357 ELS CQE error: status=x%x: "
+   "CQE: %08x %08x %08x %08x\n",
+   bf_get(lpfc_wcqe_c_status, wcqe),
+   wcqe->word0, wcqe->total_data_placed,
+   wcqe->parameter, wcqe->word3);
+   }
+
/* Get an irspiocbq for later ELS response processing use */
irspiocbq = lpfc_sli_get_iocbq(phba);
if (!irspiocbq) {
@@ -13392,14 +13403,12 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, 
struct lpfc_queue *cq,
phba->lpfc_rampdown_queue_depth(phba);
 
/* Log the error status */
-   lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-   "0373 FCP complete error: status=x%x, "
-   "hw_status=x%x, total_data_specified=%d, "
-   "parameter=x%x, word3=x%x\n",
+   lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+   "0373 FCP CQE error: status=x%x: "
+   "CQE: %08x %08x %08x %08x\n",
bf_get(lpfc_wcqe_c_status, wcqe),
-   bf_get(lpfc_wcqe_c_hw_status, wcqe),
-   wcqe->total_data_placed, wcqe->parameter,
-   wcqe->word3);
+   wcqe->word0, wcqe->total_data_placed,
+   wcqe->parameter, wcqe->word3);
}
 
/* Look up the FCP command IOCB and create pseudo response IOCB */
-- 
2.13.1



[PATCH 09/10] lpfc: update driver version to 12.0.0.3

2018-05-04 Thread James Smart
Update the driver version to 12.0.0.3

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 0cd474bb0bdd..666ffa179653 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.2"
+#define LPFC_DRIVER_VERSION "12.0.0.3"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH 05/10] lpfc: Driver NVME load fails when CPU cnt > WQ resource cnt

2018-05-04 Thread James Smart
If the cpu count is larger than the number of WQ resources available,
adapter attachment eventually failes due to a WQ_CREATE failure.

Calculate the number of WQs desired (which initializes to cpu count)
after accounting for the number of queues the adapter supports and
the number allocated to SCSI and the control/ELS path, and scale down
if necessary.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_init.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 0ba49e605a61..119432035e9e 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -7790,6 +7790,40 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
phba->sli4_hba.max_cfg_param.max_wq,
phba->sli4_hba.max_cfg_param.max_rq);
 
+   /*
+* Calculate NVME queue resources based on how
+* many WQ/CQs are available.
+*/
+   if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
+   length = phba->sli4_hba.max_cfg_param.max_wq;
+   if (phba->sli4_hba.max_cfg_param.max_cq <
+   phba->sli4_hba.max_cfg_param.max_wq)
+   length = phba->sli4_hba.max_cfg_param.max_cq;
+
+   /*
+* Whats left after this can go toward NVME.
+* The minus 6 accounts for ELS, NVME LS, MBOX
+* fof plus a couple extra. When configured for
+* NVMET, FCP io channel WQs are not created.
+*/
+   length -= 6;
+   if (!phba->nvmet_support)
+   length -= phba->cfg_fcp_io_channel;
+
+   if (phba->cfg_nvme_io_channel > length) {
+   lpfc_printf_log(
+   phba, KERN_ERR, LOG_SLI,
+   "2005 Reducing NVME IO channel to %d: "
+   "WQ %d CQ %d NVMEIO %d FCPIO %d\n",
+   length,
+   phba->sli4_hba.max_cfg_param.max_wq,
+   phba->sli4_hba.max_cfg_param.max_cq,
+   phba->cfg_nvme_io_channel,
+   phba->cfg_fcp_io_channel);
+
+   phba->cfg_nvme_io_channel = length;
+   }
+   }
}
 
if (rc)
-- 
2.13.1



[PATCH 10/10] lpfc: Comment cleanup regarding Broadcom copyright header

2018-05-04 Thread James Smart
Fix small formatting and wording nits in Broadcom copyright header

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_attr.c| 2 +-
 drivers/scsi/lpfc/lpfc_debugfs.c | 2 +-
 drivers/scsi/lpfc/lpfc_hw4.h | 2 +-
 drivers/scsi/lpfc/lpfc_init.c| 2 +-
 drivers/scsi/lpfc/lpfc_nvme.c| 2 +-
 drivers/scsi/lpfc/lpfc_nvme.h| 2 +-
 drivers/scsi/lpfc/lpfc_scsi.c| 2 +-
 drivers/scsi/lpfc/lpfc_scsi.h| 2 +-
 drivers/scsi/lpfc/lpfc_sli.c | 2 +-
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index e79724564b2e..a66c4fbc7690 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index ccc342247782..9df0c051349f 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
  * Copyright (C) 2007-2015 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index eed8dea42f74..807901af9bbe 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
  * Copyright (C) 2009-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 119432035e9e..3d89b08896d1 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 9fba34d5d5e1..f5f90d19b215 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
  * www.broadcom.com*
diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
index 129189324c31..04bd463dd043 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.h
+++ b/drivers/scsi/lpfc/lpfc_nvme.h
@@ -2,7 +2,7 @@
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
  * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
+ * “Broadcom” refers to Broadcom Inc

[PATCH 07/10] lpfc: Fix up log messages and stats counters in IO submit code path

2018-05-04 Thread James Smart
Fix up log messages and add an fcp error stat counter in the IO
submit code path to make diagnosing problems easier

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_attr.c|  3 ++-
 drivers/scsi/lpfc/lpfc_debugfs.c |  3 ++-
 drivers/scsi/lpfc/lpfc_nvme.c| 53 
 drivers/scsi/lpfc/lpfc_nvme.h|  1 +
 4 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index fd3b25317887..e79724564b2e 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -405,11 +405,12 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
 
len += snprintf(buf+len, PAGE_SIZE-len,
"  abort %08x noxri %08x nondlp %08x qdepth %08x "
-   "wqerr %08x\n",
+   "wqerr %08x err %08x\n",
atomic_read(>xmt_fcp_abort),
atomic_read(>xmt_fcp_noxri),
atomic_read(>xmt_fcp_bad_ndlp),
atomic_read(>xmt_fcp_qdepth),
+   atomic_read(>xmt_fcp_err),
atomic_read(>xmt_fcp_wqerr));
 
len += snprintf(buf + len, PAGE_SIZE - len,
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index afe7883c988a..ccc342247782 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -959,11 +959,12 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char 
*buf, int size)
 
len += snprintf(buf + len, size - len,
"FCP Xmt Err: noxri %06x nondlp %06x "
-   "qdepth %06x wqerr %06x Abrt %06x\n",
+   "qdepth %06x wqerr %06x err %06x Abrt %06x\n",
atomic_read(>xmt_fcp_noxri),
atomic_read(>xmt_fcp_bad_ndlp),
atomic_read(>xmt_fcp_qdepth),
atomic_read(>xmt_fcp_wqerr),
+   atomic_read(>xmt_fcp_err),
atomic_read(>xmt_fcp_abort));
 
len += snprintf(buf + len, size - len,
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 2d80c7207869..9fba34d5d5e1 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1451,8 +1451,9 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
vport = lport->vport;
 
if (unlikely(!hw_queue_handle)) {
-   lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS,
-"6117 Fail Abort, NULL hw_queue_handle\n");
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+"6117 Fail IO, NULL hw_queue_handle\n");
+   atomic_inc(>xmt_fcp_err);
ret = -EBUSY;
goto out_fail;
}
@@ -1465,12 +1466,18 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
}
 
if (vport->load_flag & FC_UNLOADING) {
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+"6124 Fail IO, Driver unload\n");
+   atomic_inc(>xmt_fcp_err);
ret = -ENODEV;
goto out_fail;
}
 
freqpriv = pnvme_fcreq->private;
if (unlikely(!freqpriv)) {
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+"6158 Fail IO, NULL request data\n");
+   atomic_inc(>xmt_fcp_err);
ret = -EINVAL;
goto out_fail;
}
@@ -1488,29 +1495,22 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port 
*pnvme_lport,
 */
ndlp = rport->ndlp;
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
-   lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
-"6053 rport %p, ndlp %p, DID x%06x "
-"ndlp not ready.\n",
+   lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_NVME_IOERR,
+"6053 Fail IO, ndlp not ready: rport %p "
+ "ndlp %p, DID x%06x\n",
 rport, ndlp, pnvme_rport->port_id);
-
-   ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
-   if (!ndlp) {
-   lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
-"6066 Missing node for DID %x\n",
-   

[PATCH 00/10] lpfc updates for 12.0.0.3

2018-05-04 Thread James Smart
This patch contains lpfc bug fixes and a few message updates and
cleanups.

The patches were cut against the Martin's 4.17/scsi-queue tree


James Smart (10):
  lpfc: Change IO submit return to EBUSY if remote port is recovering
  lpfc: enhance LE data structure copies to hardware
  lpfc: Correct fw download error message
  lpfc: Handle new link fault code returned by adapter firmware.
  lpfc: Driver NVME load fails when CPU cnt > WQ resource cnt
  lpfc: Check if SCSI scanning is complete, before allowing I/O commands
  lpfc: Fix up log messages and stats counters in IO submit code path
  lpfc: Enhance log messages when reporting CQE errors
  lpfc: update driver version to 12.0.0.3
  lpfc: Comment cleanup regarding Broadcom copyright header

 drivers/scsi/lpfc/lpfc_attr.c|  5 ++-
 drivers/scsi/lpfc/lpfc_debugfs.c |  5 ++-
 drivers/scsi/lpfc/lpfc_hw4.h |  6 ++-
 drivers/scsi/lpfc/lpfc_init.c| 73 ++--
 drivers/scsi/lpfc/lpfc_nvme.c| 64 ++-
 drivers/scsi/lpfc/lpfc_nvme.h|  3 +-
 drivers/scsi/lpfc/lpfc_scsi.c| 50 -
 drivers/scsi/lpfc/lpfc_scsi.h| 17 -
 drivers/scsi/lpfc/lpfc_sli.c | 81 +---
 drivers/scsi/lpfc/lpfc_version.h |  4 +-
 10 files changed, 231 insertions(+), 77 deletions(-)

-- 
2.13.1



[PATCH 02/10] lpfc: enhance LE data structure copies to hardware

2018-05-04 Thread James Smart
The driver builds the control structures in host memory using
definitions that are based on 32-bit words. After building the
structure it is then written to the adapter.

This patch slightly optimizes LE hosts by copying the structures
via 64-bit copies.  This is doable as the adapter interface is LE
thus there is no byteswapping as the copy is performed.

The same optimization would be nice on BE systems, but when
byteswapping occurs, it swaps 32-bit words as well, thus trashing
the control structure. Given amount of code that is dependent
upon the 32-bit word definition, it was decided to not change
things for the minor optimization. Thus PPC 64-bit systems sticks
with doing 32-bit copies.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_sli.c | 56 +---
 1 file changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 38993efbe37e..30480e47913f 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -96,6 +96,34 @@ lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
return >iocb;
 }
 
+#if defined(CONFIG_64BIT) && defined(__LITTLE_ENDIAN)
+/**
+ * lpfc_sli4_pcimem_bcopy - SLI4 memory copy function
+ * @srcp: Source memory pointer.
+ * @destp: Destination memory pointer.
+ * @cnt: Number of words required to be copied.
+ *   Must be a multiple of sizeof(uint64_t)
+ *
+ * This function is used for copying data between driver memory
+ * and the SLI WQ. This function also changes the endianness
+ * of each word if native endianness is different from SLI
+ * endianness. This function can be called with or without
+ * lock.
+ **/
+void
+lpfc_sli4_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
+{
+   uint64_t *src = srcp;
+   uint64_t *dest = destp;
+   int i;
+
+   for (i = 0; i < (int)cnt; i += sizeof(uint64_t))
+   *dest++ = *src++;
+}
+#else
+#define lpfc_sli4_pcimem_bcopy(a, b, c) lpfc_sli_pcimem_bcopy(a, b, c)
+#endif
+
 /**
  * lpfc_sli4_wq_put - Put a Work Queue Entry on an Work Queue
  * @q: The Work Queue to operate on.
@@ -137,7 +165,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 
*wqe)
bf_set(wqe_wqec, >generic.wqe_com, 0);
if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
bf_set(wqe_wqid, >generic.wqe_com, q->queue_id);
-   lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
+   lpfc_sli4_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
if (q->dpp_enable && q->phba->cfg_enable_dpp) {
/* write to DPP aperture taking advatage of Combined Writes */
tmp = (uint8_t *)temp_wqe;
@@ -240,7 +268,7 @@ lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe)
/* If the host has not yet processed the next entry then we are done */
if (((q->host_index + 1) % q->entry_count) == q->hba_index)
return -ENOMEM;
-   lpfc_sli_pcimem_bcopy(mqe, temp_mqe, q->entry_size);
+   lpfc_sli4_pcimem_bcopy(mqe, temp_mqe, q->entry_size);
/* Save off the mailbox pointer for completion */
q->phba->mbox = (MAILBOX_t *)temp_mqe;
 
@@ -663,8 +691,8 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue 
*dq,
/* If the host has not yet processed the next entry then we are done */
if (((hq_put_index + 1) % hq->entry_count) == hq->hba_index)
return -EBUSY;
-   lpfc_sli_pcimem_bcopy(hrqe, temp_hrqe, hq->entry_size);
-   lpfc_sli_pcimem_bcopy(drqe, temp_drqe, dq->entry_size);
+   lpfc_sli4_pcimem_bcopy(hrqe, temp_hrqe, hq->entry_size);
+   lpfc_sli4_pcimem_bcopy(drqe, temp_drqe, dq->entry_size);
 
/* Update the host index to point to the next slot */
hq->host_index = ((hq_put_index + 1) % hq->entry_count);
@@ -8185,8 +8213,8 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
 */
mbx_cmnd = bf_get(lpfc_mqe_command, mb);
memset(phba->sli4_hba.bmbx.avirt, 0, sizeof(struct lpfc_bmbx_create));
-   lpfc_sli_pcimem_bcopy(mb, phba->sli4_hba.bmbx.avirt,
- sizeof(struct lpfc_mqe));
+   lpfc_sli4_pcimem_bcopy(mb, phba->sli4_hba.bmbx.avirt,
+  sizeof(struct lpfc_mqe));
 
/* Post the high mailbox dma address to the port and wait for ready. */
dma_address = >sli4_hba.bmbx.dma_address;
@@ -8210,11 +8238,11 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
 * If so, update the mailbox status so that the upper layers
 * can complete the request normally.
 */
-   lpfc_sli_pcimem_bcopy(phba->sli4_hba.bmbx.avirt, mb,
- sizeof(struct

[PATCH 03/10] lpfc: Correct fw download error message

2018-05-04 Thread James Smart
In situations when the firmware image in inappropriate for the
chip type, initial validation checks were light, allowing the
checks to pass, thus allowing the firmware to be downloaded.
Eventually, after the download, the chip rejects the firmware
but it is logged as a generic firmware download error.

Revise the initial checks to validate the image vs asic type so
that the correct message is displayed and the download process
is avoided.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_hw4.h  | 3 +++
 drivers/scsi/lpfc/lpfc_init.c | 6 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 9df1c8da6f52..571099fbde28 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -4628,6 +4628,9 @@ union lpfc_wqe128 {
struct send_frame_wqe send_frame;
 };
 
+#define MAGIC_NUMER_G6 0xFEAA0003
+#define MAGIC_NUMER_G7 0xFEAA0005
+
 struct lpfc_grp_hdr {
uint32_t size;
uint32_t magic_number;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 060f0e2f6ff5..70583e1b227d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -11349,7 +11349,11 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, 
uint32_t offset,
uint32_t magic_number, uint32_t ftype, uint32_t fid, uint32_t fsize,
const struct firmware *fw)
 {
-   if (offset == ADD_STATUS_FW_NOT_SUPPORTED)
+   if ((offset == ADD_STATUS_FW_NOT_SUPPORTED) ||
+   (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
+magic_number != MAGIC_NUMER_G6) ||
+   (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC &&
+magic_number != MAGIC_NUMER_G7))
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3030 This firmware version is not supported on "
"this HBA model. Device:%x Magic:%x Type:%x "
-- 
2.13.1



[PATCH v2 04/13] lpfc: Enlarge nvmet asynchronous receive buffer counts

2018-04-09 Thread James Smart
Under large io load, the current sizing of asynchronous buffer counts
could be exceeded, indicated by a 2885 log message:
  2885 Port Status Event: port status reg 0x8180, port smphr
  reg 0xc000, error 1=0x52004a01, error 2=0x0

Enlarge the async receive queue size.  Allow for a configurable number
of buffers to be posted to each RQ, using the new attribute
lpfc_nvmet_mrq_post.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
Reviewed-by: Hannes Reinecke <h...@suse.com>
---
 drivers/scsi/lpfc/lpfc.h   |  1 +
 drivers/scsi/lpfc/lpfc_attr.c  | 11 +++
 drivers/scsi/lpfc/lpfc_nvmet.h |  6 --
 drivers/scsi/lpfc/lpfc_sli.c   |  2 +-
 4 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 2b47c69c1732..20b249a649dd 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -782,6 +782,7 @@ struct lpfc_hba {
uint32_t cfg_nvme_oas;
uint32_t cfg_nvme_embed_cmd;
uint32_t cfg_nvme_io_channel;
+   uint32_t cfg_nvmet_mrq_post;
uint32_t cfg_nvmet_mrq;
uint32_t cfg_enable_nvmet;
uint32_t cfg_nvme_enable_fb;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3a6b1be18886..15f921d8ea56 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3424,6 +3424,15 @@ LPFC_ATTR_R(nvmet_mrq,
"Specify number of RQ pairs for processing NVMET cmds");
 
 /*
+ * lpfc_nvmet_mrq_post: Specify number of RQ buffer to initially post
+ * to each NVMET RQ. Range 64 to 2048, default is 512.
+ */
+LPFC_ATTR_R(nvmet_mrq_post,
+   LPFC_NVMET_RQE_DEF_POST, LPFC_NVMET_RQE_MIN_POST,
+   LPFC_NVMET_RQE_DEF_COUNT,
+   "Specify number of RQ buffers to initially post");
+
+/*
  * lpfc_enable_fc4_type: Defines what FC4 types are supported.
  * Supported Values:  1 - register just FCP
  *3 - register both FCP and NVME
@@ -5353,6 +5362,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_lpfc_suppress_rsp,
_attr_lpfc_nvme_io_channel,
_attr_lpfc_nvmet_mrq,
+   _attr_lpfc_nvmet_mrq_post,
_attr_lpfc_nvme_enable_fb,
_attr_lpfc_nvmet_fb_size,
_attr_lpfc_enable_bg,
@@ -6403,6 +6413,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
 
lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type);
lpfc_nvmet_mrq_init(phba, lpfc_nvmet_mrq);
+   lpfc_nvmet_mrq_post_init(phba, lpfc_nvmet_mrq_post);
 
/* Initialize first burst. Target vs Initiator are different. */
lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h
index c1bcef3f103c..81f520abfd64 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.h
+++ b/drivers/scsi/lpfc/lpfc_nvmet.h
@@ -22,8 +22,10 @@
  /
 
 #define LPFC_NVMET_DEFAULT_SEGS(64 + 1)/* 256K IOs */
-#define LPFC_NVMET_RQE_DEF_COUNT   512
-#define LPFC_NVMET_SUCCESS_LEN 12
+#define LPFC_NVMET_RQE_MIN_POST128
+#define LPFC_NVMET_RQE_DEF_POST512
+#define LPFC_NVMET_RQE_DEF_COUNT   2048
+#define LPFC_NVMET_SUCCESS_LEN 12
 
 #define LPFC_NVMET_MRQ_OFF 0x
 #define LPFC_NVMET_MRQ_AUTO0
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index cb17e2b2be81..e0a8c8008195 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -7199,7 +7199,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
lpfc_post_rq_buffer(
phba, phba->sli4_hba.nvmet_mrq_hdr[i],
phba->sli4_hba.nvmet_mrq_data[i],
-   LPFC_NVMET_RQE_DEF_COUNT, i);
+   phba->cfg_nvmet_mrq_post, i);
}
}
 
-- 
2.13.1



[PATCH v2 13/13] lpfc: update driver version to 12.0.0.2

2018-04-09 Thread James Smart
Update the driver version to 12.0.0.2

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
Reviewed-by: Hannes Reinecke <h...@suse.com>
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index e8b089abbfb3..0cd474bb0bdd 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "12.0.0.1"
+#define LPFC_DRIVER_VERSION "12.0.0.2"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH v2 08/13] lpfc: Fix WQ/CQ creation for older asic's.

2018-04-09 Thread James Smart
The patch to enlarge WQ/CQ creation keys off of an adapter
response that indicates support for the larger values. Older
adapters return an incorrect response and are limited in size.
Thus the adapters fail the WQ creation steps.

Augment the WQ sizing checks with a check on the older adapter
types and limit them to the restricted sizes.

Fixes: c176ffa0841c ("scsi: lpfc: Increase CQ and WQ sizes for SCSI")
Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
Reviewed-by: Hannes Reinecke <h...@suse.com>
---
 drivers/scsi/lpfc/lpfc_hw4.h  | 12 
 drivers/scsi/lpfc/lpfc_init.c | 15 +++
 drivers/scsi/lpfc/lpfc_sli4.h |  1 +
 3 files changed, 28 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 98b80559c215..9df1c8da6f52 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -104,6 +104,17 @@ struct lpfc_sli_intf {
 #define LPFC_SLI_INTF_IF_TYPE_VIRT 1
 };
 
+struct lpfc_sli_asic_rev {
+   u32 word0;
+#define LPFC_SLI_ASIC_VER_A0x0
+#define LPFC_SLI_ASIC_VER_B0x1
+#define LPFC_SLI_ASIC_VER_C0x2
+#define LPFC_SLI_ASIC_VER_D0x3
+#define lpfc_sli_asic_ver_SHIFT4
+#define lpfc_sli_asic_ver_MASK 0x000F
+#define lpfc_sli_asic_ver_WORD word0
+};
+
 #define LPFC_SLI4_MBX_EMBEDtrue
 #define LPFC_SLI4_MBX_NEMBED   false
 
@@ -566,6 +577,7 @@ struct lpfc_register {
 
 /* The following BAR0 register sets are defined for if_type 0 and 2 UCNAs. */
 #define LPFC_SLI_INTF  0x0058
+#define LPFC_SLI_ASIC_VER  0x009C
 
 #define LPFC_CTL_PORT_SEM_OFFSET   0x400
 #define lpfc_port_smphr_perr_SHIFT 31
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 8dac676a46db..060f0e2f6ff5 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9514,6 +9514,11 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
return error;
}
 
+   if (pci_read_config_dword(pdev, LPFC_SLI_ASIC_VER,
+ >sli4_hba.sli_asic_ver.word0)) {
+   return error;
+   }
+
/* There is no SLI3 failback for SLI4 devices. */
if (bf_get(lpfc_sli_intf_valid, >sli4_hba.sli_intf) !=
LPFC_SLI_INTF_VALID) {
@@ -10545,6 +10550,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
struct lpfc_pc_sli4_params *sli4_params;
uint32_t mbox_tmo;
int length;
+   bool exp_wqcq_pages = true;
struct lpfc_sli4_parameters *mbx_sli4_parameters;
 
/*
@@ -10671,8 +10677,17 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
phba->nvme_support, phba->nvme_embed_pbde,
phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
 
+   if ((bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) ==
+   LPFC_SLI_INTF_IF_TYPE_2) &&
+   (bf_get(lpfc_sli_intf_sli_family, >sli4_hba.sli_intf) ==
+LPFC_SLI_INTF_FAMILY_LNCR_A0) &&
+   (bf_get(lpfc_sli_asic_ver, >sli4_hba.sli_asic_ver) ==
+   LPFC_SLI_ASIC_VER_A))
+   exp_wqcq_pages = false;
+
if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
(bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) &&
+   exp_wqcq_pages &&
(sli4_params->wqsize & LPFC_WQ_SZ128_SUPPORT))
phba->enab_exp_wqcq_pages = 1;
else
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index cf64aca82bd0..179e870a00b4 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -592,6 +592,7 @@ struct lpfc_sli4_hba {
uint32_t ue_to_sr;
uint32_t ue_to_rp;
struct lpfc_register sli_intf;
+   struct lpfc_register sli_asic_ver;
struct lpfc_pc_sli4_params pc_sli4_params;
struct lpfc_bbscn_params bbscn_params;
struct lpfc_hba_eq_hdl *hba_eq_hdl; /* HBA per-WQ handle */
-- 
2.13.1



[PATCH v2 10/13] lpfc: Fix nvme remoteport registration race conditions

2018-04-09 Thread James Smart
On tests adding and removing a remote port, calls to nvme_info would
eventually show fewer target ports discovered than were present in
the san. Additionally, the following error messages were seen:
  6031 RemotePort Registration failed err: -116, DID x471301

There is a race condition that exists between the driver and the nvme
transport on remote port unregister vs the confirmed deletion. It's
possible that the driver may rediscover the remote port and reregister
the remote port before a prior unregister delete callback was made
(as it rebinded to the prior remoteport structure). However, the
driver was coded to expect the callback before seeing the remote
port again thus a new registration. The logic results in the driver
having an invalid remoteport pointer set.

Correct by tracking when waiting for the delete callback. In cases
where the ndlp remoteport pointer is updated, it is only cleared
when the wait has not been superceded by a prior registration.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
Reviewed-by: Hannes Reinecke <h...@suse.com>
---
 drivers/scsi/lpfc/lpfc_nvme.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 22962b08c275..a0257478b63c 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -334,8 +334,14 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port 
*remoteport)
"6146 remoteport delete of remoteport %p\n",
remoteport);
spin_lock_irq(>phba->hbalock);
-   ndlp->nrport = NULL;
-   ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG;
+
+   /* The register rebind might have occurred before the delete
+* downcall.  Guard against this race.
+*/
+   if (ndlp->upcall_flags & NLP_WAIT_FOR_UNREG) {
+   ndlp->nrport = NULL;
+   ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG;
+   }
spin_unlock_irq(>phba->hbalock);
 
/* Remove original register reference. The host transport
@@ -2691,6 +2697,12 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp)
 * a resume of the existing rport.  Else this is a
 * new rport.
 */
+   /* Guard against an unregister/reregister
+* race that leaves the WAIT flag set.
+*/
+   spin_lock_irq(>phba->hbalock);
+   ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG;
+   spin_unlock_irq(>phba->hbalock);
rport = remote_port->private;
if (oldrport) {
if (oldrport == remote_port->private) {
-- 
2.13.1



[PATCH v2 06/13] lpfc: Fix lingering lpfc_wq resource after driver unload

2018-04-09 Thread James Smart
After driver unloads lpfc_wq remains active. The destroy_workqueue
calls were not being made in driver unload.  Additionally, SLI3 is
allocating lpfc_wq resources, but never uses it.

Make the destroy_workqueue calls on driver unload.
Modify the SLI3 code path no longer allocate lpfc_wq resources.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
Reviewed-by: Hannes Reinecke <h...@suse.com>
---
 drivers/scsi/lpfc/lpfc_init.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4add398ec9cf..8dac676a46db 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -6420,8 +6420,11 @@ lpfc_setup_driver_resource_phase2(struct lpfc_hba *phba)
return error;
}
 
-   /* workqueue for deferred irq use */
-   phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0);
+   /* The lpfc_wq workqueue for deferred irq use, is only used for SLI4 */
+   if (phba->sli_rev == LPFC_SLI_REV4)
+   phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0);
+   else
+   phba->wq = NULL;
 
return 0;
 }
@@ -6444,7 +6447,8 @@ lpfc_unset_driver_resource_phase2(struct lpfc_hba *phba)
}
 
/* Stop kernel worker thread */
-   kthread_stop(phba->worker_thread);
+   if (phba->worker_thread)
+   kthread_stop(phba->worker_thread);
 }
 
 /**
@@ -11727,6 +11731,7 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
lpfc_nvme_free(phba);
lpfc_free_iocb_list(phba);
 
+   lpfc_unset_driver_resource_phase2(phba);
lpfc_sli4_driver_resource_unset(phba);
 
/* Unmap adapter Control and Doorbell registers */
-- 
2.13.1



  1   2   3   4   5   6   7   8   9   10   >