summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2025-12-16 21:58:08 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2025-12-16 21:58:08 -0500
commitf5c0386e2c5cd9767fcb53fee660cd7af1ecaa6a (patch)
treea574878c4e8c30917b83b39e56af68b4843553d6
parent1a56e63c82161fca8f8d93b0ce5ce66c7c7d6b6d (diff)
parent6211644253153e4a86892112121ea597d02b5e12 (diff)
Merge patch series "Update lpfc to revision 14.4.0.13"
Justin Tee <justintee8345@gmail.com> says: Update lpfc to revision 14.4.0.13 This patch set introduces reporting encryption information for Fibre Channel HBAs. First, the scsi_transport_fc layer is updated to include a new fc_encryption_info attribute that is added to struct fc_rport. Supporting sysfs and LLDD templates are provided. Then, the lpfc driver is updated to utilize the new templates for reporting encrypted fibre channel connections to upper layer. The patches were cut against Martin's 6.19/scsi-queue tree. Link: https://patch.msgid.link/20251211001659.138635-1-justintee8345@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/base/transport_class.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c40
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h7
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c57
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h11
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/scsi_transport_fc.c42
-rw-r--r--include/linux/transport_class.h1
-rw-r--r--include/scsi/scsi_transport_fc.h12
14 files changed, 197 insertions, 3 deletions
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 09ee2a1e35bb..69c6ac2e8263 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -169,6 +169,12 @@ static int transport_add_class_device(struct attribute_container *cont,
goto err_del;
}
+ if (tcont->encryption) {
+ error = sysfs_create_group(&classdev->kobj, tcont->encryption);
+ if (error)
+ goto err_del;
+ }
+
return 0;
err_del:
@@ -244,6 +250,8 @@ static int transport_remove_classdev(struct attribute_container *cont,
if (tclass->remove != anon_transport_dummy_function) {
if (tcont->statistics)
sysfs_remove_group(&classdev->kobj, tcont->statistics);
+ if (tcont->encryption)
+ sysfs_remove_group(&classdev->kobj, tcont->encryption);
attribute_container_class_device_del(classdev);
}
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 33582d48ec09..4af5c069635a 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -6979,6 +6979,42 @@ lpfc_reset_stats(struct Scsi_Host *shost)
return;
}
+/**
+ * lpfc_get_enc_info - Return encryption information about the session for
+ * a given remote port.
+ * @rport: ptr to fc_rport from scsi transport fc
+ *
+ * Given an rport object, iterate through the fc_nodes list to find node
+ * corresponding with rport. Pass the encryption information from the node to
+ * rport's encryption attribute for reporting to upper layers. Information is
+ * passed through nlp_enc_info struct which contains encryption status.
+ *
+ * Returns:
+ * - Address of rport's fc_encryption_info struct
+ * - NULL when not found
+ **/
+static struct fc_encryption_info *
+lpfc_get_enc_info(struct fc_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct fc_encryption_info *ef = NULL;
+ struct lpfc_nodelist *ndlp, *next_ndlp;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&vport->fc_nodes_list_lock, iflags);
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (ndlp->rport && ndlp->rport == rport) {
+ ef = &rport->enc_info;
+ ef->status = ndlp->nlp_enc_info.status;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&vport->fc_nodes_list_lock, iflags);
+ return ef;
+}
+
+
/*
* The LPFC driver treats linkdown handling as target loss events so there
* are no sysfs handlers for link_down_tmo.
@@ -7196,6 +7232,8 @@ struct fc_function_template lpfc_transport_functions = {
.get_fc_host_stats = lpfc_get_stats,
.reset_fc_host_stats = lpfc_reset_stats,
+ .get_fc_rport_enc_info = lpfc_get_enc_info,
+
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
@@ -7265,6 +7303,8 @@ struct fc_function_template lpfc_vport_transport_functions = {
.get_fc_host_stats = lpfc_get_stats,
.reset_fc_host_stats = lpfc_reset_stats,
+ .get_fc_rport_enc_info = lpfc_get_enc_info,
+
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 92b5b2dbe847..646f88c776f5 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -872,6 +872,13 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
ndlp->nlp_rpi);
len += scnprintf(buf+len, size-len, "flag:x%08lx ",
ndlp->nlp_flag);
+ if (ndlp->nlp_enc_info.status) {
+ len += scnprintf(buf + len,
+ size - len, "ENCRYPTED");
+ len += scnprintf(buf + len, size - len,
+ ndlp->nlp_enc_info.level
+ ? "(CNSA2.0) " : "(CNSA1.0) ");
+ }
if (!ndlp->nlp_type)
len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE ");
if (ndlp->nlp_type & NLP_FC_NODE)
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 51cb8571c049..de0adeecf668 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -77,6 +77,11 @@ struct lpfc_node_rrqs {
unsigned long xri_bitmap[XRI_BITMAP_ULONGS];
};
+struct lpfc_enc_info {
+ u8 status; /* encryption status for session */
+ u8 level; /* CNSA encryption level */
+};
+
enum lpfc_fc4_xpt_flags {
NLP_XPT_REGD = 0x1,
SCSI_XPT_REGD = 0x2,
@@ -138,6 +143,8 @@ struct lpfc_nodelist {
uint8_t vmid_support; /* destination VMID support */
#define NLP_NVME_NSLER 0x1 /* NVME NSLER device */
+ struct lpfc_enc_info nlp_enc_info; /* Encryption information struct */
+
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct lpfc_hba *phba;
struct fc_rport *rport; /* scsi_transport_fc port structure */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 02b6d31b9ad9..32da3c23c7f4 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2014,6 +2014,58 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_nlp_put(ndlp);
return;
}
+
+/**
+ * lpfc_check_encryption - Reports an ndlp's encryption information
+ * @phba: pointer to lpfc hba data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @cmdiocb: pointer to lpfc command iocbq data structure.
+ * @rspiocb: pointer to lpfc response iocbq data structure.
+ *
+ * This routine is called in the completion callback function for issuing
+ * or receiving a Port Login (PLOGI) command. In a PLOGI completion, if FEDIF
+ * is supported, encryption information will be provided in completion status
+ * data. If @phba supports FEDIF, a log message containing encryption
+ * information will be logged. Encryption status is also saved for encryption
+ * reporting with upper layer through the rport encryption attribute.
+ **/
+static void
+lpfc_check_encryption(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb)
+{
+ struct lpfc_vport *vport = cmdiocb->vport;
+ u32 did = ndlp->nlp_DID;
+ struct lpfc_enc_info *nlp_enc_info = &ndlp->nlp_enc_info;
+ char enc_status[FC_RPORT_ENCRYPTION_STATUS_MAX_LEN] = {0};
+ char enc_level[8] = "N/A";
+ u8 encryption;
+
+ if (phba->sli4_hba.encryption_support &&
+ ((did & Fabric_DID_MASK) != Fabric_DID_MASK)) {
+ encryption = bf_get(lpfc_wcqe_c_enc,
+ &rspiocb->wcqe_cmpl);
+ nlp_enc_info->status = encryption;
+
+ strscpy(enc_status, encryption ? "Encrypted" : "Unencrypted",
+ sizeof(enc_status));
+
+ if (encryption) {
+ nlp_enc_info->level = bf_get(lpfc_wcqe_c_enc_lvl,
+ &rspiocb->wcqe_cmpl);
+ strscpy(enc_level, nlp_enc_info->level ? "CNSA2.0" :
+ "CNSA1.0",
+ sizeof(enc_level));
+ }
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ENCRYPTION,
+ "0924 DID:x%06x %s Session "
+ "Established, Encryption Level:%s "
+ "rpi:x%x\n",
+ ndlp->nlp_DID, enc_status, enc_level,
+ ndlp->nlp_rpi);
+ }
+}
+
/**
* lpfc_cmpl_els_plogi - Completion callback function for plogi
* @phba: pointer to lpfc hba data structure.
@@ -2153,6 +2205,8 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
+ lpfc_check_encryption(phba, ndlp, cmdiocb, rspiocb);
+
sp = (struct serv_parm *)((u8 *)prsp->virt +
sizeof(u32));
@@ -5407,6 +5461,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
}
+ if (!ulp_status && test_bit(NLP_RCV_PLOGI, &ndlp->nlp_flag))
+ lpfc_check_encryption(phba, ndlp, cmdiocb, rspiocb);
+
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"ELS rsp cmpl: status:x%x/x%x did:x%x",
ulp_status, ulp_word4, did);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bb803f32bc1b..1aeebdc08073 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -5340,6 +5340,7 @@ out:
clear_bit(NLP_NPR_ADISC, &ndlp->nlp_flag);
if (acc_plogi)
clear_bit(NLP_LOGO_ACC, &ndlp->nlp_flag);
+ memset(&ndlp->nlp_enc_info, 0, sizeof(ndlp->nlp_enc_info));
return 1;
}
clear_bit(NLP_LOGO_ACC, &ndlp->nlp_flag);
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index a7f7ed86d2b0..c000474c3066 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -437,6 +437,12 @@ struct lpfc_wcqe_complete {
#define lpfc_wcqe_c_cmf_bw_MASK 0x0FFFFFFF
#define lpfc_wcqe_c_cmf_bw_WORD total_data_placed
uint32_t parameter;
+#define lpfc_wcqe_c_enc_SHIFT 31
+#define lpfc_wcqe_c_enc_MASK 0x00000001
+#define lpfc_wcqe_c_enc_WORD parameter
+#define lpfc_wcqe_c_enc_lvl_SHIFT 30
+#define lpfc_wcqe_c_enc_lvl_MASK 0x00000001
+#define lpfc_wcqe_c_enc_lvl_WORD parameter
#define lpfc_wcqe_c_bg_edir_SHIFT 5
#define lpfc_wcqe_c_bg_edir_MASK 0x00000001
#define lpfc_wcqe_c_bg_edir_WORD parameter
@@ -2942,7 +2948,10 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
- uint32_t rsvd_3;
+ uint32_t word3;
+#define lpfc_mbx_rd_conf_fedif_SHIFT 6
+#define lpfc_mbx_rd_conf_fedif_MASK 0x00000001
+#define lpfc_mbx_rd_conf_fedif_WORD word3
uint32_t word4;
#define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0
#define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b1460b16dd91..a116a16c4a6f 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9999,6 +9999,11 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
(phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
phba->max_vports = phba->max_vpi;
+ if (bf_get(lpfc_mbx_rd_conf_fedif, rd_config))
+ phba->sli4_hba.encryption_support = true;
+ else
+ phba->sli4_hba.encryption_support = false;
+
/* Next decide on FPIN or Signal E2E CGN support
* For congestion alarms and warnings valid combination are:
* 1. FPIN alarms / FPIN warnings
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index 59bd2bafc73f..e00d101d548c 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-2023 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-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -47,6 +47,7 @@
#define LOG_RSVD1 0x01000000 /* Reserved */
#define LOG_RSVD2 0x02000000 /* Reserved */
#define LOG_CGN_MGMT 0x04000000 /* Congestion Mgmt events */
+#define LOG_ENCRYPTION 0x40000000 /* EDIF Encryption events. */
#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */
#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index fd6dab157887..ee58383492b2 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -888,6 +888,10 @@ struct lpfc_sli4_hba {
#define LPFC_FP_EQ_MAX_INTR_SEC 10000
uint32_t intr_enable;
+
+ /* Indicates whether SLI Port supports FEDIF */
+ bool encryption_support;
+
struct lpfc_bmbx bmbx;
struct lpfc_max_cfg_param max_cfg_param;
uint16_t extents_in_use; /* must allocate resource extents. */
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index f3dada5bf7c1..c4ca8bf5843a 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.4.0.12"
+#define LPFC_DRIVER_VERSION "14.4.0.13"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 987befb02408..b95c46a346fb 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1328,6 +1328,46 @@ store_fc_rport_fast_io_fail_tmo(struct device *dev,
static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
+#define fc_rport_encryption(name) \
+static ssize_t fc_rport_encinfo_##name(struct device *cd, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct fc_rport *rport = transport_class_to_rport(cd); \
+ struct Scsi_Host *shost = rport_to_shost(rport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ struct fc_encryption_info *info; \
+ ssize_t ret = -ENOENT; \
+ u32 data; \
+ \
+ if (i->f->get_fc_rport_enc_info) { \
+ info = (i->f->get_fc_rport_enc_info)(rport); \
+ if (info) { \
+ data = info->name; \
+ if (!strcmp(#name, "status")) { \
+ ret = scnprintf(buf, \
+ FC_RPORT_ENCRYPTION_STATUS_MAX_LEN, \
+ "%s\n", \
+ data ? "Encrypted" : "Unencrypted"); \
+ } \
+ } \
+ } \
+ return ret; \
+} \
+static FC_DEVICE_ATTR(rport, encryption_##name, 0444, fc_rport_encinfo_##name, NULL) \
+
+fc_rport_encryption(status);
+
+static struct attribute *fc_rport_encryption_attrs[] = {
+ &device_attr_rport_encryption_status.attr,
+ NULL
+};
+
+static struct attribute_group fc_rport_encryption_group = {
+ .name = "encryption",
+ .attrs = fc_rport_encryption_attrs,
+};
+
#define fc_rport_fpin_statistic(name) \
static ssize_t fc_rport_fpinstat_##name(struct device *cd, \
struct device_attribute *attr, \
@@ -2633,6 +2673,8 @@ fc_attach_transport(struct fc_function_template *ft)
i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
i->rport_attr_cont.ac.class = &fc_rport_class.class;
i->rport_attr_cont.ac.match = fc_rport_match;
+ if (ft->get_fc_rport_enc_info)
+ i->rport_attr_cont.encryption = &fc_rport_encryption_group;
i->rport_attr_cont.statistics = &fc_rport_statistics_group;
transport_container_register(&i->rport_attr_cont);
diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
index 2efc271a96fa..a009d66db15a 100644
--- a/include/linux/transport_class.h
+++ b/include/linux/transport_class.h
@@ -56,6 +56,7 @@ struct anon_transport_class cls = { \
struct transport_container {
struct attribute_container ac;
const struct attribute_group *statistics;
+ const struct attribute_group *encryption;
};
#define attribute_container_to_transport_container(x) \
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index b908aacfef48..9f30625aa0d3 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -317,6 +317,15 @@ struct fc_fpin_stats {
u64 cn_device_specific;
};
+#define FC_RPORT_ENCRYPTION_STATUS_MAX_LEN 14
+/*
+ * Encryption Information
+ */
+struct fc_encryption_info {
+ /* Encryption Status */
+ u8 status;
+};
+
/* Macro for use in defining Remote Port attributes */
#define FC_RPORT_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_rport_##_name = \
@@ -364,6 +373,7 @@ struct fc_rport { /* aka fc_starget_attrs */
u64 port_name;
u32 port_id;
u32 roles;
+ struct fc_encryption_info enc_info;
enum fc_port_state port_state; /* Will only be ONLINE or UNKNOWN */
u32 scsi_target_id;
u32 fast_io_fail_tmo;
@@ -691,6 +701,8 @@ struct fc_function_template {
struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
void (*reset_fc_host_stats)(struct Scsi_Host *);
+ struct fc_encryption_info * (*get_fc_rport_enc_info)(struct fc_rport *);
+
int (*issue_fc_host_lip)(struct Scsi_Host *);
void (*dev_loss_tmo_callbk)(struct fc_rport *);