Merge patch series "lpfc: Update lpfc to revision 14.2.0.11"

Justin Tee <justin.tee@broadcom.com> says:

Update lpfc to revision 14.2.0.11

This patch set contains bug fixes for buffer overflow, resource
management, discovery, and HBA error status handling.

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

Justin Tee (10):
  lpfc: Protect against potential lpfc_debugfs_lockstat_write buffer overflow
  lpfc: Reorder freeing of various dma buffers and their list removal
  lpfc: Fix lockdep warning for rx_monitor lock when unloading driver
  lpfc: Record LOGO state with discovery engine even if aborted
  lpfc: Defer issuing new PLOGI if received RSCN before completing REG_LOGIN
  lpfc: Correct used_rpi count when devloss tmo fires with no recovery
  lpfc: Skip waiting for register ready bits when in unrecoverable state
  lpfc: Revise lpfc_error_lost_link reason code evaluation logic
  lpfc: Update lpfc version to 14.2.0.11
  lpfc: Copyright updates for 14.2.0.11 patches

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen 2023-03-09 21:22:40 -05:00
commit 04d02221db
13 changed files with 134 additions and 58 deletions

View File

@ -1644,6 +1644,12 @@ lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
!bf_get(lpfc_sliport_status_err, &portstat_reg))
return -EPERM;
/* There is no point to wait if the port is in an unrecoverable
* state.
*/
if (lpfc_sli4_unrecoverable_port(&portstat_reg))
return -EIO;
/* wait for the SLI port firmware ready after firmware reset */
for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
msleep(10);

View File

@ -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) 2009-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@ -134,8 +134,8 @@ lpfc_free_bsg_buffers(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
if (mlist) {
list_for_each_entry_safe(mlast, next_mlast, &mlist->list,
list) {
lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
list_del(&mlast->list);
lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
kfree(mlast);
}
lpfc_mbuf_free(phba, mlist->virt, mlist->phys);

View File

@ -458,6 +458,8 @@ void lpfc_get_cfgparam(struct lpfc_hba *);
void lpfc_get_vport_cfgparam(struct lpfc_vport *);
int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
void lpfc_free_sysfs_attr(struct lpfc_vport *);
bool lpfc_error_lost_link(struct lpfc_vport *vport, u32 ulp_status,
u32 ulp_word4);
extern const struct attribute_group *lpfc_hba_groups[];
extern const struct attribute_group *lpfc_vport_groups[];
extern struct scsi_host_template lpfc_template;

View File

@ -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. *
@ -476,8 +476,8 @@ lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
struct lpfc_dmabuf *mlast, *next_mlast;
list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) {
lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
list_del(&mlast->list);
lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
kfree(mlast);
}
lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
@ -958,7 +958,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
goto out;
}
if (lpfc_error_lost_link(ulp_status, ulp_word4)) {
if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0226 NS query failed due to link event: "
"ulp_status x%x ulp_word4 x%x fc_flag x%x "
@ -1181,7 +1181,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
goto out;
}
if (lpfc_error_lost_link(ulp_status, ulp_word4)) {
if (lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"4166 NS query failed due to link event: "
"ulp_status x%x ulp_word4 x%x fc_flag x%x "

View File

@ -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) 2007-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@ -2157,10 +2157,13 @@ lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
char mybuf[64];
char *pbuf;
int i;
size_t bsize;
memset(mybuf, 0, sizeof(mybuf));
if (copy_from_user(mybuf, buf, nbytes))
bsize = min(nbytes, (sizeof(mybuf) - 1));
if (copy_from_user(mybuf, buf, bsize))
return -EFAULT;
pbuf = &mybuf[0];
@ -2181,7 +2184,7 @@ lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
qp->lock_conflict.wq_access = 0;
}
}
return nbytes;
return bsize;
}
#endif

View File

@ -1088,7 +1088,7 @@ stop_rr_fcf_flogi:
}
/* Do not register VFI if the driver aborted FLOGI */
if (!lpfc_error_lost_link(ulp_status, ulp_word4))
if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4))
lpfc_issue_reg_vfi(vport);
lpfc_nlp_put(ndlp);
@ -1207,7 +1207,7 @@ flogifail:
phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
spin_unlock_irq(&phba->hbalock);
if (!lpfc_error_lost_link(ulp_status, ulp_word4)) {
if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
/* FLOGI failed, so just use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
@ -2087,7 +2087,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ulp_word4);
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if (!lpfc_error_lost_link(ulp_status, ulp_word4))
if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4))
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PLOGI);
@ -2208,14 +2208,15 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
* outstanding UNREG_RPI mbox command completes, unless we
* are going offline. This logic does not apply for Fabric DIDs
*/
if ((ndlp->nlp_flag & NLP_UNREG_INP) &&
if ((ndlp->nlp_flag & (NLP_IGNR_REG_CMPL | NLP_UNREG_INP)) &&
((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) &&
!(vport->fc_flag & FC_OFFLINE_MODE)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"4110 Issue PLOGI x%x deferred "
"on NPort x%x rpi x%x Data: x%px\n",
"on NPort x%x rpi x%x flg x%x Data:"
" x%px\n",
ndlp->nlp_defer_did, ndlp->nlp_DID,
ndlp->nlp_rpi, ndlp);
ndlp->nlp_rpi, ndlp->nlp_flag, ndlp);
/* We can only defer 1st PLOGI */
if (ndlp->nlp_defer_did == NLP_EVT_NOTHING_PENDING)
@ -2382,7 +2383,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp->fc4_prli_sent);
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if (!lpfc_error_lost_link(ulp_status, ulp_word4))
if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4))
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PRLI);
@ -3037,15 +3038,16 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp->nlp_DID, ulp_status,
ulp_word4);
if (lpfc_error_lost_link(ulp_status, ulp_word4)) {
if (lpfc_error_lost_link(vport, ulp_status, ulp_word4))
skip_recovery = 1;
goto out;
}
}
/* Call state machine. This will unregister the rpi if needed. */
lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
if (skip_recovery)
goto out;
/* The driver sets this flag for an NPIV instance that doesn't want to
* log into the remote port.
*/
@ -4928,7 +4930,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if ((cmd == ELS_CMD_FLOGI) &&
(phba->fc_topology != LPFC_TOPOLOGY_LOOP) &&
!lpfc_error_lost_link(ulp_status, ulp_word4)) {
!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
/* FLOGI retry policy */
retry = 1;
/* retry FLOGI forever */
@ -4942,7 +4944,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
else if (cmdiocb->retry >= 32)
delay = 1000;
} else if ((cmd == ELS_CMD_FDISC) &&
!lpfc_error_lost_link(ulp_status, ulp_word4)) {
!lpfc_error_lost_link(vport, ulp_status, ulp_word4)) {
/* retry FDISCs every second up to devloss */
retry = 1;
maxretry = vport->cfg_devloss_tmo;
@ -5455,18 +5457,20 @@ out:
* these conditions and release the RPI.
*/
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) {
if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
spin_lock_irq(&ndlp->lock);
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
spin_unlock_irq(&ndlp->lock);
lpfc_drop_node(vport, ndlp);
vport && vport->port_type == LPFC_NPIV_PORT &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
spin_lock_irq(&ndlp->lock);
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
spin_unlock_irq(&ndlp->lock);
}
}
lpfc_drop_node(vport, ndlp);
}
/* Release the originating I/O reference. */

View File

@ -5755,8 +5755,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
(NLP_FCP_TARGET | NLP_NVME_TARGET)))
return NULL;
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
lpfc_disc_state_machine(vport, ndlp, NULL,
NLP_EVT_DEVICE_RECOVERY);
spin_lock_irq(&ndlp->lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@ -7269,3 +7269,38 @@ lpfc_parse_fcoe_conf(struct lpfc_hba *phba,
lpfc_read_fcf_conn_tbl(phba, rec_ptr);
}
/*
* lpfc_error_lost_link - IO failure from link event or FW reset check.
*
* @vport: Pointer to lpfc_vport data structure.
* @ulp_status: IO completion status.
* @ulp_word4: Reason code for the ulp_status.
*
* This function evaluates the ulp_status and ulp_word4 values
* for specific error values that indicate an internal link fault
* or fw reset event for the completing IO. Callers require this
* common data to decide next steps on the IO.
*
* Return:
* false - No link or reset error occurred.
* true - A link or reset error occurred.
*/
bool
lpfc_error_lost_link(struct lpfc_vport *vport, u32 ulp_status, u32 ulp_word4)
{
/* Mask off the extra port data to get just the reason code. */
u32 rsn_code = IOERR_PARAM_MASK & ulp_word4;
if (ulp_status == IOSTAT_LOCAL_REJECT &&
(rsn_code == IOERR_SLI_ABORTED ||
rsn_code == IOERR_LINK_DOWN ||
rsn_code == IOERR_SLI_DOWN)) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI | LOG_ELS,
"0408 Report link error true: <x%x:x%x>\n",
ulp_status, ulp_word4);
return true;
}
return false;
}

View File

@ -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. *
@ -4435,16 +4435,4 @@ lpfc_is_LC_HBA(unsigned short device)
return 0;
}
/*
* Determine if failed because of a link event or firmware reset.
*/
static inline int
lpfc_error_lost_link(u32 ulp_status, u32 ulp_word4)
{
return (ulp_status == IOSTAT_LOCAL_REJECT &&
(ulp_word4 == IOERR_SLI_ABORTED ||
ulp_word4 == IOERR_LINK_DOWN ||
ulp_word4 == IOERR_SLI_DOWN));
}
#define BPL_ALIGN_SZ 8 /* 8 byte alignment for bpl and mbufs */

View File

@ -2148,7 +2148,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
/* fall through for not able to recover */
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3152 Unrecoverable error\n");
phba->link_state = LPFC_HBA_ERROR;
lpfc_sli4_offline_eratt(phba);
break;
case LPFC_SLI_INTF_IF_TYPE_1:
default:
@ -9567,8 +9567,7 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
/* Final checks. The port status should be clean. */
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&reg_data.word0) ||
(bf_get(lpfc_sliport_status_err, &reg_data) &&
!bf_get(lpfc_sliport_status_rn, &reg_data))) {
lpfc_sli4_unrecoverable_port(&reg_data)) {
phba->work_status[0] =
readl(phba->sli4_hba.u.if_type2.
ERR1regaddr);

View File

@ -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. *
@ -2265,6 +2265,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
}
if (!vport->localport ||
test_bit(HBA_PCI_ERR, &vport->phba->bit_flags) ||
phba->link_state == LPFC_HBA_ERROR ||
vport->load_flag & FC_UNLOADING)
return;
@ -2630,7 +2631,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* return values is ignored. The upcall is a courtesy to the
* transport.
*/
if (vport->load_flag & FC_UNLOADING)
if (vport->load_flag & FC_UNLOADING ||
unlikely(vport->phba->link_state == LPFC_HBA_ERROR))
(void)nvme_fc_set_remoteport_devloss(remoteport, 0);
ret = nvme_fc_unregister_remoteport(remoteport);

View File

@ -8080,16 +8080,16 @@ int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor,
/**
* lpfc_rx_monitor_destroy_ring - Free ring buffer for rx_monitor
* @rx_monitor: Pointer to lpfc_rx_info_monitor object
*
* Called after cancellation of cmf_timer.
**/
void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor)
{
spin_lock(&rx_monitor->lock);
kfree(rx_monitor->ring);
rx_monitor->ring = NULL;
rx_monitor->entries = 0;
rx_monitor->head_idx = 0;
rx_monitor->tail_idx = 0;
spin_unlock(&rx_monitor->lock);
}
/**
@ -9895,7 +9895,8 @@ lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba)
* port for twice the regular mailbox command timeout value.
*
* 0 - no timeout on waiting for bootstrap mailbox register ready.
* MBXERR_ERROR - wait for bootstrap mailbox register timed out.
* MBXERR_ERROR - wait for bootstrap mailbox register timed out or port
* is in an unrecoverable state.
**/
static int
lpfc_sli4_wait_bmbx_ready(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
@ -9903,6 +9904,23 @@ lpfc_sli4_wait_bmbx_ready(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
uint32_t db_ready;
unsigned long timeout;
struct lpfc_register bmbx_reg;
struct lpfc_register portstat_reg = {-1};
/* Sanity check - there is no point to wait if the port is in an
* unrecoverable state.
*/
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
LPFC_SLI_INTF_IF_TYPE_2) {
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0) ||
lpfc_sli4_unrecoverable_port(&portstat_reg)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3858 Skipping bmbx ready because "
"Port Status x%x\n",
portstat_reg.word0);
return MBXERR_ERROR;
}
}
timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
* 1000) + jiffies;
@ -22329,10 +22347,10 @@ lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba,
/* Free sgl pool */
list_for_each_entry_safe(list_entry, tmp,
buf_list, list_node) {
list_del(&list_entry->list_node);
dma_pool_free(phba->lpfc_sg_dma_buf_pool,
list_entry->dma_sgl,
list_entry->dma_phys_sgl);
list_del(&list_entry->list_node);
kfree(list_entry);
}
@ -22479,10 +22497,10 @@ lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
list_for_each_entry_safe(list_entry, tmp,
buf_list,
list_node) {
list_del(&list_entry->list_node);
dma_pool_free(phba->lpfc_cmd_rsp_buf_pool,
list_entry->fcp_cmnd,
list_entry->fcp_cmd_rsp_dma_handle);
list_del(&list_entry->list_node);
kfree(list_entry);
}

View File

@ -1180,3 +1180,22 @@ static inline void *lpfc_sli4_qe(struct lpfc_queue *q, uint16_t idx)
return q->q_pgs[idx / q->entry_cnt_per_pg] +
(q->entry_size * (idx % q->entry_cnt_per_pg));
}
/**
* lpfc_sli4_unrecoverable_port - Check ERR and RN bits in portstat_reg
* @portstat_reg: portstat_reg pointer containing portstat_reg contents
*
* Description:
* Use only for SLI4 interface type-2 or later. If ERR is set && RN is 0, then
* port is deemed unrecoverable.
*
* Returns:
* true - ERR && !RN
* false - otherwise
*/
static inline bool
lpfc_sli4_unrecoverable_port(struct lpfc_register *portstat_reg)
{
return bf_get(lpfc_sliport_status_err, portstat_reg) &&
!bf_get(lpfc_sliport_status_rn, portstat_reg);
}

View File

@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "14.2.0.10"
#define LPFC_DRIVER_VERSION "14.2.0.11"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */