Merge patch series "Update lpfc to revision 14.4.0.9"

Justin Tee <justintee8345@gmail.com> says:

Update lpfc to revision 14.4.0.9

This patch set contains fixes related to handling of WQE commands, PCI
function resets, firmware eratta events, ELS retries, a smatch
use-after-free warning, and the creation of a new VMID information entry.

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

Link: https://lore.kernel.org/r/20250425194806.3585-1-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen 2025-04-28 21:38:51 -04:00
commit 00159e436c
6 changed files with 183 additions and 32 deletions

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-2024 Broadcom. All Rights Reserved. The term *
* Copyright (C) 2017-2025 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. *
@ -291,6 +291,138 @@ lpfc_cmf_info_show(struct device *dev, struct device_attribute *attr,
return len;
}
static ssize_t
lpfc_vmid_info_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_vmid *vmp;
int len = 0, i, j, k, cpu;
char hxstr[LPFC_MAX_VMID_SIZE * 3] = {0};
struct timespec64 curr_tm;
struct lpfc_vmid_priority_range *vr;
u64 *lta, rct_acc = 0, max_lta = 0;
struct tm tm_val;
ktime_get_ts64(&curr_tm);
len += scnprintf(buf + len, PAGE_SIZE - len, "Key 'vmid':\n");
/* if enabled continue, else return */
if (lpfc_is_vmid_enabled(phba)) {
len += scnprintf(buf + len, PAGE_SIZE - len,
"lpfc VMID Page: ON\n\n");
} else {
len += scnprintf(buf + len, PAGE_SIZE - len,
"lpfc VMID Page: OFF\n\n");
return len;
}
/* if using priority tagging */
if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) {
len += scnprintf(buf + len, PAGE_SIZE - len,
"VMID priority ranges:\n");
vr = vport->vmid_priority.vmid_range;
for (i = 0; i < vport->vmid_priority.num_descriptors; ++i) {
len += scnprintf(buf + len, PAGE_SIZE - len,
"\t[x%x - x%x], qos: x%x\n",
vr->low, vr->high, vr->qos);
vr++;
}
}
for (i = 0; i < phba->cfg_max_vmid; i++) {
vmp = &vport->vmid[i];
max_lta = 0;
/* only if the slot is used */
if (!(vmp->flag & LPFC_VMID_SLOT_USED) ||
!(vmp->flag & LPFC_VMID_REGISTERED))
continue;
/* if using priority tagging */
if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) {
len += scnprintf(buf + len, PAGE_SIZE - len,
"VEM ID: %02x:%02x:%02x:%02x:"
"%02x:%02x:%02x:%02x:%02x:%02x:"
"%02x:%02x:%02x:%02x:%02x:%02x\n",
vport->lpfc_vmid_host_uuid[0],
vport->lpfc_vmid_host_uuid[1],
vport->lpfc_vmid_host_uuid[2],
vport->lpfc_vmid_host_uuid[3],
vport->lpfc_vmid_host_uuid[4],
vport->lpfc_vmid_host_uuid[5],
vport->lpfc_vmid_host_uuid[6],
vport->lpfc_vmid_host_uuid[7],
vport->lpfc_vmid_host_uuid[8],
vport->lpfc_vmid_host_uuid[9],
vport->lpfc_vmid_host_uuid[10],
vport->lpfc_vmid_host_uuid[11],
vport->lpfc_vmid_host_uuid[12],
vport->lpfc_vmid_host_uuid[13],
vport->lpfc_vmid_host_uuid[14],
vport->lpfc_vmid_host_uuid[15]);
}
/* IO stats */
len += scnprintf(buf + len, PAGE_SIZE - len,
"ID00 READs:%llx WRITEs:%llx\n",
vmp->io_rd_cnt,
vmp->io_wr_cnt);
for (j = 0, k = 0; j < strlen(vmp->host_vmid); j++, k += 3)
sprintf((char *)(hxstr + k), "%2x ", vmp->host_vmid[j]);
/* UUIDs */
len += scnprintf(buf + len, PAGE_SIZE - len, "UUID:\n");
len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", hxstr);
len += scnprintf(buf + len, PAGE_SIZE - len, "String (%s)\n",
vmp->host_vmid);
if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
len += scnprintf(buf + len, PAGE_SIZE - len,
"CS_CTL VMID: 0x%x\n",
vmp->un.cs_ctl_vmid);
else
len += scnprintf(buf + len, PAGE_SIZE - len,
"Application id: 0x%x\n",
vmp->un.app_id);
/* calculate the last access time */
for_each_possible_cpu(cpu) {
lta = per_cpu_ptr(vmp->last_io_time, cpu);
if (!lta)
continue;
/* if last access time is less than timeout */
if (time_after((unsigned long)*lta, jiffies))
continue;
if (*lta > max_lta)
max_lta = *lta;
}
rct_acc = jiffies_to_msecs(jiffies - max_lta) / 1000;
/* current time */
time64_to_tm(ktime_get_real_seconds(),
-(sys_tz.tz_minuteswest * 60) - rct_acc, &tm_val);
len += scnprintf(buf + len, PAGE_SIZE - len,
"Last Access Time :"
"%ld-%d-%dT%02d:%02d:%02d\n\n",
1900 + tm_val.tm_year, tm_val.tm_mon + 1,
tm_val.tm_mday, tm_val.tm_hour,
tm_val.tm_min, tm_val.tm_sec);
if (len >= PAGE_SIZE)
return len;
memset(hxstr, 0, LPFC_MAX_VMID_SIZE * 3);
}
return len;
}
/**
* lpfc_drvr_version_show - Return the Emulex driver string with version number
* @dev: class unused variable.
@ -3011,6 +3143,7 @@ static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
NULL);
static DEVICE_ATTR(cmf_info, 0444, lpfc_cmf_info_show, NULL);
static DEVICE_ATTR_RO(lpfc_vmid_info);
#define WWN_SZ 8
/**
@ -6117,6 +6250,7 @@ static struct attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_vmid_inactivity_timeout.attr,
&dev_attr_lpfc_vmid_app_header.attr,
&dev_attr_lpfc_vmid_priority_tagging.attr,
&dev_attr_lpfc_vmid_info.attr,
NULL,
};

View File

@ -161,7 +161,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
struct lpfc_hba *phba;
struct lpfc_work_evt *evtp;
unsigned long iflags;
bool nvme_reg = false;
bool drop_initial_node_ref = false;
ndlp = ((struct lpfc_rport_data *)rport->dd_data)->pnode;
if (!ndlp)
@ -188,8 +188,13 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
spin_lock_irqsave(&ndlp->lock, iflags);
ndlp->rport = NULL;
if (ndlp->fc4_xpt_flags & NVME_XPT_REGD)
nvme_reg = true;
/* Only 1 thread can drop the initial node reference.
* If not registered for NVME and NLP_DROPPED flag is
* clear, remove the initial reference.
*/
if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD))
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
drop_initial_node_ref = true;
/* The scsi_transport is done with the rport so lpfc cannot
* call to unregister.
@ -200,13 +205,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
/* If NLP_XPT_REGD was cleared in lpfc_nlp_unreg_node,
* unregister calls were made to the scsi and nvme
* transports and refcnt was already decremented. Clear
* the NLP_XPT_REGD flag only if the NVME Rport is
* the NLP_XPT_REGD flag only if the NVME nrport is
* confirmed unregistered.
*/
if (!nvme_reg && ndlp->fc4_xpt_flags & NLP_XPT_REGD) {
ndlp->fc4_xpt_flags &= ~NLP_XPT_REGD;
if (ndlp->fc4_xpt_flags & NLP_XPT_REGD) {
if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD))
ndlp->fc4_xpt_flags &= ~NLP_XPT_REGD;
spin_unlock_irqrestore(&ndlp->lock, iflags);
lpfc_nlp_put(ndlp); /* may free ndlp */
/* Release scsi transport reference */
lpfc_nlp_put(ndlp);
} else {
spin_unlock_irqrestore(&ndlp->lock, iflags);
}
@ -214,14 +222,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
spin_unlock_irqrestore(&ndlp->lock, iflags);
}
/* Only 1 thread can drop the initial node reference. If
* another thread has set NLP_DROPPED, this thread is done.
*/
if (nvme_reg || test_bit(NLP_DROPPED, &ndlp->nlp_flag))
return;
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
lpfc_nlp_put(ndlp);
if (drop_initial_node_ref)
lpfc_nlp_put(ndlp);
return;
}
@ -4695,9 +4697,7 @@ lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (ndlp->fc4_xpt_flags & NVME_XPT_REGD) {
vport->phba->nport_event_cnt++;
if (vport->phba->nvmet_support == 0) {
/* Start devloss if target. */
if (ndlp->nlp_type & NLP_NVME_TARGET)
lpfc_nvme_unregister_port(vport, ndlp);
lpfc_nvme_unregister_port(vport, ndlp);
} else {
/* NVMET has no upcall. */
lpfc_nlp_put(ndlp);
@ -5053,7 +5053,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba,
case CMD_GEN_REQUEST64_CR:
if (iocb->ndlp == ndlp)
return 1;
fallthrough;
break;
case CMD_ELS_REQUEST64_CR:
if (remote_id == ndlp->nlp_DID)
return 1;

View File

@ -1907,6 +1907,9 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
uint32_t intr_mode;
LPFC_MBOXQ_t *mboxq;
/* Notifying the transport that the targets are going offline. */
lpfc_scsi_dev_block(phba);
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
LPFC_SLI_INTF_IF_TYPE_2) {
/*

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-2024 Broadcom. All Rights Reserved. The term *
* Copyright (C) 2017-2025 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. *
@ -2508,7 +2508,10 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
"6031 RemotePort Registration failed "
"err: %d, DID x%06x ref %u\n",
ret, ndlp->nlp_DID, kref_read(&ndlp->kref));
lpfc_nlp_put(ndlp);
/* Only release reference if one was taken for this request */
if (!oldrport)
lpfc_nlp_put(ndlp);
}
return ret;
@ -2614,7 +2617,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* clear any rport state until the transport calls back.
*/
if (ndlp->nlp_type & NLP_NVME_TARGET) {
if ((ndlp->nlp_type & NLP_NVME_TARGET) ||
(remoteport->port_role & FC_PORT_ROLE_NVME_TARGET)) {
/* No concern about the role change on the nvme remoteport.
* The transport will update it.
*/

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-2024 Broadcom. All Rights Reserved. The term *
* Copyright (C) 2017-2025 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. *
@ -3926,12 +3926,19 @@ void lpfc_poll_eratt(struct timer_list *t)
uint64_t sli_intr, cnt;
phba = from_timer(phba, t, eratt_poll);
if (!test_bit(HBA_SETUP, &phba->hba_flag))
return;
if (test_bit(FC_UNLOADING, &phba->pport->load_flag))
return;
if (phba->sli_rev == LPFC_SLI_REV4 &&
!test_bit(HBA_SETUP, &phba->hba_flag)) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"0663 HBA still initializing 0x%lx, restart "
"timer\n",
phba->hba_flag);
goto restart_timer;
}
/* Here we will also keep track of interrupts per sec of the hba */
sli_intr = phba->sli.slistat.sli_intr;
@ -3950,13 +3957,16 @@ void lpfc_poll_eratt(struct timer_list *t)
/* Check chip HA register for error event */
eratt = lpfc_sli_check_eratt(phba);
if (eratt)
if (eratt) {
/* Tell the worker thread there is work to do */
lpfc_worker_wake_up(phba);
else
/* Restart the timer for next eratt poll */
mod_timer(&phba->eratt_poll,
jiffies + secs_to_jiffies(phba->eratt_poll_interval));
return;
}
restart_timer:
/* Restart the timer for next eratt poll */
mod_timer(&phba->eratt_poll,
jiffies + secs_to_jiffies(phba->eratt_poll_interval));
return;
}

View File

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