git: 8b2e75970c03 - main - ixl: Add led(4) identification support

Kevin Bowling <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a7be676.388a7.390be8b3__22217.9236284987$1786504887$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=8b2e75970c0328e7397290417cc06e9d9c763d2a

commit 8b2e75970c0328e7397290417cc06e9d9c763d2a
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-08-12 00:54:21 +0000
Commit:     Kevin Bowling <[email protected]>
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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.