[PATCH 15/23] net: hpe: sl: add the NIC binding and logging helpers
From: Doug Ledford
Date: Fri Oct 30 2026 - 17:08:26 EST
Add the glue that binds SL to a NIC: ASIC and CSR definitions, the NIC
logical device and media hooks, and the logging helpers.
sl_asic_csrs.h is generated from the hardware register description and
is kept in that form; its integer types were converted to the kernel
types in the same pass as the other UAPI/header cleanups.
checkpatch --strict (100 columns) still reports the following in this
patch. They need coordination with the internal repositories this code
is maintained in and will be fixed in V2:
- WARNING: LONG_LINE (18)
- CHECK: UNNECESSARY_PARENTHESES (16), COMPARISON_TO_NULL (3)
Co-developed-by: Sandeep Bhoot <sandeep.bhoot@xxxxxxx>
Signed-off-by: Sandeep Bhoot <sandeep.bhoot@xxxxxxx>
Signed-off-by: Doug Ledford <doug.ledford@xxxxxxx>
---
drivers/net/ethernet/hpe/sl/log/sl_log.c | 566 +++++++++++++++++++++++++++++
drivers/net/ethernet/hpe/sl/nic/sl_ldev.c | 147 ++++++++
drivers/net/ethernet/hpe/sl/nic/sl_media.c | 53 +++
3 files changed, 766 insertions(+)
diff --git a/drivers/net/ethernet/hpe/sl/log/sl_log.c b/drivers/net/ethernet/hpe/sl/log/sl_log.c
new file mode 100644
index 000000000000..64382f9b46bb
--- /dev/null
+++ b/drivers/net/ethernet/hpe/sl/log/sl_log.c
@@ -0,0 +1,566 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2022-2026 Hewlett Packard Enterprise Development LP */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#include "sl_asic.h"
+
+#include "sl_log.h"
+
+#include "sl_ldev.h"
+#include "sl_lgrp.h"
+#include "sl_link.h"
+#include "sl_llr.h"
+#include "sl_mac.h"
+
+#include "sl_ctrl_ldev.h"
+#include "sl_ctrl_lgrp.h"
+#include "sl_ctrl_link.h"
+#include "sl_ctrl_llr.h"
+#include "sl_ctrl_mac.h"
+
+#include "sl_core_ldev.h"
+#include "sl_core_lgrp.h"
+#include "sl_core_link.h"
+#include "sl_core_mac.h"
+#include "sl_core_llr.h"
+
+#include "sl_media_ldev.h"
+#include "sl_media_lgrp.h"
+#include "sl_media_jack.h"
+
+#include "data/sl_ctrl_data_lgrp_trace.h"
+
+#include "hw/sl_core_hw_intr.h"
+#include "data/sl_core_data_link.h"
+#include "data/sl_core_data_lgrp.h"
+#include "data/sl_core_data_lgrp_trace.h"
+#include "data/sl_core_data_ldev.h"
+
+#include "data/sl_media_data_lgrp_trace.h"
+
+#define SL_LOG_MSG_LEN 150
+#define SL_LOG_NULL_ID_FMT "%c[-:--:-] ??? "
+#define SL_LOG_DFLT_ID_FMT "%c[-:--:-] 0x%08X "
+#define SL_LOG_LDEV_ID_FMT "%c[%1u:--:-] ldev%1u "
+#define SL_LOG_LGRP_ID_FMT "%c[%1u:%02u:-] %-12s"
+#define SL_LOG_LINK_ID_FMT "%c[%1u:%02u:%1u] %-12s"
+#define SL_LOG_JACK_ID_FMT "%c[-:--:-] jack%03u "
+#define SL_LOG_CONTEXT (in_interrupt() ? '^' : ' ')
+
+static int remaining_chars(int idx)
+{
+ return max(SL_LOG_MSG_LEN - idx, 0);
+}
+
+static void sl_log_msg_create(const char *level, void *ptr, char *msg,
+ const char *block, const char *name, const char *text)
+{
+ struct sl_ldev *ldev;
+ struct sl_lgrp *lgrp;
+ struct sl_link *link;
+ struct sl_llr *llr;
+ struct sl_mac *mac;
+ struct sl_ctrl_ldev *ctrl_ldev;
+ struct sl_ctrl_lgrp *ctrl_lgrp;
+ struct sl_ctrl_link *ctrl_link;
+ struct sl_ctrl_llr *ctrl_llr;
+ struct sl_ctrl_mac *ctrl_mac;
+ struct sl_core_ldev *core_ldev;
+ struct sl_core_lgrp *core_lgrp;
+ struct sl_core_link *core_link;
+ struct sl_core_mac *core_mac;
+ struct sl_core_llr *core_llr;
+ struct sl_media_ldev *media_ldev;
+ struct sl_media_lgrp *media_lgrp;
+ struct sl_media_jack *media_jack;
+ int idx;
+ unsigned long irq_flags;
+
+ idx = snprintf(msg, SL_LOG_MSG_LEN, "%s%s", level, module_name(THIS_MODULE));
+ if (ptr != NULL) {
+ switch (*((u32 *)ptr)) {
+ case SL_LDEV_MAGIC:
+ ldev = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LDEV_ID_FMT,
+ SL_LOG_CONTEXT,
+ ldev->num, ldev->num);
+ break;
+ case SL_LGRP_MAGIC:
+ lgrp = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LGRP_ID_FMT,
+ SL_LOG_CONTEXT,
+ lgrp->ldev_num, lgrp->num, "lgrp");
+ break;
+ case SL_LINK_MAGIC:
+ link = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ link->ldev_num, link->lgrp_num, link->num, "link");
+ break;
+ case SL_LLR_MAGIC:
+ llr = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ llr->ldev_num, llr->lgrp_num, llr->num, "llr");
+ break;
+ case SL_MAC_MAGIC:
+ mac = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ mac->ldev_num, mac->lgrp_num, mac->num, "mac");
+ break;
+ case SL_CTRL_LDEV_MAGIC:
+ ctrl_ldev = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LDEV_ID_FMT,
+ SL_LOG_CONTEXT,
+ ctrl_ldev->num, ctrl_ldev->num);
+ break;
+ case SL_CTRL_LGRP_MAGIC:
+ ctrl_lgrp = ptr;
+ spin_lock_irqsave(&(ctrl_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LGRP_ID_FMT,
+ SL_LOG_CONTEXT,
+ ctrl_lgrp->ctrl_ldev->num, ctrl_lgrp->num,
+ ctrl_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(ctrl_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CTRL_LINK_MAGIC:
+ ctrl_link = ptr;
+ spin_lock_irqsave(&(ctrl_link->ctrl_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ ctrl_link->ctrl_lgrp->ctrl_ldev->num, ctrl_link->ctrl_lgrp->num, ctrl_link->num,
+ ctrl_link->ctrl_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(ctrl_link->ctrl_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CTRL_LLR_MAGIC:
+ ctrl_llr = ptr;
+ spin_lock_irqsave(&(ctrl_llr->ctrl_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ ctrl_llr->ctrl_lgrp->ctrl_ldev->num, ctrl_llr->ctrl_lgrp->num, ctrl_llr->num,
+ ctrl_llr->ctrl_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(ctrl_llr->ctrl_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CTRL_MAC_MAGIC:
+ ctrl_mac = ptr;
+ spin_lock_irqsave(&(ctrl_mac->ctrl_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ ctrl_mac->ctrl_lgrp->ctrl_ldev->num, ctrl_mac->ctrl_lgrp->num, ctrl_mac->num,
+ ctrl_mac->ctrl_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(ctrl_mac->ctrl_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CORE_LDEV_MAGIC:
+ core_ldev = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LDEV_ID_FMT,
+ SL_LOG_CONTEXT,
+ core_ldev->num, core_ldev->num);
+ break;
+ case SL_CORE_LGRP_MAGIC:
+ core_lgrp = ptr;
+ spin_lock_irqsave(&(core_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LGRP_ID_FMT,
+ SL_LOG_CONTEXT,
+ core_lgrp->core_ldev->num, core_lgrp->num,
+ core_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(core_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CORE_LINK_MAGIC:
+ core_link = ptr;
+ spin_lock_irqsave(&(core_link->core_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ core_link->core_lgrp->core_ldev->num, core_link->core_lgrp->num, core_link->num,
+ core_link->core_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(core_link->core_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CORE_MAC_MAGIC:
+ core_mac = ptr;
+ spin_lock_irqsave(&(core_mac->core_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ core_mac->core_lgrp->core_ldev->num, core_mac->core_lgrp->num, core_mac->num,
+ core_mac->core_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(core_mac->core_lgrp->log_lock), irq_flags);
+ break;
+ case SL_CORE_LLR_MAGIC:
+ core_llr = ptr;
+ spin_lock_irqsave(&(core_llr->core_lgrp->log_lock), irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LINK_ID_FMT,
+ SL_LOG_CONTEXT,
+ core_llr->core_lgrp->core_ldev->num, core_llr->core_lgrp->num, core_llr->num,
+ core_llr->core_lgrp->log_connect_id);
+ spin_unlock_irqrestore(&(core_llr->core_lgrp->log_lock), irq_flags);
+ break;
+ case SL_MEDIA_LDEV_MAGIC:
+ media_ldev = ptr;
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LDEV_ID_FMT,
+ SL_LOG_CONTEXT,
+ media_ldev->num, media_ldev->num);
+ break;
+ case SL_MEDIA_LGRP_MAGIC:
+ media_lgrp = ptr;
+ spin_lock_irqsave(&media_lgrp->log_lock, irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_LGRP_ID_FMT,
+ SL_LOG_CONTEXT,
+ media_lgrp->media_ldev->num, media_lgrp->num,
+ media_lgrp->connect_id);
+ spin_unlock_irqrestore(&media_lgrp->log_lock, irq_flags);
+ break;
+ case SL_MEDIA_JACK_MAGIC:
+ media_jack = ptr;
+ spin_lock_irqsave(&media_jack->log_lock, irq_flags);
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_JACK_ID_FMT,
+ SL_LOG_CONTEXT,
+ media_jack->physical_num);
+ spin_unlock_irqrestore(&media_jack->log_lock, irq_flags);
+ break;
+ default:
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_DFLT_ID_FMT,
+ SL_LOG_CONTEXT,
+ *((u32 *)ptr));
+ break;
+ }
+ } else {
+ idx += snprintf(msg + idx, remaining_chars(idx), SL_LOG_NULL_ID_FMT,
+ SL_LOG_CONTEXT);
+ }
+
+ snprintf(msg + idx, remaining_chars(idx), " %5s-%-10s: %s\n", block, name, text);
+}
+
+void sl_log(void *ptr, const char *level, const char *block,
+ const char *name, const char *text, ...)
+{
+ char msg[SL_LOG_MSG_LEN + 1];
+ va_list args;
+
+ if (!level) {
+ pr_err("NULL level\n");
+ return;
+ }
+ if (!block) {
+ pr_err("NULL block\n");
+ return;
+ }
+ if (!name) {
+ pr_err("NULL name\n");
+ return;
+ }
+ if (!text) {
+ pr_err("NULL text\n");
+ return;
+ }
+
+ sl_log_msg_create(level, ptr, msg, block, name, text);
+
+ va_start(args, text);
+ vprintk(msg, args);
+ va_end(args);
+}
+
+void sl_log_err_trace(void *ptr, const char *block,
+ const char *name, const char *text, ...)
+{
+ int rtn;
+ char msg[SL_LOG_MSG_LEN + 1];
+ va_list args;
+ struct sl_ctrl_lgrp *ctrl_lgrp;
+ struct sl_ctrl_link *ctrl_link;
+ struct sl_ctrl_llr *ctrl_llr;
+ struct sl_ctrl_mac *ctrl_mac;
+ struct sl_core_lgrp *core_lgrp;
+ struct sl_core_link *core_link;
+ struct sl_core_mac *core_mac;
+ struct sl_core_llr *core_llr;
+ struct sl_media_lgrp *media_lgrp;
+ bool err_trace_enable;
+
+ if (!block) {
+ pr_err("NULL block\n");
+ return;
+ }
+ if (!name) {
+ pr_err("NULL name\n");
+ return;
+ }
+ if (!text) {
+ pr_err("NULL text\n");
+ return;
+ }
+
+ if (ptr == NULL)
+ return;
+
+ switch (*((u32 *)ptr)) {
+ case SL_CTRL_LGRP_MAGIC:
+ ctrl_lgrp = ptr;
+ rtn = sl_ctrl_data_lgrp_is_err_trace_enabled(ctrl_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CTRL_LINK_MAGIC:
+ ctrl_link = ptr;
+ rtn = sl_ctrl_data_lgrp_is_err_trace_enabled(ctrl_link->ctrl_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CTRL_LLR_MAGIC:
+ ctrl_llr = ptr;
+ rtn = sl_ctrl_data_lgrp_is_err_trace_enabled(ctrl_llr->ctrl_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CTRL_MAC_MAGIC:
+ ctrl_mac = ptr;
+ rtn = sl_ctrl_data_lgrp_is_err_trace_enabled(ctrl_mac->ctrl_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CORE_LGRP_MAGIC:
+ core_lgrp = ptr;
+ rtn = sl_core_data_lgrp_is_err_trace_enabled(core_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CORE_LINK_MAGIC:
+ core_link = ptr;
+ rtn = sl_core_data_lgrp_is_err_trace_enabled(core_link->core_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CORE_MAC_MAGIC:
+ core_mac = ptr;
+ rtn = sl_core_data_lgrp_is_err_trace_enabled(core_mac->core_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_CORE_LLR_MAGIC:
+ core_llr = ptr;
+ rtn = sl_core_data_lgrp_is_err_trace_enabled(core_llr->core_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ case SL_MEDIA_LGRP_MAGIC:
+ media_lgrp = ptr;
+ rtn = sl_media_data_lgrp_is_err_trace_enabled(media_lgrp, &err_trace_enable);
+ if (rtn)
+ return;
+ if (!err_trace_enable)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ sl_log_msg_create(KERN_ERR, ptr, msg, block, name, text);
+
+ va_start(args, text);
+ vprintk(msg, args);
+ va_end(args);
+}
+
+void sl_log_warn_trace(void *ptr, const char *block,
+ const char *name, const char *text, ...)
+{
+ int rtn;
+ char msg[SL_LOG_MSG_LEN + 1];
+ va_list args;
+ struct sl_ctrl_lgrp *ctrl_lgrp;
+ struct sl_ctrl_link *ctrl_link;
+ struct sl_ctrl_llr *ctrl_llr;
+ struct sl_ctrl_mac *ctrl_mac;
+ struct sl_core_lgrp *core_lgrp;
+ struct sl_core_link *core_link;
+ struct sl_core_mac *core_mac;
+ struct sl_core_llr *core_llr;
+ struct sl_media_lgrp *media_lgrp;
+ bool warn_trace_enable;
+
+ if (!block) {
+ pr_err("NULL block\n");
+ return;
+ }
+ if (!name) {
+ pr_err("NULL name\n");
+ return;
+ }
+ if (!text) {
+ pr_err("NULL text\n");
+ return;
+ }
+
+ if (ptr == NULL)
+ return;
+
+ switch (*((u32 *)ptr)) {
+ case SL_CTRL_LGRP_MAGIC:
+ ctrl_lgrp = ptr;
+ rtn = sl_ctrl_data_lgrp_is_warn_trace_enabled(ctrl_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CTRL_LINK_MAGIC:
+ ctrl_link = ptr;
+ rtn = sl_ctrl_data_lgrp_is_warn_trace_enabled(ctrl_link->ctrl_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CTRL_LLR_MAGIC:
+ ctrl_llr = ptr;
+ rtn = sl_ctrl_data_lgrp_is_warn_trace_enabled(ctrl_llr->ctrl_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CTRL_MAC_MAGIC:
+ ctrl_mac = ptr;
+ rtn = sl_ctrl_data_lgrp_is_warn_trace_enabled(ctrl_mac->ctrl_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CORE_LGRP_MAGIC:
+ core_lgrp = ptr;
+ rtn = sl_core_data_lgrp_is_warn_trace_enabled(core_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CORE_LINK_MAGIC:
+ core_link = ptr;
+ rtn = sl_core_data_lgrp_is_warn_trace_enabled(core_link->core_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CORE_MAC_MAGIC:
+ core_mac = ptr;
+ rtn = sl_core_data_lgrp_is_warn_trace_enabled(core_mac->core_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_CORE_LLR_MAGIC:
+ core_llr = ptr;
+ rtn = sl_core_data_lgrp_is_warn_trace_enabled(core_llr->core_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ case SL_MEDIA_LGRP_MAGIC:
+ media_lgrp = ptr;
+ rtn = sl_media_data_lgrp_is_warn_trace_enabled(media_lgrp, &warn_trace_enable);
+ if (rtn)
+ return;
+ if (!warn_trace_enable)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ sl_log_msg_create(KERN_WARNING, ptr, msg, block, name, text);
+
+ va_start(args, text);
+ vprintk(msg, args);
+ va_end(args);
+}
+
+void sl_log_io_trace(void *ptr, const char *block, const char *name, const char *text, ...)
+{
+ char msg[SL_LOG_MSG_LEN + 1];
+ va_list args;
+ struct sl_core_lgrp *core_lgrp;
+
+ if (!block) {
+ pr_err("NULL block\n");
+ return;
+ }
+ if (!name) {
+ pr_err("NULL name\n");
+ return;
+ }
+ if (!text) {
+ pr_err("NULL text\n");
+ return;
+ }
+
+ if (!ptr)
+ return;
+
+ switch (*((u32 *)ptr)) {
+ case SL_CORE_LGRP_MAGIC:
+ core_lgrp = ptr;
+ if (!sl_core_data_lgrp_is_io_trace_enabled(core_lgrp))
+ return;
+ break;
+ default:
+ return;
+ }
+
+ sl_log_msg_create(KERN_INFO, ptr, msg, block, name, text);
+
+ va_start(args, text);
+ vprintk(msg, args);
+ va_end(args);
+}
+
+void __sl_log_dynamic_dbg(struct _ddebug *desc, void *ptr, const char *block,
+ const char *name, const char *text, ...)
+{
+ char msg[SL_LOG_MSG_LEN + 1];
+ va_list args;
+
+ if (!desc) {
+ pr_err("NULL desc\n");
+ return;
+ }
+ if (!block) {
+ pr_err("NULL desc\n");
+ return;
+ }
+ if (!name) {
+ pr_err("NULL name\n");
+ return;
+ }
+ if (!text) {
+ pr_err("NULL text\n");
+ return;
+ }
+
+ sl_log_msg_create(KERN_DEBUG, ptr, msg, block, name, text);
+
+ va_start(args, text);
+ vprintk(msg, args);
+ va_end(args);
+}
diff --git a/drivers/net/ethernet/hpe/sl/nic/sl_ldev.c b/drivers/net/ethernet/hpe/sl/nic/sl_ldev.c
new file mode 100644
index 000000000000..e93cd667dab8
--- /dev/null
+++ b/drivers/net/ethernet/hpe/sl/nic/sl_ldev.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2025 Hewlett Packard Enterprise Development LP */
+
+#include <linux/module.h>
+
+#include <linux/hpe/sl/sl_ldev.h>
+
+#include "sl_log.h"
+#include "sl_ldev.h"
+#include "sl_media_ldev.h"
+
+#define LOG_BLOCK SL_LOG_BLOCK
+#define LOG_NAME SL_LOG_LDEV_LOG_NAME
+
+int sl_ldev_attr_check(struct sl_ldev_attr *ldev_attr)
+{
+ if (!ldev_attr) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ldev_attr");
+ return -EINVAL;
+ }
+ if (IS_ERR(ldev_attr)) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "ldev_attr pointer error");
+ return -EINVAL;
+ }
+ if (ldev_attr->magic != SL_LDEV_ATTR_MAGIC) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "bad ldev_attr magic");
+ return -EINVAL;
+ }
+ if (ldev_attr->ver != SL_LDEV_ATTR_VER) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "bad ldev_attr version");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ldev_attr ops");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ldev_attr accessors");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->read64) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops read64");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->write64) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops write64");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->sbus_op) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops sbus_op");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->pmi_op) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops pmi_op");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->pml_intr_register) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops pml_intr_register");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->pml_intr_unregister) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops pml_intr_unregister");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->pml_intr_enable) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops pml_intr_enable");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->pml_intr_disable) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops pml_intr_disable");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->dt_info_get) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops dt_info_get");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->mb_info_get) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops mb_info_get");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->dmac_alloc) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops dmac_alloc");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->dmac_free) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops dmac_free");
+ return -EINVAL;
+ }
+ if (!ldev_attr->ops->dmac_xfer) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL ops dmac_xfer");
+ return -EINVAL;
+ }
+
+ if (!ldev_attr->accessors->pci) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor PCI");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors->sbus) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor SBUS");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors->pmi) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor PMI");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors->intr) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor INTR");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors->dt) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor DT");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors->mb) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor MB");
+ return -EINVAL;
+ }
+ if (!ldev_attr->accessors->dmac) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL accessor DMAC");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int sl_ldev_uc_ops_set(struct sl_ldev *ldev, struct sl_uc_ops *uc_ops,
+ struct sl_uc_accessor *uc_accessor)
+{
+ int rtn;
+
+ rtn = sl_ldev_check(ldev);
+ if (rtn) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "check fail");
+ return rtn;
+ }
+
+ sl_log_dbg(ldev, LOG_BLOCK, LOG_NAME, "uc ops_set");
+
+ rtn = sl_media_ldev_uc_ops_set(ldev->num, uc_ops, uc_accessor);
+ if (rtn) {
+ sl_log_err(ldev, LOG_BLOCK, LOG_NAME, "media_ldev_uc_ops_set failed [%d]", rtn);
+ return rtn;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sl_ldev_uc_ops_set);
diff --git a/drivers/net/ethernet/hpe/sl/nic/sl_media.c b/drivers/net/ethernet/hpe/sl/nic/sl_media.c
new file mode 100644
index 000000000000..dddfaef0cb28
--- /dev/null
+++ b/drivers/net/ethernet/hpe/sl/nic/sl_media.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2024,2025 Hewlett Packard Enterprise Development LP */
+
+#include <linux/module.h>
+
+#include <linux/hpe/sl/sl_media.h>
+
+#include "base/sl_media_log.h"
+#include "sl_lgrp.h"
+#include "sl_media_lgrp.h"
+#include "sl_media_jack.h"
+
+#define LOG_BLOCK SL_LOG_BLOCK
+#define LOG_NAME SL_LOG_MEDIA_LOG_NAME
+
+int sl_media_cable_insert(struct sl_lgrp *lgrp, u8 *eeprom_page0, u8 *eeprom_page1, u32 flags)
+{
+ int rtn;
+
+ rtn = sl_lgrp_check(lgrp);
+ if (rtn) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "cable insert fail");
+ return rtn;
+ }
+ if (!eeprom_page0) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "NULL eeprom");
+ return -EINVAL;
+ }
+
+ /*
+ * hardcoding 0 for now since there is only one jack. Might change in future
+ */
+ return sl_media_jack_cable_insert(lgrp->ldev_num, lgrp->num, 0, eeprom_page0,
+ eeprom_page1, flags);
+}
+EXPORT_SYMBOL(sl_media_cable_insert);
+
+int sl_media_cable_remove(struct sl_lgrp *lgrp)
+{
+ int rtn;
+
+ rtn = sl_lgrp_check(lgrp);
+ if (rtn) {
+ sl_log_err(NULL, LOG_BLOCK, LOG_NAME, "cable remove fail");
+ return rtn;
+ }
+
+ /*
+ * hardcoding 0 for now since there is only one jack. Might change in future
+ */
+ return sl_media_jack_cable_remove(lgrp->ldev_num, lgrp->num, 0);
+}
+EXPORT_SYMBOL(sl_media_cable_remove);
--
2.56.0