git: 8b2e75970c03 - main - ixl: Add led(4) identification support
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 12 Aug 2026 03:20:22 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=8b2e75970c0328e7397290417cc06e9d9c763d2a
commit 8b2e75970c0328e7397290417cc06e9d9c763d2a
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-12 00:54:21 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-12 03:16:08 +0000
ixl: Add led(4) identification support
Expose each physical port identification LED through /dev/led/ixl*.
Use the existing GPIO LED helpers for most devices and the PHY
provisioning interface for X710 10GBASE-T adapters.
Preserve and restore the original GPIO or PHY indication mode,
including before the interface is stopped.
MFC after: 2 weeks
---
share/man/man4/ixl.4 | 7 ++++-
sys/dev/ixl/if_ixl.c | 78 +++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/ixl/ixl_pf.h | 5 +++
sys/dev/ixl/ixl_pf_iflib.c | 2 ++
4 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/share/man/man4/ixl.4 b/share/man/man4/ixl.4
index 37d8c0cf5db8..b9c22e8b9b9c 100644
--- a/share/man/man4/ixl.4
+++ b/share/man/man4/ixl.4
@@ -29,7 +29,7 @@
.\"
.\" * Other names and brands may be claimed as the property of others.
.\"
-.Dd August 9, 2026
+.Dd August 12, 2026
.Dt IXL 4
.Os
.Sh NAME
@@ -88,6 +88,10 @@ and/or TSO6, and finally LRO can be set and unset.
.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
+.Pp
+The identification LED for each port is controlled through its
+.Pa /dev/led/ixl*
+device node.
.Ss Additional Utilities
There are additional tools available from Intel to help configure and update
the adapters covered by this driver.
@@ -301,6 +305,7 @@ email all the specific information related to the issue to
.Xr arp 4 ,
.Xr iavf 4 ,
.Xr iflib 4 ,
+.Xr led 4 ,
.Xr netintro 4 ,
.Xr vlan 4 ,
.Xr ifconfig 8 ,
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index 953882287386..886a4e52303c 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -122,6 +122,7 @@ static uint64_t ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt);
static int ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req);
static int ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data);
static bool ixl_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event);
+static void ixl_if_led_func(if_ctx_t ctx, int onoff);
#ifdef PCI_IOV
static void ixl_if_vflr_handle(if_ctx_t ctx);
#endif
@@ -193,13 +194,13 @@ static device_method_t ixl_if_methods[] = {
DEVMETHOD(ifdi_i2c_req, ixl_if_i2c_req),
DEVMETHOD(ifdi_priv_ioctl, ixl_if_priv_ioctl),
DEVMETHOD(ifdi_needs_restart, ixl_if_needs_restart),
+ DEVMETHOD(ifdi_led_func, ixl_if_led_func),
#ifdef PCI_IOV
DEVMETHOD(ifdi_iov_init, ixl_if_iov_init),
DEVMETHOD(ifdi_iov_uninit, ixl_if_iov_uninit),
DEVMETHOD(ifdi_iov_vf_add, ixl_if_iov_vf_add),
DEVMETHOD(ifdi_vflr_handle, ixl_if_vflr_handle),
#endif
- // ifdi_led_func
// ifdi_debug
DEVMETHOD_END
};
@@ -1063,6 +1064,7 @@ ixl_if_stop(if_ctx_t ctx)
INIT_DEBUGOUT("ixl_if_stop: begin\n");
+ ixl_led_restore(pf);
if (IXL_PF_IN_RECOVERY_MODE(pf))
return;
@@ -1085,6 +1087,80 @@ ixl_if_stop(if_ctx_t ctx)
ixl_set_link(pf, false);
}
+#define IXL_PHY_DEBUG_ALL \
+ (I40E_AQ_PHY_DEBUG_DISABLE_LINK_FW | \
+ I40E_AQ_PHY_DEBUG_DISABLE_ALL_LINK_FW)
+
+static bool
+ixl_phy_controls_leds(const struct i40e_hw *hw)
+{
+
+ /* These external 10GBASE-T PHYs own the identification LED. */
+ return (hw->device_id == I40E_DEV_ID_10G_BASE_T ||
+ hw->device_id == I40E_DEV_ID_10G_BASE_T4);
+}
+
+static void
+ixl_if_led_func(if_ctx_t ctx, int onoff)
+{
+ struct ixl_pf *pf;
+ struct i40e_hw *hw;
+ enum i40e_status_code status;
+ u16 phy_status;
+
+ pf = iflib_get_softc(ctx);
+ hw = &pf->hw;
+ if (!onoff) {
+ ixl_led_restore(pf);
+ return;
+ }
+ if (pf->led_active)
+ return;
+
+ pf->led_phy_controlled = ixl_phy_controls_leds(hw);
+ if (!pf->led_phy_controlled) {
+ pf->led_status = i40e_led_get(hw);
+ pf->led_active = true;
+ i40e_led_set(hw, 0xf, false);
+ return;
+ }
+
+ if ((hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) == 0)
+ (void)i40e_aq_set_phy_debug(hw, IXL_PHY_DEBUG_ALL, NULL);
+ pf->led_phy_addr = I40E_PHY_LED_PROV_REG_1;
+ status = i40e_led_get_phy(hw, &pf->led_phy_addr, &phy_status);
+ if (status != I40E_SUCCESS) {
+ if ((hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) == 0)
+ (void)i40e_aq_set_phy_debug(hw, 0, NULL);
+ return;
+ }
+ pf->led_status = phy_status;
+ pf->led_active = true;
+ status = i40e_led_set_phy(hw, true, pf->led_phy_addr, 0);
+ if (status != I40E_SUCCESS)
+ ixl_led_restore(pf);
+}
+
+void
+ixl_led_restore(struct ixl_pf *pf)
+{
+ struct i40e_hw *hw;
+
+ if (!pf->led_active)
+ return;
+
+ hw = &pf->hw;
+ if (pf->led_phy_controlled) {
+ (void)i40e_led_set_phy(hw, false, pf->led_phy_addr,
+ pf->led_status | I40E_PHY_LED_MODE_ORIG);
+ if ((hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) == 0)
+ (void)i40e_aq_set_phy_debug(hw, 0, NULL);
+ } else {
+ i40e_led_set(hw, pf->led_status, false);
+ }
+ pf->led_active = false;
+}
+
static int
ixl_if_msix_intr_assign(if_ctx_t ctx, int msix)
{
diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h
index 74e1cad79731..7d751d3bd1dc 100644
--- a/sys/dev/ixl/ixl_pf.h
+++ b/sys/dev/ixl/ixl_pf.h
@@ -137,6 +137,10 @@ struct ixl_pf {
#endif
u32 state;
u8 supported_speeds;
+ bool led_active;
+ bool led_phy_controlled;
+ u16 led_phy_addr;
+ u32 led_status;
struct ixl_pf_qmgr qmgr;
struct ixl_pf_qtag qtag;
@@ -388,6 +392,7 @@ void ixl_shutdown_hmc(struct ixl_pf *);
void ixl_handle_empr_reset(struct ixl_pf *);
int ixl_prepare_for_reset(struct ixl_pf *pf, bool is_up);
int ixl_rebuild_hw_structs_after_reset(struct ixl_pf *, bool is_up);
+void ixl_led_restore(struct ixl_pf *pf);
int ixl_pf_reset(struct ixl_pf *);
#ifdef PCI_IOV
diff --git a/sys/dev/ixl/ixl_pf_iflib.c b/sys/dev/ixl/ixl_pf_iflib.c
index bdacf0cfa06d..90fc85198523 100644
--- a/sys/dev/ixl/ixl_pf_iflib.c
+++ b/sys/dev/ixl/ixl_pf_iflib.c
@@ -944,6 +944,8 @@ ixl_prepare_for_reset(struct ixl_pf *pf, bool is_up)
int error, first_error;
first_error = 0;
+ /* Restore identification before the reset tears down AdminQ access. */
+ ixl_led_restore(pf);
#ifdef PCI_IOV
ixl_notify_vfs_reset(pf);
error = ixl_quiesce_vfs_for_reset(pf);