From a4157aaf0fb458c867b76f6cd63cb57fa91da318 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:31:58 -0700 Subject: scsi: lpfc: Fix use-after-free rport memory access in lpfc_register_remote_port() Due to a target port D_ID swap, it is possible for the lpfc_register_remote_port() routine to touch post mortem fc_rport memory when trying to access fc_rport->dd_data. The D_ID swap causes a simultaneous call to lpfc_unregister_remote_port(), where fc_remote_port_delete() reclaims fc_rport memory. Remove the fc_rport->dd_data->pnode NULL assignment because the following line reassigns ndlp->rport with an fc_rport object from fc_remote_port_add() anyways. The pnode nullification is superfluous. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-2-justintee8345@gmail.com Acked-by: Martin Wilck Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 67bfdddb897c..63e42e3f2165 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4498,14 +4498,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (vport->load_flag & FC_UNLOADING) return; - /* - * Disassociate any older association between this ndlp and rport - */ - if (ndlp->rport) { - rdata = ndlp->rport->dd_data; - rdata->pnode = NULL; - } - ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, -- cgit v1.2.3 From fd57a687d44118c0a3859f61a110f6e12804dd16 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:31:59 -0700 Subject: scsi: lpfc: Clear NLP_IN_DEV_LOSS flag if already in rediscovery In dev_loss_tmo callback routine, we early return if the ndlp is in a state of rediscovery. This occurs when a target proactively PLOGIs or PRLIs after an RSCN before the dev_loss_tmo callback routine is scheduled to run. Move clear of the NLP_IN_DEV_LOSS flag before the ndlp state check in such cases. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-3-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 63e42e3f2165..f99b5c206cdb 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -556,6 +556,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); } + spin_lock_irqsave(&ndlp->lock, iflags); + ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; + spin_unlock_irqrestore(&ndlp->lock, iflags); /* If we are devloss, but we are in the process of rediscovering the * ndlp, don't issue a NLP_EVT_DEVICE_RM event. @@ -565,9 +568,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) return fcf_inuse; } - spin_lock_irqsave(&ndlp->lock, iflags); - ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; - spin_unlock_irqrestore(&ndlp->lock, iflags); if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); -- cgit v1.2.3 From 73ded37869f8c57d0beae0d5b6434c107f780ae0 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:00 -0700 Subject: scsi: lpfc: Account for fabric domain ctlr device loss recovery Pre-existing device loss recovery logic via the NLP_IN_RECOV_POST_DEV_LOSS flag only handled Fabric Port Login, Fabric Controller, Management, and Name Server addresses. Fabric domain controllers fall under the same category for usage of the NLP_IN_RECOV_POST_DEV_LOSS flag. Add a default case statement to mark an ndlp for device loss recovery. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-4-justintee8345@gmail.com Acked-by: Martin Wilck Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f99b5c206cdb..a5c69d4bf2e0 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -458,11 +458,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) if (ndlp->nlp_type & NLP_FABRIC) { spin_lock_irqsave(&ndlp->lock, iflags); - /* In massive vport configuration settings or when the FLOGI - * completes with a sequence timeout, it's possible - * dev_loss_tmo fired during node recovery. The driver has to - * account for this race to allow for recovery and keep - * the reference counting correct. + /* The driver has to account for a race between any fabric + * node that's in recovery when dev_loss_tmo expires. When this + * happens, the driver has to allow node recovery. */ switch (ndlp->nlp_DID) { case Fabric_DID: @@ -489,6 +487,17 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) recovering = true; break; + default: + /* Ensure the nlp_DID at least has the correct prefix. + * The fabric domain controller's last three nibbles + * vary so we handle it in the default case. + */ + if (ndlp->nlp_DID & Fabric_DID_MASK) { + if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) + recovering = true; + } + break; } spin_unlock_irqrestore(&ndlp->lock, iflags); -- cgit v1.2.3 From 9914a3d033d3e1d836a43e93e9738e7dd44a096a Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:01 -0700 Subject: scsi: lpfc: Revise NPIV ELS unsol rcv cmpl logic to drop ndlp based on nlp_state When NPIV ports are zoned to devices that support both initiator and target mode, a remote device's initiated PRLI results in unintended final kref clean up of the device's ndlp structure. This disrupts NPIV ports' discovery for target devices that support both initiator and target mode. Modify the NPIV lpfc_drop_node clause such that we allow the ndlp to live so long as it was in NLP_STE_PLOGI_ISSUE, NLP_STE_REG_LOGIN_ISSUE, or NLP_STE_PRLI_ISSUE nlp_state. This allows lpfc's issued PRLI completion routine to determine if the final kref clean up should execute rather than a remote device's issued PRLI. Fixes: db651ec22524 ("scsi: lpfc: Correct used_rpi count when devloss tmo fires with no recovery") Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-5-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index a3c8550e9985..2bad9954c355 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -5452,9 +5452,19 @@ out: ndlp->nlp_flag &= ~NLP_RELEASE_RPI; spin_unlock_irq(&ndlp->lock); } + lpfc_drop_node(vport, ndlp); + } else if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE && + ndlp->nlp_state != NLP_STE_PRLI_ISSUE) { + /* Drop ndlp if there is no planned or outstanding + * issued PRLI. + * + * In cases when the ndlp is acting as both an initiator + * and target function, let our issued PRLI determine + * the final ndlp kref drop. + */ + lpfc_drop_node(vport, ndlp); } - - lpfc_drop_node(vport, ndlp); } /* Release the originating I/O reference. */ -- cgit v1.2.3 From b9951e1cffaec55cecdc3a7fae7c81dbd15c7d11 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:02 -0700 Subject: scsi: lpfc: Change firmware upgrade logging to KERN_NOTICE instead of TRACE_EVENT A firmware upgrade does not necessitate dumping of phba->dbg_log[] to kmsg via LOG_TRACE_EVENT. A simple KERN_NOTICE log message should suffice to notify the user of successful or unsuccessful firmware upgrade. As such, firmware upgrade log messages are updated to use KERN_NOTICE instead of LOG_TRACE_EVENT. Additionally, in order to notify the user of reset type for instantiating newly downloaded firmware, lpfc_log_msg's default KERN_LEVEL is updated to 5 or KERN_NOTICE. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-6-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 24 +++++++++--------- drivers/scsi/lpfc/lpfc_logmsg.h | 4 +-- drivers/scsi/lpfc/lpfc_sli.c | 54 ++++++++++++++++++++--------------------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 088bd75fb5d7..2d9879bf298b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -14747,10 +14747,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) INIT_LIST_HEAD(&dma_buffer_list); lpfc_decode_firmware_rev(phba, fwrev, 1); if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) { - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3023 Updating Firmware, Current Version:%s " - "New Version:%s\n", - fwrev, image->revision); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3023 Updating Firmware, Current Version:%s " + "New Version:%s\n", + fwrev, image->revision); for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) { dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); @@ -14797,10 +14797,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) } rc = offset; } else - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3029 Skipped Firmware update, Current " - "Version:%s New Version:%s\n", - fwrev, image->revision); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3029 Skipped Firmware update, Current " + "Version:%s New Version:%s\n", + fwrev, image->revision); release_out: list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { @@ -14812,11 +14812,11 @@ release_out: release_firmware(fw); out: if (rc < 0) - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3062 Firmware update error, status %d.\n", rc); + lpfc_log_msg(phba, KERN_ERR, LOG_INIT | LOG_SLI, + "3062 Firmware update error, status %d.\n", rc); else - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3024 Firmware update success: size %d.\n", rc); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3024 Firmware update success: size %d.\n", rc); } /** diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index b39cefcd8703..324b865db0e1 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -55,7 +55,7 @@ void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...); /* generate message by verbose log setting or severity */ #define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \ -{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '4')) \ +{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '5')) \ dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } @@ -64,7 +64,7 @@ do { \ { uint32_t log_verbose = (phba)->pport ? \ (phba)->pport->cfg_log_verbose : \ (phba)->cfg_log_verbose; \ - if (((mask) & log_verbose) || (level[1] <= '4')) \ + if (((mask) & log_verbose) || (level[1] <= '5')) \ dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ fmt, phba->brd_no, ##arg); \ } \ diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 22708f66be64..58d10f8f75a7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -20800,23 +20800,23 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, if (shdr_add_status == LPFC_ADD_STATUS_INCOMPAT_OBJ) { switch (shdr_add_status_2) { case LPFC_ADD_STATUS_2_INCOMPAT_FLASH: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4199 Firmware write failed: " - "image incompatible with flash x%02x\n", - phba->sli4_hba.flash_id); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4199 Firmware write failed: " + "image incompatible with flash x%02x\n", + phba->sli4_hba.flash_id); break; case LPFC_ADD_STATUS_2_INCORRECT_ASIC: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4200 Firmware write failed: " - "image incompatible with ASIC " - "architecture x%02x\n", - phba->sli4_hba.asic_rev); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4200 Firmware write failed: " + "image incompatible with ASIC " + "architecture x%02x\n", + phba->sli4_hba.asic_rev); break; default: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4210 Firmware write failed: " - "add_status_2 x%02x\n", - shdr_add_status_2); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4210 Firmware write failed: " + "add_status_2 x%02x\n", + shdr_add_status_2); break; } } else if (!shdr_status && !shdr_add_status) { @@ -20829,26 +20829,26 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, switch (shdr_change_status) { case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3198 Firmware write complete: System " - "reboot required to instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3198 Firmware write complete: System " + "reboot required to instantiate\n"); break; case (LPFC_CHANGE_STATUS_FW_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3199 Firmware write complete: " - "Firmware reset required to " - "instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3199 Firmware write complete: " + "Firmware reset required to " + "instantiate\n"); break; case (LPFC_CHANGE_STATUS_PORT_MIGRATION): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3200 Firmware write complete: Port " - "Migration or PCI Reset required to " - "instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3200 Firmware write complete: Port " + "Migration or PCI Reset required to " + "instantiate\n"); break; case (LPFC_CHANGE_STATUS_PCI_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3201 Firmware write complete: PCI " - "Reset required to instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3201 Firmware write complete: PCI " + "Reset required to instantiate\n"); break; default: break; -- cgit v1.2.3 From 6a84d015082ef8ef1d933230abc3fb1f6774d1d3 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:03 -0700 Subject: scsi: lpfc: Clean up SLI-4 CQE status handling There is mishandling of SLI-4 CQE status values larger than what is allowed by the LPFC_IOCB_STATUS_MASK of 4 bits. The LPFC_IOCB_STATUS_MASK is a leftover SLI-3 construct and serves no purpose in SLI-4 path. Remove the LPFC_IOCB_STATUS_MASK and clean up general CQE status handling in SLI-4 completion paths. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-7-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 -- drivers/scsi/lpfc/lpfc_hw4.h | 3 -- drivers/scsi/lpfc/lpfc_nvme.c | 17 ++++++----- drivers/scsi/lpfc/lpfc_nvmet.c | 4 +-- drivers/scsi/lpfc/lpfc_scsi.c | 65 +++++++++++++++++++----------------------- 5 files changed, 41 insertions(+), 50 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 5e3a93d13a91..dcb87bb5f88b 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -932,8 +932,6 @@ struct lpfc_hba { void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *, struct lpfc_iocbq *); int (*lpfc_hba_down_post)(struct lpfc_hba *phba); - void (*lpfc_scsi_cmd_iocb_cmpl) - (struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); /* MBOX interface function jump table entries */ int (*lpfc_sli_issue_mbox) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 082f8a109e55..5d4f9f27084d 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -395,9 +395,6 @@ struct lpfc_cqe { #define CQE_STATUS_NEED_BUFF_ENTRY 0xf #define CQE_STATUS_DI_ERROR 0x16 -/* Used when mapping CQE status to IOCB */ -#define LPFC_IOCB_STATUS_MASK 0xf - /* Status returned by hardware (valid only if status = CQE_STATUS_SUCCESS). */ #define CQE_HW_STATUS_NO_ERR 0x0 #define CQE_HW_STATUS_UNDERRUN 0x1 diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 82730a89ecb5..8db7cb99903d 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -310,20 +310,20 @@ lpfc_nvme_handle_lsreq(struct lpfc_hba *phba, * for the LS request. **/ void -__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, +__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe) { struct nvmefc_ls_req *pnvme_lsreq; struct lpfc_dmabuf *buf_ptr; struct lpfc_nodelist *ndlp; - uint32_t status; + int status; pnvme_lsreq = cmdwqe->context_un.nvme_lsreq; ndlp = cmdwqe->ndlp; buf_ptr = cmdwqe->bpl_dmabuf; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6047 NVMEx LS REQ x%px cmpl DID %x Xri: %x " @@ -343,14 +343,17 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, kfree(buf_ptr); cmdwqe->bpl_dmabuf = NULL; } - if (pnvme_lsreq->done) + if (pnvme_lsreq->done) { + if (status != CQE_STATUS_SUCCESS) + status = -ENXIO; pnvme_lsreq->done(pnvme_lsreq, status); - else + } else { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6046 NVMEx cmpl without done call back? " "Data x%px DID %x Xri: %x status %x\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, cmdwqe->sli4_xritag, status); + } if (ndlp) { lpfc_nlp_put(ndlp); cmdwqe->ndlp = NULL; @@ -367,7 +370,7 @@ lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, uint32_t status; struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); if (vport->localport) { lport = (struct lpfc_nvme_lport *)vport->localport->private; @@ -1040,7 +1043,7 @@ lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, nCmd->rcv_rsplen = LPFC_NVME_ERSP_LEN; nCmd->transferred_length = nCmd->payload_length; } else { - lpfc_ncmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_ncmd->status = status; lpfc_ncmd->result = (wcqe->parameter & IOERR_PARAM_MASK); /* For NVME, the only failure path that results in an diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 7517dd55fe91..ce201465dc6f 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -300,7 +300,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp; uint32_t status, result; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); result = wcqe->parameter; if (axchg->state != LPFC_NVME_STE_LS_RSP || axchg->entry_cnt != 2) { @@ -350,7 +350,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, if (!phba->targetport) goto finish; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); result = wcqe->parameter; tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 49aa86c477c6..a62e091894f6 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4026,7 +4026,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, struct lpfc_fast_path_event *fast_path_evt; struct Scsi_Host *shost; u32 logit = LOG_FCP; - u32 status, idx; + u32 idx; u32 lat; u8 wait_xb_clr = 0; @@ -4061,8 +4061,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, #endif shost = cmd->device->host; - status = bf_get(lpfc_wcqe_c_status, wcqe); - lpfc_cmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_cmd->status = bf_get(lpfc_wcqe_c_status, wcqe); lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK); lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; @@ -4104,11 +4103,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, } #endif if (unlikely(lpfc_cmd->status)) { - if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT && - (lpfc_cmd->result & IOERR_DRVR_MASK)) - lpfc_cmd->status = IOSTAT_DRIVER_REJECT; - else if (lpfc_cmd->status >= IOSTAT_CNT) - lpfc_cmd->status = IOSTAT_DEFAULT; if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR && !lpfc_cmd->fcp_rsp->rspStatus3 && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) && @@ -4133,16 +4127,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, } switch (lpfc_cmd->status) { - case IOSTAT_SUCCESS: + case CQE_STATUS_SUCCESS: cmd->result = DID_OK << 16; break; - case IOSTAT_FCP_RSP_ERROR: + case CQE_STATUS_FCP_RSP_FAILURE: lpfc_handle_fcp_err(vport, lpfc_cmd, pwqeIn->wqe.fcp_iread.total_xfer_len - wcqe->total_data_placed); break; - case IOSTAT_NPORT_BSY: - case IOSTAT_FABRIC_BSY: + case CQE_STATUS_NPORT_BSY: + case CQE_STATUS_FABRIC_BSY: cmd->result = DID_TRANSPORT_DISRUPTED << 16; fast_path_evt = lpfc_alloc_fast_evt(phba); if (!fast_path_evt) @@ -4185,7 +4179,27 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, wcqe->total_data_placed, lpfc_cmd->cur_iocbq.iocb.ulpIoTag); break; - case IOSTAT_REMOTE_STOP: + case CQE_STATUS_DI_ERROR: + if (bf_get(lpfc_wcqe_c_bg_edir, wcqe)) + lpfc_cmd->result = IOERR_RX_DMA_FAILED; + else + lpfc_cmd->result = IOERR_TX_DMA_FAILED; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_BG, + "9048 DI Error xri x%x status x%x DI ext " + "status x%x data placed x%x\n", + lpfc_cmd->cur_iocbq.sli4_xritag, + lpfc_cmd->status, wcqe->parameter, + wcqe->total_data_placed); + if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { + /* BG enabled cmd. Parse BG error */ + lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); + break; + } + cmd->result = DID_ERROR << 16; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9040 DI Error on unprotected cmd\n"); + break; + case CQE_STATUS_REMOTE_STOP: if (ndlp) { /* This I/O was aborted by the target, we don't * know the rxid and because we did not send the @@ -4196,7 +4210,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, 0, 0); } fallthrough; - case IOSTAT_LOCAL_REJECT: + case CQE_STATUS_LOCAL_REJECT: if (lpfc_cmd->result & IOERR_DRVR_MASK) lpfc_cmd->status = IOSTAT_DRIVER_REJECT; if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR || @@ -4217,24 +4231,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, cmd->result = DID_TRANSPORT_DISRUPTED << 16; break; } - if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || - lpfc_cmd->result == IOERR_TX_DMA_FAILED) && - status == CQE_STATUS_DI_ERROR) { - if (scsi_get_prot_op(cmd) != - SCSI_PROT_NORMAL) { - /* - * This is a response for a BG enabled - * cmd. Parse BG error - */ - lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); - break; - } else { - lpfc_printf_vlog(vport, KERN_WARNING, - LOG_BG, - "9040 non-zero BGSTAT " - "on unprotected cmd\n"); - } - } lpfc_printf_vlog(vport, KERN_WARNING, logit, "9036 Local Reject FCP cmd x%x failed" " <%d/%lld> " @@ -4253,10 +4249,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, lpfc_cmd->cur_iocbq.iocb.ulpIoTag); fallthrough; default: - if (lpfc_cmd->status >= IOSTAT_CNT) - lpfc_cmd->status = IOSTAT_DEFAULT; cmd->result = DID_ERROR << 16; - lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "9037 FCP Completion Error: xri %x " "status x%x result x%x [x%x] " "placed x%x\n", @@ -5010,7 +5004,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) return -ENODEV; } phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; - phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; return 0; } -- cgit v1.2.3 From 93190ac1d4e7aa5fc959cf6a2bd294c1dfe6ee47 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:04 -0700 Subject: scsi: lpfc: Enhance congestion statistics collection Various improvements are made for collecting congestion statistics: - Pre-existing logic is replaced with use of an hrtimer for increased reporting accuracy. - Congestion timestamp information is reorganized into a single struct. - Common statistic collection logic is refactored into a helper routine. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-8-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 63 ++++-------- drivers/scsi/lpfc/lpfc_init.c | 226 ++++++++++++------------------------------ 2 files changed, 81 insertions(+), 208 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index dcb87bb5f88b..9a8963684369 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -429,6 +429,15 @@ struct lpfc_cgn_param { /* Max number of days of congestion data */ #define LPFC_MAX_CGN_DAYS 10 +struct lpfc_cgn_ts { + uint8_t month; + uint8_t day; + uint8_t year; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + /* Format of congestion buffer info * This structure defines memory thats allocated and registered with * the HBA firmware. When adding or removing fields from this structure @@ -442,6 +451,7 @@ struct lpfc_cgn_info { #define LPFC_CGN_INFO_V1 1 #define LPFC_CGN_INFO_V2 2 #define LPFC_CGN_INFO_V3 3 +#define LPFC_CGN_INFO_V4 4 uint8_t cgn_info_mode; /* 0=off 1=managed 2=monitor only */ uint8_t cgn_info_detect; uint8_t cgn_info_action; @@ -450,12 +460,7 @@ struct lpfc_cgn_info { uint8_t cgn_info_level2; /* Start Time */ - uint8_t cgn_info_month; - uint8_t cgn_info_day; - uint8_t cgn_info_year; - uint8_t cgn_info_hour; - uint8_t cgn_info_minute; - uint8_t cgn_info_second; + struct lpfc_cgn_ts base_time; /* minute / hours / daily indices */ uint8_t cgn_index_minute; @@ -496,45 +501,17 @@ struct lpfc_cgn_info { uint8_t cgn_stat_npm; /* Notifications per minute */ /* Start Time */ - uint8_t cgn_stat_month; - uint8_t cgn_stat_day; - uint8_t cgn_stat_year; - uint8_t cgn_stat_hour; - uint8_t cgn_stat_minute; - uint8_t cgn_pad2[2]; + struct lpfc_cgn_ts stat_start; /* Base time */ + uint8_t cgn_pad2; __le32 cgn_notification; __le32 cgn_peer_notification; __le32 link_integ_notification; __le32 delivery_notification; - - uint8_t cgn_stat_cgn_month; /* Last congestion notification FPIN */ - uint8_t cgn_stat_cgn_day; - uint8_t cgn_stat_cgn_year; - uint8_t cgn_stat_cgn_hour; - uint8_t cgn_stat_cgn_min; - uint8_t cgn_stat_cgn_sec; - - uint8_t cgn_stat_peer_month; /* Last peer congestion FPIN */ - uint8_t cgn_stat_peer_day; - uint8_t cgn_stat_peer_year; - uint8_t cgn_stat_peer_hour; - uint8_t cgn_stat_peer_min; - uint8_t cgn_stat_peer_sec; - - uint8_t cgn_stat_lnk_month; /* Last link integrity FPIN */ - uint8_t cgn_stat_lnk_day; - uint8_t cgn_stat_lnk_year; - uint8_t cgn_stat_lnk_hour; - uint8_t cgn_stat_lnk_min; - uint8_t cgn_stat_lnk_sec; - - uint8_t cgn_stat_del_month; /* Last delivery notification FPIN */ - uint8_t cgn_stat_del_day; - uint8_t cgn_stat_del_year; - uint8_t cgn_stat_del_hour; - uint8_t cgn_stat_del_min; - uint8_t cgn_stat_del_sec; + struct lpfc_cgn_ts stat_fpin; /* Last congestion notification FPIN */ + struct lpfc_cgn_ts stat_peer; /* Last peer congestion FPIN */ + struct lpfc_cgn_ts stat_lnk; /* Last link integrity FPIN */ + struct lpfc_cgn_ts stat_delivery; /* Last delivery notification FPIN */ ); __le32 cgn_info_crc; @@ -1043,8 +1020,6 @@ struct lpfc_hba { * capability */ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ -#define HBA_SHORT_CMF 0x200000 /* shorter CMF timer routine */ -#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */ #define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */ #define HBA_SETUP 0x1000000 /* Signifies HBA setup is completed */ #define HBA_NEEDS_CFG_PORT 0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */ @@ -1527,6 +1502,7 @@ struct lpfc_hba { uint64_t cmf_last_sync_bw; #define LPFC_CMF_BLK_SIZE 512 struct hrtimer cmf_timer; + struct hrtimer cmf_stats_timer; /* 1 minute stats timer */ atomic_t cmf_bw_wait; atomic_t cmf_busy; atomic_t cmf_stop_io; /* To block request and stop IO's */ @@ -1574,12 +1550,11 @@ struct lpfc_hba { atomic_t cgn_sync_alarm_cnt; /* Total alarm events for SYNC wqe */ atomic_t cgn_driver_evt_cnt; /* Total driver cgn events for fmw */ atomic_t cgn_latency_evt_cnt; - struct timespec64 cgn_daily_ts; atomic64_t cgn_latency_evt; /* Avg latency per minute */ unsigned long cgn_evt_timestamp; #define LPFC_CGN_TIMER_TO_MIN 60000 /* ms in a minute */ uint32_t cgn_evt_minute; -#define LPFC_SEC_MIN 60 +#define LPFC_SEC_MIN 60UL #define LPFC_MIN_HOUR 60 #define LPFC_HOUR_DAY 24 #define LPFC_MIN_DAY (LPFC_MIN_HOUR * LPFC_HOUR_DAY) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2d9879bf298b..3221a934066b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -101,6 +101,7 @@ static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static DEFINE_IDR(lpfc_hba_index); #define LPFC_NVMET_BUF_POST 254 static int lpfc_vmid_res_alloc(struct lpfc_hba *phba, struct lpfc_vport *vport); +static void lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts); /** * lpfc_config_port_prep - Perform lpfc initialization prior to config port @@ -3197,6 +3198,7 @@ lpfc_cmf_stop(struct lpfc_hba *phba) "6221 Stop CMF / Cancel Timer\n"); /* Cancel the CMF timer */ + hrtimer_cancel(&phba->cmf_stats_timer); hrtimer_cancel(&phba->cmf_timer); /* Zero CMF counters */ @@ -3283,7 +3285,10 @@ lpfc_cmf_start(struct lpfc_hba *phba) phba->cmf_timer_cnt = 0; hrtimer_start(&phba->cmf_timer, - ktime_set(0, LPFC_CMF_INTERVAL * 1000000), + ktime_set(0, LPFC_CMF_INTERVAL * NSEC_PER_MSEC), + HRTIMER_MODE_REL); + hrtimer_start(&phba->cmf_stats_timer, + ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC), HRTIMER_MODE_REL); /* Setup for latency check in IO cmpl routines */ ktime_get_real_ts64(&phba->cmf_latency); @@ -5595,81 +5600,74 @@ void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag) { struct lpfc_cgn_info *cp; - struct tm broken; - struct timespec64 cur_time; - u32 cnt; u32 value; /* Make sure we have a congestion info buffer */ if (!phba->cgn_i) return; cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - ktime_get_real_ts64(&cur_time); - time64_to_tm(cur_time.tv_sec, 0, &broken); /* Update congestion statistics */ switch (dtag) { case ELS_DTAG_LNK_INTEGRITY: - cnt = le32_to_cpu(cp->link_integ_notification); - cnt++; - cp->link_integ_notification = cpu_to_le32(cnt); - - cp->cgn_stat_lnk_month = broken.tm_mon + 1; - cp->cgn_stat_lnk_day = broken.tm_mday; - cp->cgn_stat_lnk_year = broken.tm_year - 100; - cp->cgn_stat_lnk_hour = broken.tm_hour; - cp->cgn_stat_lnk_min = broken.tm_min; - cp->cgn_stat_lnk_sec = broken.tm_sec; + le32_add_cpu(&cp->link_integ_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_lnk); break; case ELS_DTAG_DELIVERY: - cnt = le32_to_cpu(cp->delivery_notification); - cnt++; - cp->delivery_notification = cpu_to_le32(cnt); - - cp->cgn_stat_del_month = broken.tm_mon + 1; - cp->cgn_stat_del_day = broken.tm_mday; - cp->cgn_stat_del_year = broken.tm_year - 100; - cp->cgn_stat_del_hour = broken.tm_hour; - cp->cgn_stat_del_min = broken.tm_min; - cp->cgn_stat_del_sec = broken.tm_sec; + le32_add_cpu(&cp->delivery_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_delivery); break; case ELS_DTAG_PEER_CONGEST: - cnt = le32_to_cpu(cp->cgn_peer_notification); - cnt++; - cp->cgn_peer_notification = cpu_to_le32(cnt); - - cp->cgn_stat_peer_month = broken.tm_mon + 1; - cp->cgn_stat_peer_day = broken.tm_mday; - cp->cgn_stat_peer_year = broken.tm_year - 100; - cp->cgn_stat_peer_hour = broken.tm_hour; - cp->cgn_stat_peer_min = broken.tm_min; - cp->cgn_stat_peer_sec = broken.tm_sec; + le32_add_cpu(&cp->cgn_peer_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_peer); break; case ELS_DTAG_CONGESTION: - cnt = le32_to_cpu(cp->cgn_notification); - cnt++; - cp->cgn_notification = cpu_to_le32(cnt); - - cp->cgn_stat_cgn_month = broken.tm_mon + 1; - cp->cgn_stat_cgn_day = broken.tm_mday; - cp->cgn_stat_cgn_year = broken.tm_year - 100; - cp->cgn_stat_cgn_hour = broken.tm_hour; - cp->cgn_stat_cgn_min = broken.tm_min; - cp->cgn_stat_cgn_sec = broken.tm_sec; + le32_add_cpu(&cp->cgn_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_fpin); } if (phba->cgn_fpin_frequency && phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) { value = LPFC_CGN_TIMER_TO_MIN / phba->cgn_fpin_frequency; cp->cgn_stat_npm = value; } + value = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(value); } /** - * lpfc_cgn_save_evt_cnt - Save data into registered congestion buffer + * lpfc_cgn_update_tstamp - Update cmf timestamp * @phba: pointer to lpfc hba data structure. + * @ts: structure to write the timestamp to. + */ +void +lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts) +{ + struct timespec64 cur_time; + struct tm tm_val; + + ktime_get_real_ts64(&cur_time); + time64_to_tm(cur_time.tv_sec, 0, &tm_val); + + ts->month = tm_val.tm_mon + 1; + ts->day = tm_val.tm_mday; + ts->year = tm_val.tm_year - 100; + ts->hour = tm_val.tm_hour; + ts->minute = tm_val.tm_min; + ts->second = tm_val.tm_sec; + + lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, + "2646 Updated CMF timestamp : " + "%u/%u/%u %u:%u:%u\n", + ts->day, ts->month, + ts->year, ts->hour, + ts->minute, ts->second); +} + +/** + * lpfc_cmf_stats_timer - Save data into registered congestion buffer + * @timer: Timer cookie to access lpfc private data * * Save the congestion event data every minute. * On the hour collapse all the minute data into hour data. Every day @@ -5677,12 +5675,11 @@ lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag) * and fabrc congestion event counters that will be saved out * to the registered congestion buffer every minute. */ -static void -lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) +static enum hrtimer_restart +lpfc_cmf_stats_timer(struct hrtimer *timer) { + struct lpfc_hba *phba; struct lpfc_cgn_info *cp; - struct tm broken; - struct timespec64 cur_time; uint32_t i, index; uint16_t value, mvalue; uint64_t bps; @@ -5693,21 +5690,18 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) __le32 *lptr; __le16 *mptr; + phba = container_of(timer, struct lpfc_hba, cmf_stats_timer); /* Make sure we have a congestion info buffer */ if (!phba->cgn_i) - return; + return HRTIMER_NORESTART; cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - if (time_before(jiffies, phba->cgn_evt_timestamp)) - return; phba->cgn_evt_timestamp = jiffies + msecs_to_jiffies(LPFC_CGN_TIMER_TO_MIN); phba->cgn_evt_minute++; /* We should get to this point in the routine on 1 minute intervals */ - - ktime_get_real_ts64(&cur_time); - time64_to_tm(cur_time.tv_sec, 0, &broken); + lpfc_cgn_update_tstamp(phba, &cp->base_time); if (phba->cgn_fpin_frequency && phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) { @@ -5860,31 +5854,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) index = 0; } - /* Anytime we overwrite daily index 0, after we wrap, - * we will be overwriting the oldest day, so we must - * update the congestion data start time for that day. - * That start time should have previously been saved after - * we wrote the last days worth of data. - */ - if ((phba->hba_flag & HBA_CGN_DAY_WRAP) && index == 0) { - time64_to_tm(phba->cgn_daily_ts.tv_sec, 0, &broken); - - cp->cgn_info_month = broken.tm_mon + 1; - cp->cgn_info_day = broken.tm_mday; - cp->cgn_info_year = broken.tm_year - 100; - cp->cgn_info_hour = broken.tm_hour; - cp->cgn_info_minute = broken.tm_min; - cp->cgn_info_second = broken.tm_sec; - - lpfc_printf_log - (phba, KERN_INFO, LOG_CGN_MGMT, - "2646 CGNInfo idx0 Start Time: " - "%d/%d/%d %d:%d:%d\n", - cp->cgn_info_day, cp->cgn_info_month, - cp->cgn_info_year, cp->cgn_info_hour, - cp->cgn_info_minute, cp->cgn_info_second); - } - dvalue = 0; wvalue = 0; lvalue = 0; @@ -5918,15 +5887,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) "2420 Congestion Info - daily (%d): " "%d %d %d %d %d\n", index, dvalue, wvalue, lvalue, mvalue, avalue); - - /* We just wrote LPFC_MAX_CGN_DAYS of data, - * so we are wrapped on any data after this. - * Save this as the start time for the next day. - */ - if (index == (LPFC_MAX_CGN_DAYS - 1)) { - phba->hba_flag |= HBA_CGN_DAY_WRAP; - ktime_get_real_ts64(&phba->cgn_daily_ts); - } } /* Use the frequency found in the last rcv'ed FPIN */ @@ -5937,6 +5897,10 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) lvalue = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(lvalue); + + hrtimer_forward_now(timer, ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC)); + + return HRTIMER_RESTART; } /** @@ -6067,13 +6031,6 @@ lpfc_cmf_timer(struct hrtimer *timer) if (ms && ms < LPFC_CMF_INTERVAL) { cnt = div_u64(total, ms); /* bytes per ms */ cnt *= LPFC_CMF_INTERVAL; /* what total should be */ - - /* If the timeout is scheduled to be shorter, - * this value may skew the data, so cap it at mbpi. - */ - if ((phba->hba_flag & HBA_SHORT_CMF) && cnt > mbpi) - cnt = mbpi; - extra = cnt - total; } lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total + extra); @@ -6143,34 +6100,6 @@ lpfc_cmf_timer(struct hrtimer *timer) } phba->rx_block_cnt += div_u64(rcv, 512); /* save 512 byte block cnt */ - /* Each minute save Fabric and Driver congestion information */ - lpfc_cgn_save_evt_cnt(phba); - - phba->hba_flag &= ~HBA_SHORT_CMF; - - /* Since we need to call lpfc_cgn_save_evt_cnt every minute, on the - * minute, adjust our next timer interval, if needed, to ensure a - * 1 minute granularity when we get the next timer interrupt. - */ - if (time_after(jiffies + msecs_to_jiffies(LPFC_CMF_INTERVAL), - phba->cgn_evt_timestamp)) { - timer_interval = jiffies_to_msecs(phba->cgn_evt_timestamp - - jiffies); - if (timer_interval <= 0) - timer_interval = LPFC_CMF_INTERVAL; - else - phba->hba_flag |= HBA_SHORT_CMF; - - /* If we adjust timer_interval, max_bytes_per_interval - * needs to be adjusted as well. - */ - phba->cmf_link_byte_count = div_u64(phba->cmf_max_line_rate * - timer_interval, 1000); - if (phba->cmf_active_mode == LPFC_CFG_MONITOR) - phba->cmf_max_bytes_per_interval = - phba->cmf_link_byte_count; - } - /* Since total_bytes has already been zero'ed, its okay to unblock * after max_bytes_per_interval is setup. */ @@ -8016,6 +7945,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* CMF congestion timer */ hrtimer_init(&phba->cmf_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); phba->cmf_timer.function = lpfc_cmf_timer; + /* CMF 1 minute stats collection timer */ + hrtimer_init(&phba->cmf_stats_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + phba->cmf_stats_timer.function = lpfc_cmf_stats_timer; /* * Control structure for handling external multi-buffer mailbox @@ -13525,6 +13457,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) struct pci_dev *pdev = phba->pcidev; lpfc_stop_hba_timers(phba); + hrtimer_cancel(&phba->cmf_stats_timer); hrtimer_cancel(&phba->cmf_timer); if (phba->pport) @@ -13649,8 +13582,6 @@ void lpfc_init_congestion_buf(struct lpfc_hba *phba) { struct lpfc_cgn_info *cp; - struct timespec64 cmpl_time; - struct tm broken; uint16_t size; uint32_t crc; @@ -13670,11 +13601,10 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba) atomic_set(&phba->cgn_latency_evt_cnt, 0); atomic64_set(&phba->cgn_latency_evt, 0); phba->cgn_evt_minute = 0; - phba->hba_flag &= ~HBA_CGN_DAY_WRAP; memset(cp, 0xff, offsetof(struct lpfc_cgn_info, cgn_stat)); cp->cgn_info_size = cpu_to_le16(LPFC_CGN_INFO_SZ); - cp->cgn_info_version = LPFC_CGN_INFO_V3; + cp->cgn_info_version = LPFC_CGN_INFO_V4; /* cgn parameters */ cp->cgn_info_mode = phba->cgn_p.cgn_param_mode; @@ -13682,22 +13612,7 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba) cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1; cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2; - ktime_get_real_ts64(&cmpl_time); - time64_to_tm(cmpl_time.tv_sec, 0, &broken); - - cp->cgn_info_month = broken.tm_mon + 1; - cp->cgn_info_day = broken.tm_mday; - cp->cgn_info_year = broken.tm_year - 100; /* relative to 2000 */ - cp->cgn_info_hour = broken.tm_hour; - cp->cgn_info_minute = broken.tm_min; - cp->cgn_info_second = broken.tm_sec; - - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT, - "2643 CGNInfo Init: Start Time " - "%d/%d/%d %d:%d:%d\n", - cp->cgn_info_day, cp->cgn_info_month, - cp->cgn_info_year, cp->cgn_info_hour, - cp->cgn_info_minute, cp->cgn_info_second); + lpfc_cgn_update_tstamp(phba, &cp->base_time); /* Fill in default LUN qdepth */ if (phba->pport) { @@ -13720,8 +13635,6 @@ void lpfc_init_congestion_stat(struct lpfc_hba *phba) { struct lpfc_cgn_info *cp; - struct timespec64 cmpl_time; - struct tm broken; uint32_t crc; lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, @@ -13733,22 +13646,7 @@ lpfc_init_congestion_stat(struct lpfc_hba *phba) cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; memset(&cp->cgn_stat, 0, sizeof(cp->cgn_stat)); - ktime_get_real_ts64(&cmpl_time); - time64_to_tm(cmpl_time.tv_sec, 0, &broken); - - cp->cgn_stat_month = broken.tm_mon + 1; - cp->cgn_stat_day = broken.tm_mday; - cp->cgn_stat_year = broken.tm_year - 100; /* relative to 2000 */ - cp->cgn_stat_hour = broken.tm_hour; - cp->cgn_stat_minute = broken.tm_min; - - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT, - "2647 CGNstat Init: Start Time " - "%d/%d/%d %d:%d\n", - cp->cgn_stat_day, cp->cgn_stat_month, - cp->cgn_stat_year, cp->cgn_stat_hour, - cp->cgn_stat_minute); - + lpfc_cgn_update_tstamp(phba, &cp->stat_start); crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(crc); } -- cgit v1.2.3 From 48abf8b4b563b38c994fd6e3be082a0dcff91be3 Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:05 -0700 Subject: scsi: lpfc: Update lpfc version to 14.2.0.13 Update lpfc version to 14.2.0.13 Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-9-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- 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 5fda8ac6b883..6f35491aed0f 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 "14.2.0.12" +#define LPFC_DRIVER_VERSION "14.2.0.13" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- cgit v1.2.3 From b93f9eb8f4cde7b0907d3f59b047cac6c3c2ae5f Mon Sep 17 00:00:00 2001 From: Justin Tee Date: Tue, 23 May 2023 11:32:06 -0700 Subject: scsi: lpfc: Copyright updates for 14.2.0.13 patches Update copyrights to 2023 for files modified in the 14.2.0.13 patch set. Signed-off-by: Justin Tee Link: https://lore.kernel.org/r/20230523183206.7728-10-justintee8345@gmail.com Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_logmsg.h | 2 +- drivers/scsi/lpfc/lpfc_nvmet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index 324b865db0e1..f896ec610433 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2009 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index ce201465dc6f..dff4584d338b 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 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. * -- cgit v1.2.3