lpfc: Update lpfc to revision 14.0.0.2
Subsystems (3)
cover lpfc: Update lpfc to revision 14.0.0.2
Update lpfc to revision 14.0.0.2
This patch provides a number of fixes to discovery scenarios and tweaks to the recent congestion mgmt framework.
It also provides a significant eeh patch as well.
The patches were cut against Martin's 5.15/scsi-queue tree
James Smart (14):
lpfc: Fix list_add corruption in lpfc_drain_txq
lpfc: Don't release final kref on Fport node while ABTS outstanding
lpfc: Fix premature rpi release for unsolicited TPLS and LS_RJT
lpfc: Fix hang on unload due to stuck fport node
lpfc: Fix rediscovery of tape device after issue lip
lpfc: Don't remove ndlp on PRLI errors in P2P mode
lpfc: Fix NVME I/O failover to non-optimized path
lpfc: Fix FCP I/O flush functionality for TMF routines
lpfc: Fix EEH support for NVME I/O
lpfc: Adjust bytes received vales during cmf timer interval
lpfc: Fix I/O block after enabling managed congestion mode
lpfc: Zero CGN stats only during initial driver load and stat reset
lpfc: Improve PBDE checks during SGL processing
lpfc: Update lpfc version to 14.0.0.2
drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 41 +++++++-- drivers/scsi/lpfc/lpfc_hbadisc.c | 32 +++++-- drivers/scsi/lpfc/lpfc_init.c | 49 +++++++++-- drivers/scsi/lpfc/lpfc_nvme.c | 70 +++++++++++++--- drivers/scsi/lpfc/lpfc_nvmet.c | 44 +++++----- drivers/scsi/lpfc/lpfc_scsi.c | 92 ++++++++++++-------- drivers/scsi/lpfc/lpfc_sli.c | 139 +++++++++++++++++++++++++------ drivers/scsi/lpfc/lpfc_sli4.h | 2 + drivers/scsi/lpfc/lpfc_version.h | 2 +- 10 files changed, 353 insertions(+), 119 deletions(-)
Signature · 1 line
2.26.2
PATCH 1/14 lpfc: Fix list_add corruption in lpfc_drain_txq
When parsing the txq list in lpfc_drain_txq, the driver attempts to pass the requests to the adapter. If such an attempt fails, a local "fail_msg" string is set and a log message output. The job is then added to a completions list for cancellation.
Processing of any further jobs from the txq list continues, but since "fail_msg" remains set, jobs are added to the completions list regardless of whether a wqe was passed to the adapter. If successfully added to txcmplq, jobs are added to both lists resulting in list corruption.
Fix by clearing the fail_msg string after adding a job to the completions list. This stops the subsequent jobs from being added to the completions list unless they had an appropriate failure.
--- drivers/scsi/lpfc/lpfc_sli.c | 1 + 1 file changed, 1 insertion(+)
drivers/scsi/lpfc/lpfc_sli.c +1 -0
@@ -21104,6 +21104,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) fail_msg, piocbq->iotag, piocbq->sli4_xritag);list_add_tail (&piocbq->list, &completions); + fail_msg =NULL ; }spin_unlock_irqrestore (&pring->ring_lock, iflags); }
Signature · 1 line
2.26.2
PATCH 2/14 lpfc: Don't release final kref on Fport node while ABTS outstanding
In reply to James SmartIn a rarely executed path, FLOGI failure, there is a refcounting error. If FLOGI completed with an error, typically a timeout, the initial completion handler would remove the job reference. However, the job completion isn't the actual end of the job/exchange as the timeout usually initiates an ABTS, and upon that ABTS completion, a final completion is sent. The driver removes the reference again in the final completion. Thus the imbalance.
In the buggy cases, if there was a link bounce while the delayed response is outstanding, the fport node may be referenced again but there was no additional reference as it is already present. The delayed completion then occurs and removes the last reference freeing the node and causing issues in the link up processed that is using the node.
Fix this scenario by removing the snippet that removed the reference in the initial flogi completion. The bad snippet was poorly trying to identify the flogi as ok to do so by realizing the node was not registered with either SCSI or NVME transport.
--- drivers/scsi/lpfc/lpfc_els.c | 11 +++++------ drivers/scsi/lpfc/lpfc_hbadisc.c | 10 ++++++---- drivers/scsi/lpfc/lpfc_nvme.c | 5 +++-- 3 files changed, 14 insertions(+), 12 deletions(-)
drivers/scsi/lpfc/lpfc_els.c +5 -6
@@ -1059,9 +1059,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,lpfc_printf_vlog (vport,KERN_WARNING ,LOG_TRACE_EVENT ,"0150 FLOGI failure Status:x%x/x%x " -"xri x%x TMO:x%x\n" , +"xri x%x TMO:x%x refcnt %d\n" , irsp->ulpStatus, irsp->un.ulpWord[4 ], - cmdiocb->sli4_xritag, irsp->ulpTimeout); + cmdiocb->sli4_xritag, irsp->ulpTimeout, +kref_read (&ndlp->kref));/* If this is not a loop open failure, bail out */ if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
@@ -1122,12 +1123,12 @@ 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, " -"xri x%x Data: x%x x%x x%x x%x x%x x%x x%x\n" , +"xri x%x Data: x%x x%x x%x x%x x%x x%x x%x %d\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, - sp->cmn.priority_tagging); + sp->cmn.priority_tagging,kref_read (&ndlp->kref));if (sp->cmn.priority_tagging) vport->vmid_flag |=LPFC_VMID_ISSUE_QFPA ;
@@ -1205,8 +1206,6 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, phba->fcf.fcf_flag &= ~FCF_DISCOVERY ;spin_unlock_irq (&phba->hbalock); -if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD |NVME_XPT_REGD ))) -lpfc_nlp_put (ndlp);if (!lpfc_error_lost_link (irsp)) {/* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap (vport);
drivers/scsi/lpfc/lpfc_hbadisc.c +6 -4
@@ -4449,8 +4449,9 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)fc_remote_port_rolechg (rport, rport_ids.roles);lpfc_printf_vlog (ndlp->vport,KERN_INFO ,LOG_NODE , -"3183 %s rport x%px DID x%x, role x%x\n" , - __func__, rport, rport->port_id, rport->roles); +"3183 %s rport x%px DID x%x, role x%x refcnt %d\n" , + __func__, rport, rport->port_id, rport->roles, +kref_read (&ndlp->kref));if ((rport->scsi_target_id !=-1 ) && (rport->scsi_target_id <LPFC_MAX_TARGET )) {
@@ -4475,8 +4476,9 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp)lpfc_printf_vlog (vport,KERN_INFO ,LOG_NODE ,"3184 rport unregister x%06x, rport x%px " -"xptflg x%x\n" , - ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags); +"xptflg x%x refcnt %d\n" , + ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags, +kref_read (&ndlp->kref));fc_remote_port_delete (rport);lpfc_nlp_put (ndlp);
drivers/scsi/lpfc/lpfc_nvme.c +3 -2
@@ -209,8 +209,9 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport)* calling state machine to remove the node. */ lpfc_printf_vlog (vport,KERN_INFO ,LOG_NVME_DISC , -"6146 remoteport delete of remoteport x%px\n" , - remoteport); +"6146 remoteport delete of remoteport x%px, ndlp x%px " +"DID x%x xflags x%x\n" , + remoteport, ndlp, ndlp->nlp_DID, ndlp->fc4_xpt_flags);spin_lock_irq (&ndlp->lock);/* The register rebind might have occurred before the delete
Signature · 1 line
2.26.2
PATCH 3/14 lpfc: Fix premature rpi release for unsolicited TPLS and LS_RJT
In reply to James SmartA test scenario has a target issuing a TPLS after accepting the driver's PRLI. TPLS is not supported by the driver so it rejects the ELS. However, the reject was only happening on the primary N_Port. If the TPLS was to a NPIV vport, not only would it reject the ELS, but it would act on the TPLS, starting devloss, then unregister from the SCSI transport and release the node. When devloss expired, it would access the node again and cause a page faul.
Fix by altering the NPIV code to recognize that a correctly registered node can reject unsolicited ELS IO and to not unregister with the SCSI transport and tear the node down. Add a check of the fc4_xpt_flags so that only a zero value allows the unreg and teardown.
--- drivers/scsi/lpfc/lpfc_els.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/scsi/lpfc/lpfc_els.c +5 -3
@@ -5295,6 +5295,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,*/ if (phba->sli_rev ==LPFC_SLI_REV4 && (vport && vport->port_type ==LPFC_NPIV_PORT ) && + !(ndlp->fc4_xpt_flags &SCSI_XPT_REGD ) && ndlp->nlp_flag &NLP_RELEASE_RPI ) {lpfc_sli4_free_rpi (phba, ndlp->nlp_rpi);spin_lock_irq (&ndlp->lock);
@@ -5598,11 +5599,12 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, }/* The NPIV instance is rejecting this unsolicited ELS. Make sure the -* node's assigned RPI needs to be released as this node will get -* freed. +* node's assigned RPI gets released provided this node is not already +* registered with the transport. */ if (phba->sli_rev ==LPFC_SLI_REV4 && - vport->port_type ==LPFC_NPIV_PORT ) { + vport->port_type ==LPFC_NPIV_PORT && + !(ndlp->fc4_xpt_flags &SCSI_XPT_REGD )) {spin_lock_irq (&ndlp->lock); ndlp->nlp_flag |=NLP_RELEASE_RPI ;spin_unlock_irq (&ndlp->lock);
Signature · 1 line
2.26.2
PATCH 4/14 lpfc: Fix hang on unload due to stuck fport node
In reply to James SmartA test scenario encountered an unload hang while an FLOGI ELS was in flight when a link down condition occurred. The driver fails unload as it never releases the fport node.
For most nodes, when the link drops, devloss tmo is started and the timeout will cause the final node release. For the Fport, as it has not yet registered with the SCSI transport, there is no devloss timer to be started, so there is no final release. Additionally, the link down sequence causes ABORTS to be issued for pending ELS's. The completions from the ABORTS perform the release of node references. However, as the adapter is being reset to be unloaded, those completions will never occur.
Fix by the following:
- In the els cleanup, recognize when unloading and place the els's on a different list that immediately cleansup/completes the els's. It's recognized that this condition primarily affects only the fport, with other ports having normal clean up logic that handles things.
- Resolve the devloss issue by, when cleaning up nodes on after link down, recognizing when the fabric node does not have a completed state (its state is UNUSED) and removing a reference so the node can delete after the els reference is released.
--- drivers/scsi/lpfc/lpfc_els.c | 14 ++++++++++++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 14 +++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-)
drivers/scsi/lpfc/lpfc_els.c +14 -0
@@ -11386,6 +11386,7 @@ lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport) {struct lpfc_hba *phba = vport->phba;struct lpfc_sglq *sglq_entry =NULL , *sglq_next =NULL ; +struct lpfc_nodelist *ndlp =NULL ;unsigned long iflag =0 ;spin_lock_irqsave (&phba->sli4_hba.sgl_list_lock, iflag);
@@ -11393,7 +11394,20 @@ lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport) &phba->sli4_hba.lpfc_abts_els_sgl_list, list) {if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport) {lpfc_nlp_put (sglq_entry->ndlp); + ndlp = sglq_entry->ndlp; sglq_entry->ndlp =NULL ; + +/* If the xri on the abts_els_sgl list is for the Fport +* node and the vport is unloading, the xri aborted wcqe +* likely isn't coming back. Just release the sgl. +*/ +if ((vport->load_flag &FC_UNLOADING ) && + ndlp->nlp_DID == Fabric_DID) { +list_del (&sglq_entry->list); + sglq_entry->state =SGL_FREED ; +list_add_tail (&sglq_entry->list, + &phba->sli4_hba.lpfc_els_sgl_list); + } } }spin_unlock_irqrestore (&phba->sli4_hba.sgl_list_lock, iflag);
drivers/scsi/lpfc/lpfc_hbadisc.c +13 -1
@@ -966,8 +966,20 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)struct lpfc_nodelist *ndlp, *next_ndlp;list_for_each_entry_safe (ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { -if (ndlp->nlp_state ==NLP_STE_UNUSED_NODE ) +if (ndlp->nlp_state ==NLP_STE_UNUSED_NODE ) { +/* It's possible the FLOGI to the fabric node never +* successfully completed and never registered with the +* transport. In this case there is no way to clean up +* the node. +*/ +if (ndlp->nlp_DID == Fabric_DID) { +if (ndlp->nlp_prev_state == +NLP_STE_UNUSED_NODE && + !ndlp->fc4_xpt_flags) +lpfc_nlp_put (ndlp); + }continue ; + } if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || ((vport->port_type == LPFC_NPIV_PORT) &&
Signature · 1 line
2.26.2
PATCH 5/14 lpfc: Fix rediscovery of tape device after issue lip
In reply to James SmartOn link up and node discovery, a remote port is registered with the scsi transport and the driver sets fc4_xpt_flags to track transport registration.
A link down event causes the driver to deregister with the scsi transport, starting the devloss timer, and calls a local unreg routine to clear the login state. Part of the login state is the fc4_xpt_flags. However, with TAPE devices that support sequence level error recovery, which wants to preserve the login, the local unreg routine is skipped, thus the flags aren't cleared.
A subsequent link up, ADISC is performed and the lpfc_nlp_reg_node() routine is called. As the fc4_xpt_flags is not clear, it's believed the node is already registered with the transport. Unfortunately, the registration was already terminated. Eventually the devloss tmo timer expires and tears down the device.
Fix by ensuring the tape device, known by the ADISC flag, is always unregistered if the link drops.
--- drivers/scsi/lpfc/lpfc_hbadisc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/scsi/lpfc/lpfc_hbadisc.c +5 -2
@@ -4693,8 +4693,11 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,/* Reg/Unreg for FCP and NVME Transport interface */ if ((old_state ==NLP_STE_MAPPED_NODE || old_state ==NLP_STE_UNMAPPED_NODE )) { -/* For nodes marked for ADISC, Handle unreg in ADISC cmpl */ -if (!(ndlp->nlp_flag &NLP_NPR_ADISC )) +/* For nodes marked for ADISC, Handle unreg in ADISC cmpl +* if linkup. In linkdown do unreg_node +*/ +if (!(ndlp->nlp_flag &NLP_NPR_ADISC ) || + !lpfc_is_link_up (vport->phba))lpfc_nlp_unreg_node (vport, ndlp); }
Signature · 1 line
2.26.2
PATCH 6/14 lpfc: Don't remove ndlp on PRLI errors in P2P mode
In reply to James SmartIn pt-2-pt mode, the initiator does not log into the target after a PRLI error. In pt-2-pt mode, the target responded to the PRLI by sending a LOGO. The LOGO causes all ELS and I/Os to be aborted. This caused the PRLI to fail. The PRLI completion path caused the discovery node to be dropped to avoid being stick in an UNUSED (not logged in) state. As the node was dropped there is no retry of the login and as it is pt-2-pt, there is no RSCN to retrigger discovery. Thus the other end is not seen by the os.
Fix by ensuring the discovery node is not dropped if connecting pt-2-pt. This will cause PLOGI to be retried.
--- drivers/scsi/lpfc/lpfc_els.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/scsi/lpfc/lpfc_els.c +7 -0
@@ -2329,6 +2329,13 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,lpfc_disc_state_machine (vport, ndlp, cmdiocb,NLP_EVT_CMPL_PRLI ); +/* +* For P2P topology, retain the node so that PLOGI can be +* attempted on it again. +*/ +if (vport->fc_flag &FC_PT2PT ) + goto out; +/* As long as this node is not registered with the SCSI * or NVMe transport and no other PRLIs are outstanding, * it is no longer an active node. Otherwise devloss
Signature · 1 line
2.26.2
PATCH 7/14 lpfc: Fix NVME I/O failover to non-optimized path
In reply to James SmartCurrently, we hold off unregistering with NVME transport layer until GID_FT or ADISC completes upon receipt of RSCN. In the ADISC discovery routine, for nodes not found in the GID_FT response, the nodes are unregistered from the scsi transport but not UNREG_RPI'd. Meaning outstanding WQEs continue to be outstanding and were not failed back to the OS. If an NVMe device, this mean there wasn't initial termination of the I/O's so they could be issued on a different NVME path.
Fix by unregistering the RPI so that I/O is cancelled.
--- drivers/scsi/lpfc/lpfc_els.c | 1 + 1 file changed, 1 insertion(+)
drivers/scsi/lpfc/lpfc_els.c +1 -0
@@ -6224,6 +6224,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport)* from backend */ lpfc_nlp_unreg_node (vport, ndlp); +lpfc_unreg_rpi (vport, ndlp);continue ; }
Signature · 1 line
2.26.2
PATCH 8/14 lpfc: Fix FCP I/O flush functionality for TMF routines
In reply to James SmartA prior patch inadvertently caused lpfc_sli_sum_iocb to exclude counting of outstanding aborted I/Os and ABORT iocbs. Thus, lpfc_reset_flush_io_context called from any TMF routine does not properly wait to flush all outstanding FCP iocbs leading to a block layer crash on an invalid scsi_cmnd->request pointer.
kernel BUG at ../block/blk-core.c:1489!
RIP: 0010:blk_requeue_request+0xaf/0xc0 ... Call Trace: <IRQ> __scsi_queue_insert+0x90/0xe0 [scsi_mod] blk_done_softirq+0x7e/0x90 __do_softirq+0xd2/0x280 irq_exit+0xd5/0xe0 do_IRQ+0x4c/0xd0 common_interrupt+0x87/0x87 </IRQ>
Fix by separating out the LPFC_IO_FCP, LPFC_IO_ON_TXCMPLQ, LPFC_DRIVER_ABORTED, and CMD_ABORT_XRI_CN || CMD_CLOSE_XRI_CN checks into a new lpfc_sli_validate_fcp_iocb_for_abort routine when determining to build an ABORT iocb.
Restore lpfc_reset_flush_io_context functionality by including counting of outstanding aborted iocbs and ABORT iocbs in lpfc_sli_sum_iocb.
--- drivers/scsi/lpfc/lpfc_sli.c | 101 +++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 23 deletions(-)
drivers/scsi/lpfc/lpfc_sli.c +78 -23
@@ -12485,15 +12485,54 @@ lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) }/** -* lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN +* lpfc_sli_validate_fcp_iocb_for_abort - filter iocbs appropriate for FCP aborts +* @iocbq: Pointer to iocb object. +* @vport: Pointer to driver virtual port object. +* +* This function acts as an iocb filter for functions which abort FCP iocbs. +* +* Return values +* -ENODEV, if a null iocb or vport ptr is encountered +* -EINVAL, if the iocb is not an FCP I/O, not on the TX cmpl queue, premarked as +* driver already started the abort process, or is an abort iocb itself +* 0, passes criteria for aborting the FCP I/O iocb +**/ +static int +lpfc_sli_validate_fcp_iocb_for_abort (struct lpfc_iocbq *iocbq, +struct lpfc_vport *vport) +{ +IOCB_t *icmd =NULL ; + +/* No null ptr vports */ +if (!iocbq || iocbq->vport != vport) +return -ENODEV ; + +/* iocb must be for FCP IO, already exists on the TX cmpl queue, +* can't be premarked as driver aborted, nor be an ABORT iocb itself +*/ + icmd = &iocbq->iocb; +if (!(iocbq->iocb_flag &LPFC_IO_FCP ) || + !(iocbq->iocb_flag &LPFC_IO_ON_TXCMPLQ ) || + (iocbq->iocb_flag &LPFC_DRIVER_ABORTED ) || + (icmd->ulpCommand ==CMD_ABORT_XRI_CN || + icmd->ulpCommand ==CMD_CLOSE_XRI_CN )) +return -EINVAL ; + +return 0 ; +} + +/** +* lpfc_sli_validate_fcp_iocb - validate commands associated with a SCSI target * @iocbq: Pointer to driver iocb object. * @vport: Pointer to driver virtual port object. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST * -* This function acts as an iocb filter for functions which abort or count -* all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return +* This function acts as an iocb filter for validating a lun/SCSI target/SCSI +* host. +* +* It will return * 0 if the filtering criteria is met for the given iocb and will return * 1 if the filtering criteria is not met. * If ctx_cmd == LPFC_CTX_LUN, the function returns 0 only if the
@@ -12512,22 +12551,8 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, lpfc_ctx_cmd ctx_cmd) {struct lpfc_io_buf *lpfc_cmd; -IOCB_t *icmd =NULL ;int rc =1 ; -if (!iocbq || iocbq->vport != vport) -return rc; - -if (!(iocbq->iocb_flag &LPFC_IO_FCP ) || - !(iocbq->iocb_flag &LPFC_IO_ON_TXCMPLQ ) || - iocbq->iocb_flag &LPFC_DRIVER_ABORTED ) -return rc; - - icmd = &iocbq->iocb; -if (icmd->ulpCommand ==CMD_ABORT_XRI_CN || - icmd->ulpCommand ==CMD_CLOSE_XRI_CN ) -return rc; - lpfc_cmd = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);if (lpfc_cmd->pCmd ==NULL )
@@ -12582,17 +12607,33 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, {struct lpfc_hba *phba = vport->phba;struct lpfc_iocbq *iocbq; +IOCB_t *icmd =NULL ;int sum, i; +unsigned long iflags; -spin_lock_irq (&phba->hbalock); +spin_lock_irqsave (&phba->hbalock, iflags);for (i =1 , sum =0 ; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; -if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, - ctx_cmd) ==0 ) +if (!iocbq || iocbq->vport != vport) +continue ; +if (!(iocbq->iocb_flag &LPFC_IO_FCP ) || + !(iocbq->iocb_flag &LPFC_IO_ON_TXCMPLQ )) +continue ; + +/* Include counting outstanding aborts */ + icmd = &iocbq->iocb; +if (icmd->ulpCommand ==CMD_ABORT_XRI_CN || + icmd->ulpCommand ==CMD_CLOSE_XRI_CN ) { + sum++; +continue ; + } + +if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, + ctx_cmd) ==0 ) sum++; } -spin_unlock_irq (&phba->hbalock); +spin_unlock_irqrestore (&phba->hbalock, iflags);return sum; }
@@ -12659,7 +12700,11 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,* * This function sends an abort command for every SCSI command * associated with the given virtual port pending on the ring -* filtered by lpfc_sli_validate_fcp_iocb function. +* filtered by lpfc_sli_validate_fcp_iocb_for_abort and then +* lpfc_sli_validate_fcp_iocb function. The ordering for validation before +* submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort +* followed by lpfc_sli_validate_fcp_iocb. +* * When abort_cmd == LPFC_CTX_LUN, the function sends abort only to the * FCP iocbs associated with lun specified by tgt_id and lun_id * parameters
@@ -12691,6 +12736,9 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id,for (i =1 ; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; +if (lpfc_sli_validate_fcp_iocb_for_abort (iocbq, vport)) +continue ; +if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, abort_cmd) !=0 )continue ;
@@ -12723,7 +12771,11 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id,* * This function sends an abort command for every SCSI command * associated with the given virtual port pending on the ring -* filtered by lpfc_sli_validate_fcp_iocb function. +* filtered by lpfc_sli_validate_fcp_iocb_for_abort and then +* lpfc_sli_validate_fcp_iocb function. The ordering for validation before +* submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort +* followed by lpfc_sli_validate_fcp_iocb. +* * When taskmgmt_cmd == LPFC_CTX_LUN, the function sends abort only to the * FCP iocbs associated with lun specified by tgt_id and lun_id * parameters
@@ -12761,6 +12813,9 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,for (i =1 ; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; +if (lpfc_sli_validate_fcp_iocb_for_abort (iocbq, vport)) +continue ; +if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, cmd) !=0 )continue ;
Signature · 1 line
2.26.2
PATCH 9/14 lpfc: Fix EEH support for NVME I/O
In reply to James SmartInjecting errors on the pci-slot while the driver is handling nvme io will cause crashes and hangs.
There are several rather difficult scenarios occurring. The main issue is that the adapter can report a pci error before or simultaneously to the pci subsystem reporting the error. Both paths have different entry points and currently, there is no interlock between them. Thus multiple teardown paths are competing and all heck breaks loose.
Complicating things is the nvme path. To a large degree, i/o was able to be shutdown for a full FC port on the scsi stack. But on NVMe, there isn't a similar call. At best, it works on a per-controller basis, but even at the controller level, it's a controller "reset" call. All of which means i/o is still flowing on different cpus with reset paths expecting hw access (mailbox commands) to execute properly.
The following modifications are made in this patch:
- A new flag is set in PCI error entrypoints so the driver can track being called by that path.
- A interlock is added in the sli hw error path and the pci error path such that only one of the paths proceeds with the teardown logic.
- RPI cleanup is patched such that rpis are marked unregistered w/o mbx cmds in cases of hw error.
- If entering the sli port re-init calls, a case where sli error teardown was quick and beat the pci calls now reporting error, check whether the sli port is still live on the pci bus before
- in the pci reset code to bring the adapter back, recheck the irq settings. Different checks for sli3 vs sli4.
- in i/o completions, that may be called as part of the cleanup or underway just before the hw error, check the state of the adapter. If in error, short cut handling that would expect further adapter completions as the hw error won't be sending them.
- in routines waiting on i/o completions, which may have been in progress prior to the hw error, detect the device is being torn down and abort from their waits and just give up. This points to a larger issue in the driver on ref-counting for data structures, as it doesn't have ref-counting on q and port structures. We'll do this fix for now as it would be a major rework to be done differently.
- fix the nvme cleanup to simulate nvme i/o completions if i/o is being failed back due to hw error.
- in io buf allocation, done at the start of new ios, check hw state and fail if hw error.
--- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 1 + drivers/scsi/lpfc/lpfc_init.c | 31 +++++++++++++++- drivers/scsi/lpfc/lpfc_nvme.c | 53 ++++++++++++++++++++++++++- drivers/scsi/lpfc/lpfc_scsi.c | 63 +++++++++++++++++++++----------- drivers/scsi/lpfc/lpfc_sli.c | 31 +++++++++++++++- drivers/scsi/lpfc/lpfc_sli4.h | 2 + 7 files changed, 154 insertions(+), 28 deletions(-)
drivers/scsi/lpfc/lpfc.h +1 -0
@@ -1028,6 +1028,7 @@ struct lpfc_hba {* Firmware supports Forced Link Speed * capability */ +#define HBA_PCI_ERR 0x80000/* The PCI slot is offline */ #define HBA_FLOGI_ISSUED 0x100000/* FLOGI was issued */ #define HBA_CGN_RSVD1 0x200000/* Reserved CGN flag */ #define HBA_CGN_DAY_WRAP 0x400000/* HBA Congestion info day wraps */
drivers/scsi/lpfc/lpfc_hbadisc.c +1 -0
@@ -5250,6 +5250,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) rc =lpfc_sli_issue_mbox (phba, mbox,MBX_NOWAIT );if (rc ==MBX_NOT_FINISHED ) { + ndlp->nlp_flag &= ~NLP_UNREG_INP ;mempool_free (mbox, phba->mbox_mem_pool); acc_plogi =1 ; }
drivers/scsi/lpfc/lpfc_init.c +29 -2
@@ -1606,6 +1606,11 @@ void lpfc_sli4_offline_eratt(struct lpfc_hba *phba) {spin_lock_irq (&phba->hbalock); +if (phba->link_state ==LPFC_HBA_ERROR && + phba->hba_flag &HBA_PCI_ERR ) { +spin_unlock_irq (&phba->hbalock); +return ; + } phba->link_state =LPFC_HBA_ERROR ;spin_unlock_irq (&phba->hbalock);
@@ -1945,7 +1950,6 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)if (pci_channel_offline (phba->pcidev)) {lpfc_printf_log (phba,KERN_ERR ,LOG_TRACE_EVENT ,"3166 pci channel is offline\n" ); -lpfc_sli4_offline_eratt (phba);return ; }
@@ -3643,6 +3647,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)struct lpfc_vport **vports;struct Scsi_Host *shost;int i; +int offline =0 ;if (vport->fc_flag &FC_OFFLINE_MODE )return ;
@@ -3651,6 +3656,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)lpfc_linkdown (phba); + offline =pci_channel_offline (phba->pcidev); +/* Issue an unreg_login to all nodes on all vports */ vports =lpfc_create_vport_work_array (phba);if (vports !=NULL ) {
@@ -3673,7 +3680,14 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) ndlp->nlp_flag &= ~NLP_NPR_ADISC ;spin_unlock_irq (&ndlp->lock); -lpfc_unreg_rpi (vports[i], ndlp); +if (offline) { +spin_lock_irq (&ndlp->lock); + ndlp->nlp_flag &= ~(NLP_UNREG_INP | +NLP_RPI_REGISTERED ); +spin_unlock_irq (&ndlp->lock); + }else { +lpfc_unreg_rpi (vports[i], ndlp); + }/* * Whenever an SLI4 port goes offline, free the * RPI. Get a new RPI when the adapter port
@@ -14080,6 +14094,10 @@ lpfc_pci_resume_one_s3(struct device *dev_d)return error; } +/* Init cpu_map array */ +lpfc_cpu_map_array_init (phba); +/* Init hba_eq_hdl array */ +lpfc_hba_eq_hdl_array_init (phba);/* Configure and enable interrupt */ intr_mode =lpfc_sli_enable_intr (phba, phba->intr_mode);if (intr_mode ==LPFC_INTR_ERROR ) {
@@ -15032,14 +15050,17 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)lpfc_sli4_prep_dev_for_recover (phba);return PCI_ERS_RESULT_CAN_RECOVER ;case pci_channel_io_frozen: + phba->hba_flag |=HBA_PCI_ERR ;/* Fatal error, prepare for slot reset */ lpfc_sli4_prep_dev_for_reset (phba);return PCI_ERS_RESULT_NEED_RESET ;case pci_channel_io_perm_failure: + phba->hba_flag |=HBA_PCI_ERR ;/* Permanent failure, prepare for device down */ lpfc_sli4_prep_dev_for_perm_failure (phba);return PCI_ERS_RESULT_DISCONNECT ;default : + phba->hba_flag |=HBA_PCI_ERR ;/* Unknown state, prepare and request slot reset */ lpfc_printf_log (phba,KERN_ERR ,LOG_TRACE_EVENT ,"2825 Unknown PCI error state: x%x\n" , state);
@@ -15083,6 +15104,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)pci_restore_state (pdev); + phba->hba_flag &= ~HBA_PCI_ERR ;/* * As the new kernel behavior of pci_restore_state() API call clears * device saved_state flag, need to save the restored state again.
@@ -15105,6 +15127,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)return PCI_ERS_RESULT_DISCONNECT ; }else phba->intr_mode = intr_mode; +lpfc_cpu_affinity_check (phba, phba->cfg_irq_chann);/* Log the current active interrupt mode */ lpfc_log_intr_mode (phba, phba->intr_mode);
@@ -15306,6 +15329,10 @@ lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;pci_ers_result_t rc =PCI_ERS_RESULT_DISCONNECT ; +if (phba->link_state ==LPFC_HBA_ERROR && + phba->hba_flag &HBA_IOQ_FLUSH ) +return PCI_ERS_RESULT_NEED_RESET ; +switch (phba->pci_dev_grp) {case LPFC_PCI_DEV_LP : rc =lpfc_io_error_detected_s3 (pdev, state);
drivers/scsi/lpfc/lpfc_nvme.c +51 -2
99 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_scsi.c +41 -22
110 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_sli.c +29 -2
@@ -1404,7 +1404,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) }if ((iocbq->iocb_flag &LPFC_EXCHANGE_BUSY ) && - (sglq->state !=SGL_XRI_ABORTED )) { + (!(unlikely (pci_channel_offline (phba->pcidev)))) && + sglq->state !=SGL_XRI_ABORTED ) {spin_lock_irqsave (&phba->sli4_hba.sgl_list_lock, iflag);
@@ -4583,10 +4584,12 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)lpfc_sli_cancel_iocbs (phba, &txq,IOSTAT_LOCAL_REJECT ,IOERR_SLI_DOWN ); -/* Flush the txcmpq */ +/* Flush the txcmplq */ lpfc_sli_cancel_iocbs (phba, &txcmplq,IOSTAT_LOCAL_REJECT ,IOERR_SLI_DOWN ); +if (unlikely (pci_channel_offline (phba->pcidev))) +lpfc_sli4_io_xri_aborted (phba,NULL ,0 ); } }else { pring = &psli->sli3_ring[LPFC_FCP_RING ];
@@ -22019,8 +22022,26 @@ lpfc_get_io_buf_from_multixri_pools(struct lpfc_hba *phba, qp = &phba->sli4_hba.hdwq[hwqid]; lpfc_ncmd =NULL ; +if (!qp) { +lpfc_printf_log (phba,KERN_INFO , +LOG_SLI |LOG_NVME_ABTS |LOG_FCP , +"5556 NULL qp for hwqid x%x\n" , hwqid); +return lpfc_ncmd; + } multixri_pool = qp->p_multixri_pool; +if (!multixri_pool) { +lpfc_printf_log (phba,KERN_INFO , +LOG_SLI |LOG_NVME_ABTS |LOG_FCP , +"5557 NULL multixri for hwqid x%x\n" , hwqid); +return lpfc_ncmd; + } pvt_pool = &multixri_pool->pvt_pool; +if (!pvt_pool) { +lpfc_printf_log (phba,KERN_INFO , +LOG_SLI |LOG_NVME_ABTS |LOG_FCP , +"5558 NULL pvt_pool for hwqid x%x\n" , hwqid); +return lpfc_ncmd; + } multixri_pool->io_req_count++;/* If pvt_pool is empty, move some XRIs from public to private pool */
@@ -22096,6 +22117,12 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba, qp = &phba->sli4_hba.hdwq[hwqid]; lpfc_cmd =NULL ; +if (!qp) { +lpfc_printf_log (phba,KERN_WARNING , +LOG_SLI |LOG_NVME_ABTS |LOG_FCP , +"5555 NULL qp for hwqid x%x\n" , hwqid); +return lpfc_cmd; + }if (phba->cfg_xri_rebalancing) lpfc_cmd = lpfc_get_io_buf_from_multixri_pools(
drivers/scsi/lpfc/lpfc_sli4.h +2 -0
@@ -1116,6 +1116,8 @@ void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);int lpfc_sli4_resume_rpi (struct lpfc_nodelist *,void (*)(struct lpfc_hba *,LPFC_MBOXQ_t *),void *);void lpfc_sli4_els_xri_abort_event_proc (struct lpfc_hba *phba); +void lpfc_sli4_nvme_pci_offline_aborted (struct lpfc_hba *phba, +struct lpfc_io_buf *lpfc_ncmd);void lpfc_sli4_nvme_xri_aborted (struct lpfc_hba *phba,struct sli4_wcqe_xri_aborted *axri,struct lpfc_io_buf *lpfc_ncmd);
Signature · 1 line
2.26.2
PATCH 10/14 lpfc: Adjust bytes received vales during cmf timer interval
In reply to James SmartThe newly added congestion mgmt framework is seeing unexpected congestion FPINs and signals. In analysis, time values given to the adapter are not at hard time intervals. Thus the drift vs the transfer count seen is affecting how the framework manages things.
Adjust counters to cover the drift.
--- drivers/scsi/lpfc/lpfc_init.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/scsi/lpfc/lpfc_init.c +14 -2
@@ -5876,7 +5876,7 @@ lpfc_cmf_timer(struct hrtimer *timer)uint32_t io_cnt;uint32_t head, tail;uint32_t busy, max_read; -uint64_t total, rcv, lat, mbpi; +uint64_t total, rcv, lat, mbpi, extra;int timer_interval =LPFC_CMF_INTERVAL ;uint32_t ms;struct lpfc_cgn_stat *cgs;
@@ -5943,7 +5943,19 @@ lpfc_cmf_timer(struct hrtimer *timer) phba->hba_flag & HBA_SETUP) { mbpi = phba->cmf_last_sync_bw; phba->cmf_last_sync_bw =0 ; - lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total); + extra =0 ; + +/* Calculate any extra bytes needed to account for the +* timer accuracy. If we are less than LPFC_CMF_INTERVAL +* add an extra 3% slop factor, equal to LPFC_CMF_INTERVAL +* add an extra 2%. The goal is to equalize total with a +* time > LPFC_CMF_INTERVAL or <= LPFC_CMF_INTERVAL + 1 +*/ +if (ms ==LPFC_CMF_INTERVAL ) + extra =div_u64 (total,50 ); +else if (ms <LPFC_CMF_INTERVAL ) + extra =div_u64 (total,33 ); +lpfc_issue_cmf_sync_wqe (phba,LPFC_CMF_INTERVAL , total + extra); } else {/* For Monitor mode or link down we want mbpi * to be the full link speed
Signature · 1 line
2.26.2
PATCH 11/14 lpfc: Fix I/O block after enabling managed congestion mode
In reply to James SmartIf the congestion management framework dynamically enables, it may do so while I/O is in flight. The updates of cmf info due to inflight I/O completing may happen before values have been initialized.
Fix by ensure cmf_max_bytes_per_interval is initialized when checking bandwidth utilization for SCSI layer blocking.
--- drivers/scsi/lpfc/lpfc_scsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/lpfc/lpfc_scsi.c +2 -1
@@ -3961,7 +3961,8 @@ lpfc_update_cmf_cmd(struct lpfc_hba *phba, uint32_t size)int cpu;/* At this point we are either LPFC_CFG_MANAGED or LPFC_CFG_MONITOR */ -if (phba->cmf_active_mode ==LPFC_CFG_MANAGED ) { +if (phba->cmf_active_mode ==LPFC_CFG_MANAGED && + phba->cmf_max_bytes_per_interval) { total =0 ;for_each_present_cpu (cpu) { cgs =per_cpu_ptr (phba->cmf_stat, cpu);
Signature · 1 line
2.26.2
PATCH 12/14 lpfc: Zero CGN stats only during initial driver load and stat reset
In reply to James SmartCurrently congestion management framework results are cleared whenever the framework settings changed (such as it being turned off then back on). This unfortunately means prior stats, rolled up to higher time windows lose meaning.
Change such that stats are not cleared. Thus they pause and resume with prior values still being considered.
--- drivers/scsi/lpfc/lpfc_init.c | 2 -- drivers/scsi/lpfc/lpfc_sli.c | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/scsi/lpfc/lpfc_init.c +0 -2
@@ -13394,8 +13394,6 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba)atomic_set (&phba->cgn_sync_alarm_cnt,0 );atomic_set (&phba->cgn_sync_warn_cnt,0 ); -atomic64_set (&phba->cgn_acqe_stat.alarm,0 ); -atomic64_set (&phba->cgn_acqe_stat.warn,0 );atomic_set (&phba->cgn_driver_evt_cnt,0 );atomic_set (&phba->cgn_latency_evt_cnt,0 );atomic64_set (&phba->cgn_latency_evt,0 );
drivers/scsi/lpfc/lpfc_sli.c +4 -2
@@ -7764,8 +7764,6 @@ lpfc_mbx_cmpl_cgn_set_ftrs(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)/* Zero out Congestion Signal ACQE counter */ phba->cgn_acqe_cnt =0 ; -atomic64_set (&phba->cgn_acqe_stat.warn,0 ); -atomic64_set (&phba->cgn_acqe_stat.alarm,0 ); acqe =bf_get (lpfc_mbx_set_feature_CGN_acqe_freq, &pmb->u.mqe.un.set_feature);
@@ -8017,6 +8015,10 @@ lpfc_cmf_setup(struct lpfc_hba *phba)/* initialize congestion buffer info */ lpfc_init_congestion_buf (phba);lpfc_init_congestion_stat (phba); + +/* Zero out Congestion Signal counters */ +atomic64_set (&phba->cgn_acqe_stat.alarm,0 ); +atomic64_set (&phba->cgn_acqe_stat.warn,0 ); } rc =lpfc_sli4_cgn_params_read (phba);
Signature · 1 line
2.26.2
PATCH 13/14 lpfc: Improve PBDE checks during SGL processing
In reply to James SmartThe PBDE feature, setting payload buffer address explicitly in the WQE so it doesn't have to be fetched from the SGL, only makes sense when there is a single buffer for the I/O. When there are multiple buffers it actually hurts performance as the SGL subsequently has to be fetched.
Rework the SGL logic to only use PBDE when a single buffer.
--- drivers/scsi/lpfc/lpfc_nvme.c | 12 +++++----- drivers/scsi/lpfc/lpfc_nvmet.c | 44 ++++++++++++++++------------------ drivers/scsi/lpfc/lpfc_scsi.c | 26 ++++++++++---------- 3 files changed, 40 insertions(+), 42 deletions(-)
drivers/scsi/lpfc/lpfc_nvme.c +6 -6
@@ -1299,7 +1299,6 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,struct sli4_sge *first_data_sgl;struct ulp_bde64 *bde;dma_addr_t physaddr =0 ; -uint32_t num_bde =0 ;uint32_t dma_len =0 ;uint32_t dma_offset =0 ;int nseg, i, j;
@@ -1353,7 +1352,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, } sgl->word2 =0 ; -if ((num_bde +1 ) == nseg) { +if (nseg ==1 ) {bf_set (lpfc_sli4_sge_last, sgl,1 );bf_set (lpfc_sli4_sge_type, sgl,LPFC_SGE_TYPE_DATA );
@@ -1422,8 +1421,9 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, j++; } -if (phba->cfg_enable_pbde) { -/* Use PBDE support for first SGL only, offset == 0 */ + +/* PBDE support for first data SGE only */ +if (nseg ==1 && phba->cfg_enable_pbde) {/* Words 13-15 */ bde = (struct ulp_bde64 *) &wqe->words[13 ];
@@ -1434,11 +1434,11 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, bde->tus.f.bdeFlags =BUFF_TYPE_BDE_64 ; bde->tus.w =cpu_to_le32 (bde->tus.w); -/* Word 11 */ +/* Word 11 - set PBDE bit */ bf_set (wqe_pbde, &wqe->generic.wqe_com,1 ); }else {memset (&wqe->words[13 ],0 , (sizeof (uint32_t ) *3 )); -bf_set (wqe_pbde, &wqe->generic.wqe_com,0 ); +/* Word 11 - PBDE bit disabled by default template */ } }else {
drivers/scsi/lpfc/lpfc_nvmet.c +21 -23
79 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_scsi.c +13 -13
@@ -3235,7 +3235,6 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)struct lpfc_vport *vport = phba->pport;union lpfc_wqe128 *wqe = &pwqeq->wqe;dma_addr_t physaddr; -uint32_t num_bde =0 ;uint32_t dma_len;uint32_t dma_offset =0 ;int nseg, i, j;
@@ -3297,7 +3296,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) j =2 ;for (i =0 ; i < nseg; i++) { sgl->word2 =0 ; -if ((num_bde +1 ) == nseg) { +if (nseg ==1 ) {bf_set (lpfc_sli4_sge_last, sgl,1 );bf_set (lpfc_sli4_sge_type, sgl,LPFC_SGE_TYPE_DATA );
@@ -3366,13 +3365,15 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) j++; } -/* -* Setup the first Payload BDE. For FCoE we just key off -* Performance Hints, for FC we use lpfc_enable_pbde. -* We populate words 13-15 of IOCB/WQE. + +/* PBDE support for first data SGE only. +* For FCoE, we key off Performance Hints. +* For FC, we key off lpfc_enable_pbde. */ -if ((phba->sli3_options &LPFC_SLI4_PERFH_ENABLED ) || - phba->cfg_enable_pbde) { +if (nseg ==1 && + ((phba->sli3_options &LPFC_SLI4_PERFH_ENABLED ) || + phba->cfg_enable_pbde)) { +/* Words 13-15 */ bde = (struct ulp_bde64 *) &wqe->words[13 ]; bde->addrLow = first_data_sgl->addr_lo;
@@ -3382,12 +3383,15 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) bde->tus.f.bdeFlags =BUFF_TYPE_BDE_64 ; bde->tus.w =cpu_to_le32 (bde->tus.w); +/* Word 11 - set PBDE bit */ +bf_set (wqe_pbde, &wqe->generic.wqe_com,1 ); }else {memset (&wqe->words[13 ],0 , (sizeof (uint32_t ) *3 )); +/* Word 11 - PBDE bit disabled by default template */ } }else { sgl +=1 ; -/* clear the last flag in the fcp_rsp map entry */ +/* set the last flag in the fcp_rsp map entry */ sgl->word2 =le32_to_cpu (sgl->word2);bf_set (lpfc_sli4_sge_last, sgl,1 ); sgl->word2 =cpu_to_le32 (sgl->word2);
@@ -3400,10 +3404,6 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) } } -/* Word 11 */ -if (phba->cfg_enable_pbde) -bf_set (wqe_pbde, &wqe->generic.wqe_com,1 ); -/* * Finish initializing those IOCB fields that are dependent on the * scsi_cmnd request_buffer. Note that for SLI-2 the bdeSize is
Signature · 1 line
2.26.2
PATCH 14/14 lpfc: Update lpfc version to 14.0.0.2
In reply to James SmartUpdate lpfc version to 14.0.0.2
--- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/lpfc/lpfc_version.h +1 -1
@@ -20,7 +20,7 @@* included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.0.0.1" +#define LPFC_DRIVER_VERSION "14.0.0.2"#define LPFC_DRIVER_NAME "lpfc"/* Used for SLI 2/3 */
Signature · 1 line
2.26.2
Martin K. Petersen
AppliedJames,
Quoted 1 line
Update lpfc to revision 14.0.0.2
Applied to 5.16/scsi-staging, thanks!
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering
Martin K. Petersen
AppliedQuoted 9 lines · James Smart
Update lpfc to revision 14.0.0.2
This patch provides a number of fixes to discovery scenarios and tweaks to the recent congestion mgmt framework.
It also provides a significant eeh patch as well.The patches were cut against Martin's 5.15/scsi-queue tree
[...]
Applied to 5.16/scsi-queue, thanks!
[01/14] lpfc: Fix list_add corruption in lpfc_drain_txq
https://git.kernel.org/mkp/scsi/c/99154581b05c [02/14] lpfc: Don't release final kref on Fport node while ABTS outstanding https://git.kernel.org/mkp/scsi/c/982fc3965d13 [03/14] lpfc: Fix premature rpi release for unsolicited TPLS and LS_RJT https://git.kernel.org/mkp/scsi/c/20d2279f90ce [04/14] lpfc: Fix hang on unload due to stuck fport node https://git.kernel.org/mkp/scsi/c/88f7702984e6 [05/14] lpfc: Fix rediscovery of tape device after issue lip https://git.kernel.org/mkp/scsi/c/3a874488d2e9 [06/14] lpfc: Don't remove ndlp on PRLI errors in P2P mode https://git.kernel.org/mkp/scsi/c/a864ee709bc0 [07/14] lpfc: Fix NVME I/O failover to non-optimized path https://git.kernel.org/mkp/scsi/c/b507357f7917 [08/14] lpfc: Fix FCP I/O flush functionality for TMF routines https://git.kernel.org/mkp/scsi/c/cd8a36a90bab [09/14] lpfc: Fix EEH support for NVME I/O https://git.kernel.org/mkp/scsi/c/25ac2c970be3 [10/14] lpfc: Adjust bytes received vales during cmf timer interval https://git.kernel.org/mkp/scsi/c/d5ac69b332d8 [11/14] lpfc: Fix I/O block after enabling managed congestion mode https://git.kernel.org/mkp/scsi/c/3ea998cbf9e7 [12/14] lpfc: Zero CGN stats only during initial driver load and stat reset https://git.kernel.org/mkp/scsi/c/afd63fa51149 [13/14] lpfc: Improve PBDE checks during SGL processing https://git.kernel.org/mkp/scsi/c/315b3fd13521 [14/14] lpfc: Update lpfc version to 14.0.0.2 https://git.kernel.org/mkp/scsi/c/0d6b26795bd2
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering