* [PATCHv3 0/4] nvme-fc: FPIN link integrity handling
@ 2025-04-28 6:36 hare
2025-04-28 6:36 ` [PATCH 1/4] fc_els: use 'union fc_tlv_desc' hare
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: hare @ 2025-04-28 6:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Keith Busch, Sagi Grimberg, linux-nvme, Hannes Reinecke
From: Hannes Reinecke <hare@kernel.org>
FPIN LI (link integrity) messages are received when the attached
fabric detects hardware errors. In response to these messages I/O
should be directed away from the affected ports, and only used
if the 'optimized' paths are unavailable.
Upon port reset the paths should be put back in service as the
affected hardware might have been replaced.
This patch adds a new controller flag 'NVME_CTRL_MARGINAL'
which will be checked during multipath path selection, causing the
path to be skipped when checking for 'optimized' paths. If no
optimized paths are available the 'marginal' paths are considered
for path selection alongside the 'non-optimized' paths.
Changes to the original submission:
- Changed flag name to 'marginal'
- Do not block marginal path; influence path selection instead
to de-prioritize marginal paths
Changes to v2:
- Split off driver-specific modifications
- Introduce 'union fc_tlv_desc' to avoid casts
Hannes Reinecke (4):
fc_els: use 'union fc_tlv_desc'
nvme-fc: marginal path handling
lpfc: enable FPIN notification for NVMe
qla2xxx: enable FPIN notification for NVMe
drivers/nvme/host/core.c | 1 +
drivers/nvme/host/fc.c | 99 +++++++++++++++++++
drivers/nvme/host/multipath.c | 17 ++--
drivers/nvme/host/nvme.h | 6 ++
drivers/scsi/lpfc/lpfc_els.c | 72 +++++++-------
drivers/scsi/qla2xxx/qla_isr.c | 1 +
drivers/scsi/scsi_transport_fc.c | 27 +++--
include/linux/nvme-fc-driver.h | 3 +
include/uapi/scsi/fc/fc_els.h | 165 +++++++++++++++++--------------
9 files changed, 256 insertions(+), 135 deletions(-)
--
2.35.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] fc_els: use 'union fc_tlv_desc'
2025-04-28 6:36 [PATCHv3 0/4] nvme-fc: FPIN link integrity handling hare
@ 2025-04-28 6:36 ` hare
2025-04-29 0:32 ` Justin Tee
2025-04-28 6:36 ` [PATCH 2/4] nvme-fc: marginal path handling hare
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: hare @ 2025-04-28 6:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Keith Busch, Sagi Grimberg, linux-nvme, Hannes Reinecke
From: Hannes Reinecke <hare@kernel.org>
Introduce 'union fc_tlv_desc' to have a common structure for all FC
ELS TLV structures and avoid type casts.
Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
drivers/scsi/lpfc/lpfc_els.c | 67 ++++++-------
drivers/scsi/scsi_transport_fc.c | 27 +++--
include/uapi/scsi/fc/fc_els.h | 165 +++++++++++++++++--------------
3 files changed, 131 insertions(+), 128 deletions(-)
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 375a879c31f1..4748c00f0f32 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -33,6 +33,7 @@
#include <scsi/scsi_transport_fc.h>
#include <uapi/scsi/fc/fc_fs.h>
#include <uapi/scsi/fc/fc_els.h>
+#include <linux/nvme-fc-driver.h>
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
@@ -3937,7 +3938,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
{
IOCB_t *irsp_iocb;
struct fc_els_edc_resp *edc_rsp;
- struct fc_tlv_desc *tlv;
+ union fc_tlv_desc *tlv;
struct fc_diag_cg_sig_desc *pcgd;
struct fc_diag_lnkflt_desc *plnkflt;
struct lpfc_dmabuf *pcmd, *prsp;
@@ -4028,7 +4029,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
}
- dtag = be32_to_cpu(tlv->desc_tag);
+ dtag = be32_to_cpu(tlv->hdr.desc_tag);
switch (dtag) {
case ELS_DTAG_LNK_FAULT_CAP:
if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
@@ -4043,7 +4044,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
sizeof(struct fc_diag_lnkflt_desc));
goto out;
}
- plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
+ plnkflt = &tlv->lnkflt;
lpfc_printf_log(phba, KERN_INFO,
LOG_ELS | LOG_LDS_EVENT,
"4617 Link Fault Desc Data: 0x%08x 0x%08x "
@@ -4070,7 +4071,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
}
- pcgd = (struct fc_diag_cg_sig_desc *)tlv;
+ pcgd = &tlv->cg_sig;
lpfc_printf_log(
phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"4616 CGN Desc Data: 0x%08x 0x%08x "
@@ -4125,10 +4126,8 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
static void
-lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_diag_lnkflt_desc *lft)
{
- struct fc_diag_lnkflt_desc *lft = (struct fc_diag_lnkflt_desc *)tlv;
-
lft->desc_tag = cpu_to_be32(ELS_DTAG_LNK_FAULT_CAP);
lft->desc_len = cpu_to_be32(
FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_diag_lnkflt_desc));
@@ -4141,10 +4140,8 @@ lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
}
static void
-lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_diag_cg_sig_desc *cgd)
{
- struct fc_diag_cg_sig_desc *cgd = (struct fc_diag_cg_sig_desc *)tlv;
-
/* We are assuming cgd was zero'ed before calling this routine */
/* Configure the congestion detection capability */
@@ -4233,7 +4230,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *elsiocb;
struct fc_els_edc *edc_req;
- struct fc_tlv_desc *tlv;
+ union fc_tlv_desc *tlv;
u16 cmdsize;
struct lpfc_nodelist *ndlp;
u8 *pcmd = NULL;
@@ -4272,13 +4269,13 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
tlv = edc_req->desc;
if (cgn_desc_size) {
- lpfc_format_edc_cgn_desc(phba, tlv);
+ lpfc_format_edc_cgn_desc(phba, &tlv->cg_sig);
phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
tlv = fc_tlv_next_desc(tlv);
}
if (lft_desc_size)
- lpfc_format_edc_lft_desc(phba, tlv);
+ lpfc_format_edc_lft_desc(phba, &tlv->lnkflt);
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"4623 Xmit EDC to remote "
@@ -5823,7 +5820,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
{
struct lpfc_hba *phba = vport->phba;
struct fc_els_edc_resp *edc_rsp;
- struct fc_tlv_desc *tlv;
+ union fc_tlv_desc *tlv;
struct lpfc_iocbq *elsiocb;
IOCB_t *icmd, *cmd;
union lpfc_wqe128 *wqe;
@@ -5867,10 +5864,10 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_els_lsri_desc));
edc_rsp->lsri.rqst_w0.cmd = ELS_EDC;
tlv = edc_rsp->desc;
- lpfc_format_edc_cgn_desc(phba, tlv);
+ lpfc_format_edc_cgn_desc(phba, &tlv->cg_sig);
tlv = fc_tlv_next_desc(tlv);
if (lft_desc_size)
- lpfc_format_edc_lft_desc(phba, tlv);
+ lpfc_format_edc_lft_desc(phba, &tlv->lnkflt);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"Issue EDC ACC: did:x%x flg:x%lx refcnt %d",
@@ -9255,7 +9252,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
{
struct lpfc_hba *phba = vport->phba;
struct fc_els_edc *edc_req;
- struct fc_tlv_desc *tlv;
+ union fc_tlv_desc *tlv;
uint8_t *payload;
uint32_t *ptr, dtag;
const char *dtag_nm;
@@ -9298,7 +9295,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
goto out;
}
- dtag = be32_to_cpu(tlv->desc_tag);
+ dtag = be32_to_cpu(tlv->hdr.desc_tag);
switch (dtag) {
case ELS_DTAG_LNK_FAULT_CAP:
if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
@@ -9313,7 +9310,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
sizeof(struct fc_diag_lnkflt_desc));
goto out;
}
- plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
+ plnkflt = &tlv->lnkflt;
lpfc_printf_log(phba, KERN_INFO,
LOG_ELS | LOG_LDS_EVENT,
"4626 Link Fault Desc Data: x%08x len x%x "
@@ -9350,7 +9347,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
lpfc_least_capable_settings(
- phba, (struct fc_diag_cg_sig_desc *)tlv);
+ phba, &tlv->cg_sig);
break;
default:
dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
@@ -9946,9 +9943,8 @@ lpfc_display_fpin_wwpn(struct lpfc_hba *phba, __be64 *wwnlist, u32 cnt)
* This function processes a Link Integrity FPIN event by logging a message.
**/
static void
-lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_fn_li_desc *li)
{
- struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv;
const char *li_evt_str;
u32 li_evt, cnt;
@@ -9977,9 +9973,8 @@ lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
* This function processes a Delivery FPIN event by logging a message.
**/
static void
-lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_fn_deli_desc *del)
{
- struct fc_fn_deli_desc *del = (struct fc_fn_deli_desc *)tlv;
const char *del_rsn_str;
u32 del_rsn;
__be32 *frame;
@@ -10015,9 +10010,8 @@ lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
* This function processes a Peer Congestion FPIN event by logging a message.
**/
static void
-lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_fn_peer_congn_desc *pc)
{
- struct fc_fn_peer_congn_desc *pc = (struct fc_fn_peer_congn_desc *)tlv;
const char *pc_evt_str;
u32 pc_evt, cnt;
@@ -10054,10 +10048,9 @@ lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
* to the upper layer or 0 to indicate don't deliver it.
**/
static int
-lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
+lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_fn_congn_desc *cgn)
{
struct lpfc_cgn_info *cp;
- struct fc_fn_congn_desc *cgn = (struct fc_fn_congn_desc *)tlv;
const char *cgn_evt_str;
u32 cgn_evt;
const char *cgn_sev_str;
@@ -10160,7 +10153,7 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
{
struct lpfc_hba *phba = vport->phba;
struct fc_els_fpin *fpin = (struct fc_els_fpin *)p;
- struct fc_tlv_desc *tlv, *first_tlv, *current_tlv;
+ union fc_tlv_desc *tlv, *first_tlv, *current_tlv;
const char *dtag_nm;
int desc_cnt = 0, bytes_remain, cnt;
u32 dtag, deliver = 0;
@@ -10185,7 +10178,7 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
return;
}
- tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];
+ tlv = &fpin->fpin_desc[0];
first_tlv = tlv;
bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc);
bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
@@ -10193,22 +10186,22 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
/* process each descriptor separately */
while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
- dtag = be32_to_cpu(tlv->desc_tag);
+ dtag = be32_to_cpu(tlv->hdr.desc_tag);
switch (dtag) {
case ELS_DTAG_LNK_INTEGRITY:
- lpfc_els_rcv_fpin_li(phba, tlv);
+ lpfc_els_rcv_fpin_li(phba, &tlv->li);
deliver = 1;
break;
case ELS_DTAG_DELIVERY:
- lpfc_els_rcv_fpin_del(phba, tlv);
+ lpfc_els_rcv_fpin_del(phba, &tlv->deli);
deliver = 1;
break;
case ELS_DTAG_PEER_CONGEST:
- lpfc_els_rcv_fpin_peer_cgn(phba, tlv);
+ lpfc_els_rcv_fpin_peer_cgn(phba, &tlv->peer_congn);
deliver = 1;
break;
case ELS_DTAG_CONGESTION:
- deliver = lpfc_els_rcv_fpin_cgn(phba, tlv);
+ deliver = lpfc_els_rcv_fpin_cgn(phba, &tlv->congn);
break;
default:
dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
@@ -10221,12 +10214,12 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
return;
}
lpfc_cgn_update_stat(phba, dtag);
- cnt = be32_to_cpu(tlv->desc_len);
+ cnt = be32_to_cpu(tlv->hdr.desc_len);
/* Sanity check descriptor length. The desc_len value does not
* include space for the desc_tag and the desc_len fields.
*/
- len -= (cnt + sizeof(struct fc_tlv_desc));
+ len -= (cnt + sizeof(struct fc_tlv_desc_hdr));
if (len < 0) {
dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 082f76e76721..a62636c6f708 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -750,13 +750,12 @@ fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats)
*
*/
static void
-fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
+fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_fn_li_desc *li_desc)
{
u8 i;
struct fc_rport *rport = NULL;
struct fc_rport *attach_rport = NULL;
struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
- struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;
u16 event_type = be16_to_cpu(li_desc->event_type);
u64 wwpn;
@@ -799,12 +798,11 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
*/
static void
fc_fpin_delivery_stats_update(struct Scsi_Host *shost,
- struct fc_tlv_desc *tlv)
+ struct fc_fn_deli_desc *dn_desc)
{
struct fc_rport *rport = NULL;
struct fc_rport *attach_rport = NULL;
struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
- struct fc_fn_deli_desc *dn_desc = (struct fc_fn_deli_desc *)tlv;
u32 reason_code = be32_to_cpu(dn_desc->deli_reason_code);
rport = fc_find_rport_by_wwpn(shost,
@@ -830,13 +828,11 @@ fc_fpin_delivery_stats_update(struct Scsi_Host *shost,
*/
static void
fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
- struct fc_tlv_desc *tlv)
+ struct fc_fn_peer_congn_desc *pc_desc)
{
u8 i;
struct fc_rport *rport = NULL;
struct fc_rport *attach_rport = NULL;
- struct fc_fn_peer_congn_desc *pc_desc =
- (struct fc_fn_peer_congn_desc *)tlv;
u16 event_type = be16_to_cpu(pc_desc->event_type);
u64 wwpn;
@@ -876,10 +872,9 @@ fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
*/
static void
fc_fpin_congn_stats_update(struct Scsi_Host *shost,
- struct fc_tlv_desc *tlv)
+ struct fc_fn_congn_desc *congn)
{
struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
- struct fc_fn_congn_desc *congn = (struct fc_fn_congn_desc *)tlv;
fc_cn_stats_update(be16_to_cpu(congn->event_type),
&fc_host->fpin_stats);
@@ -899,32 +894,32 @@ fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf,
u8 event_acknowledge)
{
struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf;
- struct fc_tlv_desc *tlv;
+ union fc_tlv_desc *tlv;
u32 bytes_remain;
u32 dtag;
enum fc_host_event_code event_code =
event_acknowledge ? FCH_EVT_LINK_FPIN_ACK : FCH_EVT_LINK_FPIN;
/* Update Statistics */
- tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];
+ tlv = &fpin->fpin_desc[0];
bytes_remain = fpin_len - offsetof(struct fc_els_fpin, fpin_desc);
bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
- dtag = be32_to_cpu(tlv->desc_tag);
+ dtag = be32_to_cpu(tlv->hdr.desc_tag);
switch (dtag) {
case ELS_DTAG_LNK_INTEGRITY:
- fc_fpin_li_stats_update(shost, tlv);
+ fc_fpin_li_stats_update(shost, &tlv->li);
break;
case ELS_DTAG_DELIVERY:
- fc_fpin_delivery_stats_update(shost, tlv);
+ fc_fpin_delivery_stats_update(shost, &tlv->deli);
break;
case ELS_DTAG_PEER_CONGEST:
- fc_fpin_peer_congn_stats_update(shost, tlv);
+ fc_fpin_peer_congn_stats_update(shost, &tlv->peer_congn);
break;
case ELS_DTAG_CONGESTION:
- fc_fpin_congn_stats_update(shost, tlv);
+ fc_fpin_congn_stats_update(shost, &tlv->congn);
}
bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h
index 16782c360de3..aceabd31ee88 100644
--- a/include/uapi/scsi/fc/fc_els.h
+++ b/include/uapi/scsi/fc/fc_els.h
@@ -253,12 +253,12 @@ enum fc_ls_tlv_dtag {
/*
- * Generic Link Service TLV Descriptor format
+ * Generic Link Service TLV Descriptor header
*
* This structure, as it defines no payload, will also be referred to
* as the "tlv header" - which contains the tag and len fields.
*/
-struct fc_tlv_desc {
+struct fc_tlv_desc_hdr {
__be32 desc_tag; /* Notification Descriptor Tag */
__be32 desc_len; /* Length of Descriptor (in bytes).
* Size of descriptor excluding
@@ -267,36 +267,6 @@ struct fc_tlv_desc {
__u8 desc_value[]; /* Descriptor Value */
};
-/* Descriptor tag and len fields are considered the mandatory header
- * for a descriptor
- */
-#define FC_TLV_DESC_HDR_SZ sizeof(struct fc_tlv_desc)
-
-/*
- * Macro, used when initializing payloads, to return the descriptor length.
- * Length is size of descriptor minus the tag and len fields.
- */
-#define FC_TLV_DESC_LENGTH_FROM_SZ(desc) \
- (sizeof(desc) - FC_TLV_DESC_HDR_SZ)
-
-/* Macro, used on received payloads, to return the descriptor length */
-#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv) \
- (__be32_to_cpu((tlv)->desc_len) + FC_TLV_DESC_HDR_SZ)
-
-/*
- * This helper is used to walk descriptors in a descriptor list.
- * Given the address of the current descriptor, which minimally contains a
- * tag and len field, calculate the address of the next descriptor based
- * on the len field.
- */
-static inline void *fc_tlv_next_desc(void *desc)
-{
- struct fc_tlv_desc *tlv = desc;
-
- return (desc + FC_TLV_DESC_SZ_FROM_LENGTH(tlv));
-}
-
-
/*
* Link Service Request Information Descriptor
*/
@@ -1094,19 +1064,6 @@ struct fc_fn_congn_desc {
__u8 resv[3]; /* reserved - must be zero */
};
-/*
- * ELS_FPIN - Fabric Performance Impact Notification
- */
-struct fc_els_fpin {
- __u8 fpin_cmd; /* command (0x16) */
- __u8 fpin_zero[3]; /* specified as zero - part of cmd */
- __be32 desc_len; /* Length of Descriptor List (in bytes).
- * Size of ELS excluding fpin_cmd,
- * fpin_zero and desc_len fields.
- */
- struct fc_tlv_desc fpin_desc[]; /* Descriptor list */
-};
-
/* Diagnostic Function Descriptor - FPIN Registration */
struct fc_df_desc_fpin_reg {
__be32 desc_tag; /* FPIN Registration (0x00030001) */
@@ -1125,33 +1082,6 @@ struct fc_df_desc_fpin_reg {
*/
};
-/*
- * ELS_RDF - Register Diagnostic Functions
- */
-struct fc_els_rdf {
- __u8 fpin_cmd; /* command (0x19) */
- __u8 fpin_zero[3]; /* specified as zero - part of cmd */
- __be32 desc_len; /* Length of Descriptor List (in bytes).
- * Size of ELS excluding fpin_cmd,
- * fpin_zero and desc_len fields.
- */
- struct fc_tlv_desc desc[]; /* Descriptor list */
-};
-
-/*
- * ELS RDF LS_ACC Response.
- */
-struct fc_els_rdf_resp {
- struct fc_els_ls_acc acc_hdr;
- __be32 desc_list_len; /* Length of response (in
- * bytes). Excludes acc_hdr
- * and desc_list_len fields.
- */
- struct fc_els_lsri_desc lsri;
- struct fc_tlv_desc desc[]; /* Supported Descriptor list */
-};
-
-
/*
* Diagnostic Capability Descriptors for EDC ELS
*/
@@ -1221,6 +1151,65 @@ struct fc_diag_cg_sig_desc {
struct fc_diag_cg_sig_freq rcv_signal_frequency;
};
+/*
+ * Generic Link Service TLV Descriptor format
+ *
+ * This structure, as it defines no payload, will also be referred to
+ * as the "tlv header" - which contains the tag and len fields.
+ */
+union fc_tlv_desc {
+ struct fc_tlv_desc_hdr hdr;
+ struct fc_els_lsri_desc lsri;
+ struct fc_fn_li_desc li;
+ struct fc_fn_deli_desc deli;
+ struct fc_fn_peer_congn_desc peer_congn;
+ struct fc_fn_congn_desc congn;
+ struct fc_df_desc_fpin_reg fpin_reg;
+ struct fc_diag_lnkflt_desc lnkflt;
+ struct fc_diag_cg_sig_desc cg_sig;
+};
+
+/* Descriptor tag and len fields are considered the mandatory header
+ * for a descriptor
+ */
+#define FC_TLV_DESC_HDR_SZ sizeof(struct fc_tlv_desc_hdr)
+
+/*
+ * Macro, used when initializing payloads, to return the descriptor length.
+ * Length is size of descriptor minus the tag and len fields.
+ */
+#define FC_TLV_DESC_LENGTH_FROM_SZ(desc) \
+ (sizeof(desc) - FC_TLV_DESC_HDR_SZ)
+
+/* Macro, used on received payloads, to return the descriptor length */
+#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv) \
+ (__be32_to_cpu((tlv)->hdr.desc_len) + FC_TLV_DESC_HDR_SZ)
+
+/*
+ * This helper is used to walk descriptors in a descriptor list.
+ * Given the address of the current descriptor, which minimally contains a
+ * tag and len field, calculate the address of the next descriptor based
+ * on the len field.
+ */
+static inline union fc_tlv_desc *fc_tlv_next_desc(union fc_tlv_desc *desc)
+{
+ return (union fc_tlv_desc *)((u8 *)desc + FC_TLV_DESC_SZ_FROM_LENGTH(desc));
+}
+
+
+/*
+ * ELS_FPIN - Fabric Performance Impact Notification
+ */
+struct fc_els_fpin {
+ __u8 fpin_cmd; /* command (0x16) */
+ __u8 fpin_zero[3]; /* specified as zero - part of cmd */
+ __be32 desc_len; /* Length of Descriptor List (in bytes).
+ * Size of ELS excluding fpin_cmd,
+ * fpin_zero and desc_len fields.
+ */
+ union fc_tlv_desc fpin_desc[]; /* Descriptor list */
+};
+
/*
* ELS_EDC - Exchange Diagnostic Capabilities
*/
@@ -1231,10 +1220,37 @@ struct fc_els_edc {
* Size of ELS excluding edc_cmd,
* edc_zero and desc_len fields.
*/
- struct fc_tlv_desc desc[];
+ union fc_tlv_desc desc[];
/* Diagnostic Descriptor list */
};
+/*
+ * ELS_RDF - Register Diagnostic Functions
+ */
+struct fc_els_rdf {
+ __u8 fpin_cmd; /* command (0x19) */
+ __u8 fpin_zero[3]; /* specified as zero - part of cmd */
+ __be32 desc_len; /* Length of Descriptor List (in bytes).
+ * Size of ELS excluding fpin_cmd,
+ * fpin_zero and desc_len fields.
+ */
+ union fc_tlv_desc desc[]; /* Descriptor list */
+};
+
+/*
+ * ELS RDF LS_ACC Response.
+ */
+struct fc_els_rdf_resp {
+ struct fc_els_ls_acc acc_hdr;
+ __be32 desc_list_len; /* Length of response (in
+ * bytes). Excludes acc_hdr
+ * and desc_list_len fields.
+ */
+ struct fc_els_lsri_desc lsri;
+ union fc_tlv_desc desc[]; /* Supported Descriptor list */
+};
+
+
/*
* ELS EDC LS_ACC Response.
*/
@@ -1245,9 +1261,8 @@ struct fc_els_edc_resp {
* and desc_list_len fields.
*/
struct fc_els_lsri_desc lsri;
- struct fc_tlv_desc desc[];
+ union fc_tlv_desc desc[];
/* Supported Diagnostic Descriptor list */
};
-
#endif /* _FC_ELS_H_ */
--
2.35.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] nvme-fc: marginal path handling
2025-04-28 6:36 [PATCHv3 0/4] nvme-fc: FPIN link integrity handling hare
2025-04-28 6:36 ` [PATCH 1/4] fc_els: use 'union fc_tlv_desc' hare
@ 2025-04-28 6:36 ` hare
2025-04-28 6:36 ` [PATCH 3/4] lpfc: enable FPIN notification for NVMe hare
2025-04-28 6:36 ` [PATCH 4/4] qla2xxx: " hare
3 siblings, 0 replies; 10+ messages in thread
From: hare @ 2025-04-28 6:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Keith Busch, Sagi Grimberg, linux-nvme, Hannes Reinecke
From: Hannes Reinecke <hare@kernel.org>
FPIN LI (link integrity) messages are received when the attached
fabric detects hardware errors. In response to these messages I/O
should be directed away from the affected ports, and only used
if the 'optimized' paths are unavailable.
To handle this a new controller flag 'NVME_CTRL_MARGINAL' is added
which will cause the multipath scheduler to skip these paths when
checking for 'optimized' paths. They are, however, still eligible
for non-optimized path selected. The flag is cleared upon reset as then the
faulty hardware might be replaced.
Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
drivers/nvme/host/core.c | 1 +
drivers/nvme/host/fc.c | 99 ++++++++++++++++++++++++++++++++++
drivers/nvme/host/multipath.c | 17 +++---
drivers/nvme/host/nvme.h | 6 +++
include/linux/nvme-fc-driver.h | 3 ++
5 files changed, 120 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index eb6ea8acb3cc..ab851df98079 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -4833,6 +4833,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
WRITE_ONCE(ctrl->state, NVME_CTRL_NEW);
ctrl->passthru_err_log_enabled = false;
clear_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags);
+ clear_bit(NVME_CTRL_MARGINAL, &ctrl->flags);
spin_lock_init(&ctrl->lock);
mutex_init(&ctrl->namespaces_lock);
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 2257c3c96dd2..475a636d1f7d 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -786,6 +786,10 @@ nvme_fc_ctrl_connectivity_loss(struct nvme_fc_ctrl *ctrl)
"Reconnect", ctrl->cnum);
set_bit(ASSOC_FAILED, &ctrl->flags);
+
+ /* clear 'marginal' flag as controller will be reset */
+ clear_bit(NVME_CTRL_MARGINAL, &ctrl->flags);
+
nvme_reset_ctrl(&ctrl->ctrl);
}
@@ -3713,6 +3717,101 @@ static struct nvmf_transport_ops nvme_fc_transport = {
.create_ctrl = nvme_fc_create_ctrl,
};
+static struct nvme_fc_rport *nvme_fc_rport_from_wwpn(struct nvme_fc_lport *lport,
+ u64 rport_wwpn)
+{
+ struct nvme_fc_rport *rport;
+
+ list_for_each_entry(rport, &lport->endp_list, endp_list) {
+ if (!nvme_fc_rport_get(rport))
+ continue;
+ if (rport->remoteport.port_name == rport_wwpn &&
+ rport->remoteport.port_role & FC_PORT_ROLE_NVME_TARGET)
+ return rport;
+ nvme_fc_rport_put(rport);
+ }
+ return NULL;
+}
+
+static void
+nvme_fc_fpin_li_lport_update(struct nvme_fc_lport *lport, struct fc_fn_li_desc *li)
+{
+ unsigned int i, pname_count = be32_to_cpu(li->pname_count);
+ u64 attached_wwpn = be64_to_cpu(li->attached_wwpn);
+ struct nvme_fc_rport *attached_rport;
+
+ for (i = 0; i < pname_count; i++) {
+ struct nvme_fc_rport *rport;
+ u64 wwpn = be64_to_cpu(li->pname_list[i]);
+
+ rport = nvme_fc_rport_from_wwpn(lport, wwpn);
+ if (!rport)
+ continue;
+ if (wwpn != attached_wwpn) {
+ struct nvme_fc_ctrl *ctrl;
+
+ spin_lock_irq(&rport->lock);
+ list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list)
+ set_bit(NVME_CTRL_MARGINAL, &ctrl->ctrl.flags);
+ spin_unlock_irq(&rport->lock);
+ }
+ nvme_fc_rport_put(rport);
+ }
+
+ attached_rport = nvme_fc_rport_from_wwpn(lport, attached_wwpn);
+ if (attached_rport) {
+ struct nvme_fc_ctrl *ctrl;
+
+ spin_lock_irq(&attached_rport->lock);
+ list_for_each_entry(ctrl, &attached_rport->ctrl_list, ctrl_list)
+ set_bit(NVME_CTRL_MARGINAL, &ctrl->ctrl.flags);
+ spin_unlock_irq(&attached_rport->lock);
+ nvme_fc_rport_put(attached_rport);
+ }
+}
+
+/**
+ * fc_host_fpin_rcv() - Process a received FPIN.
+ * @localport: local port the FPIN was received on
+ * @fpin_len: length of FPIN payload, in bytes
+ * @fpin_buf: pointer to FPIN payload
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+void
+nvme_fc_fpin_rcv(struct nvme_fc_local_port *localport,
+ u32 fpin_len, char *fpin_buf)
+{
+ struct nvme_fc_lport *lport;
+ struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf;
+ union fc_tlv_desc *tlv;
+ u32 bytes_remain;
+ u32 dtag;
+
+ if (!localport)
+ return;
+ lport = localport_to_lport(localport);
+ tlv = &fpin->fpin_desc[0];
+ bytes_remain = fpin_len - offsetof(struct fc_els_fpin, fpin_desc);
+ bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
+
+ while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
+ bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
+ dtag = be32_to_cpu(tlv->hdr.desc_tag);
+ switch (dtag) {
+ case ELS_DTAG_LNK_INTEGRITY:
+ nvme_fc_fpin_li_lport_update(lport, &tlv->li);
+ break;
+ default:
+ break;
+ }
+
+ bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
+ tlv = fc_tlv_next_desc(tlv);
+ }
+}
+EXPORT_SYMBOL(nvme_fc_fpin_rcv);
+
/* Arbitrary successive failures max. With lots of subsystems could be high */
#define DISCOVERY_MAX_FAIL 20
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 250f3da67cc9..6d7425d34dfc 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -273,11 +273,14 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
switch (ns->ana_state) {
case NVME_ANA_OPTIMIZED:
- if (distance < found_distance) {
- found_distance = distance;
- found = ns;
+ if (!nvme_ctrl_is_marginal(ns->ctrl)) {
+ if (distance < found_distance) {
+ found_distance = distance;
+ found = ns;
+ }
+ break;
}
- break;
+ fallthrough;
case NVME_ANA_NONOPTIMIZED:
if (distance < fallback_distance) {
fallback_distance = distance;
@@ -330,7 +333,8 @@ static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head)
if (ns->ana_state == NVME_ANA_OPTIMIZED) {
found = ns;
- goto out;
+ if (!nvme_ctrl_is_marginal(ns->ctrl))
+ goto out;
}
if (ns->ana_state == NVME_ANA_NONOPTIMIZED)
found = ns;
@@ -394,7 +398,8 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
static inline bool nvme_path_is_optimized(struct nvme_ns *ns)
{
return nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE &&
- ns->ana_state == NVME_ANA_OPTIMIZED;
+ ns->ana_state == NVME_ANA_OPTIMIZED &&
+ !nvme_ctrl_is_marginal(ns->ctrl);
}
static struct nvme_ns *nvme_numa_path(struct nvme_ns_head *head)
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index c1b4ef6c5233..503df5dc2934 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -275,6 +275,7 @@ enum nvme_ctrl_flags {
NVME_CTRL_SKIP_ID_CNS_CS = 4,
NVME_CTRL_DIRTY_CAPABILITY = 5,
NVME_CTRL_FROZEN = 6,
+ NVME_CTRL_MARGINAL = 7,
};
struct nvme_ctrl {
@@ -419,6 +420,11 @@ static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
return READ_ONCE(ctrl->state);
}
+static inline bool nvme_ctrl_is_marginal(struct nvme_ctrl *ctrl)
+{
+ return test_bit(NVME_CTRL_MARGINAL, &ctrl->flags);
+}
+
enum nvme_iopolicy {
NVME_IOPOLICY_NUMA,
NVME_IOPOLICY_RR,
diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h
index 9f6acadfe0c8..bcd3b1e5a256 100644
--- a/include/linux/nvme-fc-driver.h
+++ b/include/linux/nvme-fc-driver.h
@@ -536,6 +536,9 @@ void nvme_fc_rescan_remoteport(struct nvme_fc_remote_port *remoteport);
int nvme_fc_set_remoteport_devloss(struct nvme_fc_remote_port *remoteport,
u32 dev_loss_tmo);
+void nvme_fc_fpin_rcv(struct nvme_fc_local_port *localport,
+ u32 fpin_len, char *fpin_buf);
+
/*
* Routine called to pass a NVME-FC LS request, received by the lldd,
* to the nvme-fc transport.
--
2.35.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] lpfc: enable FPIN notification for NVMe
2025-04-28 6:36 [PATCHv3 0/4] nvme-fc: FPIN link integrity handling hare
2025-04-28 6:36 ` [PATCH 1/4] fc_els: use 'union fc_tlv_desc' hare
2025-04-28 6:36 ` [PATCH 2/4] nvme-fc: marginal path handling hare
@ 2025-04-28 6:36 ` hare
2025-04-29 0:30 ` Justin Tee
2025-04-28 6:36 ` [PATCH 4/4] qla2xxx: " hare
3 siblings, 1 reply; 10+ messages in thread
From: hare @ 2025-04-28 6:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Keith Busch, Sagi Grimberg, linux-nvme, Hannes Reinecke
From: Hannes Reinecke <hare@kernel.org>
Call 'nvme_fc_fpin_rcv()' to enble FPIN notifications for NVMe.
Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
drivers/scsi/lpfc/lpfc_els.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 4748c00f0f32..cf1fbfb15c5d 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -10248,9 +10248,12 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
fpin_length += sizeof(struct fc_els_fpin); /* the entire FPIN */
/* Send every descriptor individually to the upper layer */
- if (deliver)
+ if (deliver) {
fc_host_fpin_rcv(lpfc_shost_from_vport(vport),
fpin_length, (char *)fpin, 0);
+ nvme_fc_fpin_rcv(vport->localport,
+ fpin_length, (char *)fpin);
+ }
desc_cnt++;
}
}
--
2.35.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] qla2xxx: enable FPIN notification for NVMe
2025-04-28 6:36 [PATCHv3 0/4] nvme-fc: FPIN link integrity handling hare
` (2 preceding siblings ...)
2025-04-28 6:36 ` [PATCH 3/4] lpfc: enable FPIN notification for NVMe hare
@ 2025-04-28 6:36 ` hare
3 siblings, 0 replies; 10+ messages in thread
From: hare @ 2025-04-28 6:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Keith Busch, Sagi Grimberg, linux-nvme, Hannes Reinecke
From: Hannes Reinecke <hare@kernel.org>
Call 'nvme_fc_fpin_rcv()' to enble FPIN notifications for NVMe.
Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
drivers/scsi/qla2xxx/qla_isr.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index fe98c76e9be3..87b5b5e73a6e 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -46,6 +46,7 @@ qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct purex_item *item)
pkt, pkt_size);
fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt, 0);
+ nvme_fc_fpin_rcv(vha->nvme_local_port, pkt_size, (char *)pkt);
}
const char *const port_state_str[] = {
--
2.35.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 3/4] lpfc: enable FPIN notification for NVMe
2025-04-28 6:36 ` [PATCH 3/4] lpfc: enable FPIN notification for NVMe hare
@ 2025-04-29 0:30 ` Justin Tee
2025-04-29 6:14 ` Hannes Reinecke
0 siblings, 1 reply; 10+ messages in thread
From: Justin Tee @ 2025-04-29 0:30 UTC (permalink / raw)
To: hare
Cc: Justin Tee, James Smart, Dick Kennedy, Christoph Hellwig,
Keith Busch, Sagi Grimberg, linux-nvme
Hi Hannes,
May we qualify the call to nvme_fc_fpin_rcv with something like this?
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index cf1fbfb15c5d..ea76b4550e30 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -10251,8 +10251,11 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport,
void *p, u32 fpin_length)
if (deliver) {
fc_host_fpin_rcv(lpfc_shost_from_vport(vport),
fpin_length, (char *)fpin, 0);
- nvme_fc_fpin_rcv(vport->localport,
- fpin_length, (char *)fpin);
+#if (IS_ENABLED(CONFIG_NVME_FC))
+ if (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH)
+ nvme_fc_fpin_rcv(vport->localport,
+ fpin_length, (char *)fpin);
+#endif
}
desc_cnt++;
}
Regards,
Justin
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] fc_els: use 'union fc_tlv_desc'
2025-04-28 6:36 ` [PATCH 1/4] fc_els: use 'union fc_tlv_desc' hare
@ 2025-04-29 0:32 ` Justin Tee
2025-04-29 5:56 ` Hannes Reinecke
0 siblings, 1 reply; 10+ messages in thread
From: Justin Tee @ 2025-04-29 0:32 UTC (permalink / raw)
To: hare
Cc: Justin Tee, James Smart, Dick Kennedy, Christoph Hellwig,
Keith Busch, Sagi Grimberg, linux-nvme
Hi Hannes,
May we also update lpfc’s function header argument’s description name as well?
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index cf1fbfb15c5d..9abab90edc61 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -9938,7 +9938,7 @@ lpfc_display_fpin_wwpn(struct lpfc_hba *phba,
__be64 *wwnlist, u32 cnt)
/**
* lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event.
* @phba: Pointer to phba object.
- * @tlv: Pointer to the Link Integrity Notification Descriptor.
+ * @li: Pointer to the Link Integrity Notification Descriptor.
*
* This function processes a Link Integrity FPIN event by logging a message.
**/
@@ -9968,7 +9968,7 @@ lpfc_els_rcv_fpin_li(struct lpfc_hba *phba,
struct fc_fn_li_desc *li)
/**
* lpfc_els_rcv_fpin_del - Process an FPIN Delivery Event.
* @phba: Pointer to hba object.
- * @tlv: Pointer to the Delivery Notification Descriptor TLV
+ * @del: Pointer to the Delivery Notification Descriptor TLV
*
* This function processes a Delivery FPIN event by logging a message.
**/
@@ -10005,7 +10005,7 @@ lpfc_els_rcv_fpin_del(struct lpfc_hba *phba,
struct fc_fn_deli_desc *del)
/**
* lpfc_els_rcv_fpin_peer_cgn - Process a FPIN Peer Congestion Event.
* @phba: Pointer to hba object.
- * @tlv: Pointer to the Peer Congestion Notification Descriptor TLV
+ * @pc: Pointer to the Peer Congestion Notification Descriptor TLV
*
* This function processes a Peer Congestion FPIN event by logging a message.
**/
@@ -10039,7 +10039,7 @@ lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba
*phba, struct fc_fn_peer_congn_desc *
/**
* lpfc_els_rcv_fpin_cgn - Process an FPIN Congestion notification
* @phba: Pointer to hba object.
- * @tlv: Pointer to the Congestion Notification Descriptor TLV
+ * @cgn: Pointer to the Congestion Notification Descriptor TLV
*
* This function processes an FPIN Congestion Notifiction. The notification
* could be an Alarm or Warning. This routine feeds that data into driver's
Regards,
Justin
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] fc_els: use 'union fc_tlv_desc'
2025-04-29 0:32 ` Justin Tee
@ 2025-04-29 5:56 ` Hannes Reinecke
0 siblings, 0 replies; 10+ messages in thread
From: Hannes Reinecke @ 2025-04-29 5:56 UTC (permalink / raw)
To: Justin Tee, hare
Cc: Justin Tee, James Smart, Dick Kennedy, Christoph Hellwig,
Keith Busch, Sagi Grimberg, linux-nvme
On 4/29/25 02:32, Justin Tee wrote:
> Hi Hannes,
>
> May we also update lpfc’s function header argument’s description name as well?
>
Sure. I'll fold it in.
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/4] lpfc: enable FPIN notification for NVMe
2025-04-29 0:30 ` Justin Tee
@ 2025-04-29 6:14 ` Hannes Reinecke
2025-04-29 21:28 ` Justin Tee
0 siblings, 1 reply; 10+ messages in thread
From: Hannes Reinecke @ 2025-04-29 6:14 UTC (permalink / raw)
To: Justin Tee, hare
Cc: Justin Tee, James Smart, Dick Kennedy, Christoph Hellwig,
Keith Busch, Sagi Grimberg, linux-nvme
On 4/29/25 02:30, Justin Tee wrote:
> Hi Hannes,
>
> May we qualify the call to nvme_fc_fpin_rcv with something like this?
>
> diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
> index cf1fbfb15c5d..ea76b4550e30 100644
> --- a/drivers/scsi/lpfc/lpfc_els.c
> +++ b/drivers/scsi/lpfc/lpfc_els.c
> @@ -10251,8 +10251,11 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport,
> void *p, u32 fpin_length)
> if (deliver) {
> fc_host_fpin_rcv(lpfc_shost_from_vport(vport),
> fpin_length, (char *)fpin, 0);
> - nvme_fc_fpin_rcv(vport->localport,
> - fpin_length, (char *)fpin);
> +#if (IS_ENABLED(CONFIG_NVME_FC))
> + if (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH)
> + nvme_fc_fpin_rcv(vport->localport,
> + fpin_length, (char *)fpin);
> +#endif
> }
> desc_cnt++;
> }
>
That should rather be a 'cfg_enable_fc4_type & LPFC_ENABLE_NVME', right?
But okay, I'll fold it in.
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/4] lpfc: enable FPIN notification for NVMe
2025-04-29 6:14 ` Hannes Reinecke
@ 2025-04-29 21:28 ` Justin Tee
0 siblings, 0 replies; 10+ messages in thread
From: Justin Tee @ 2025-04-29 21:28 UTC (permalink / raw)
To: Hannes Reinecke
Cc: hare, Justin Tee, James Smart, Dick Kennedy, Christoph Hellwig,
Keith Busch, Sagi Grimberg, linux-nvme
> That should rather be a 'cfg_enable_fc4_type & LPFC_ENABLE_NVME', right?
Yes, please (:
But also, something like this to ensure our NVME target driver mode is excluded:
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index cf1fbfb15c5d..fdf4568e171e 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -10251,8 +10251,12 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport,
void *p, u32 fpin_length)
if (deliver) {
fc_host_fpin_rcv(lpfc_shost_from_vport(vport),
fpin_length, (char *)fpin, 0);
- nvme_fc_fpin_rcv(vport->localport,
- fpin_length, (char *)fpin);
+#if (IS_ENABLED(CONFIG_NVME_FC))
+ if (vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME &&
+ !phba->nvmet_support)
+ nvme_fc_fpin_rcv(vport->localport,
+ fpin_length, (char *)fpin);
+#endif
}
desc_cnt++;
}
Regards,
Justin
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-04-29 21:30 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-28 6:36 [PATCHv3 0/4] nvme-fc: FPIN link integrity handling hare
2025-04-28 6:36 ` [PATCH 1/4] fc_els: use 'union fc_tlv_desc' hare
2025-04-29 0:32 ` Justin Tee
2025-04-29 5:56 ` Hannes Reinecke
2025-04-28 6:36 ` [PATCH 2/4] nvme-fc: marginal path handling hare
2025-04-28 6:36 ` [PATCH 3/4] lpfc: enable FPIN notification for NVMe hare
2025-04-29 0:30 ` Justin Tee
2025-04-29 6:14 ` Hannes Reinecke
2025-04-29 21:28 ` Justin Tee
2025-04-28 6:36 ` [PATCH 4/4] qla2xxx: " hare
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox