[PATCH 03/15] lpfc: refactor mailbox structure context fields
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
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
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.
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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.
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.
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
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
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
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)
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
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.
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
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