Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Jul 2023 21:53:45 GMT
From:      Eric Joyner <erj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 1f188b9af075 - stable/13 - ixl(4): Add link state polling
Message-ID:  <202307272153.36RLrj30052725@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by erj:

URL: https://cgit.FreeBSD.org/src/commit/?id=1f188b9af0755ee1aeb7e1211f274b96952a10f1

commit 1f188b9af0755ee1aeb7e1211f274b96952a10f1
Author:     Krzysztof Galazka <krzysztof.galazka@intel.com>
AuthorDate: 2023-07-20 22:33:52 +0000
Commit:     Eric Joyner <erj@FreeBSD.org>
CommitDate: 2023-07-27 21:49:13 +0000

    ixl(4): Add link state polling
    
    In some cases driver may ask FW about link state before FW finishes
    configuration of a (Q)SFP+ transceiver. If first attempt of using Get Link
    Status AQC after loading driver or handling a reset fails, then re-try
    periodically for 5 seconds.
    
    Signed-off-by: Krzysztof Galazka <krzysztof.galazka@intel.com>
    Signed-off-by: Eric Joyner <erj@FreeBSD.org>
    
    Tested by:      jeffrey.e.pieper@intel.com
    Approved by:    erj@
    Sponsored by:   Intel Corporation
    Differential Revision:  https://reviews.freebsd.org/D40899
    
    (cherry picked from commit ba2f531f816a6bc1ef5f2cba4a329ff7bdbec0f3)
---
 sys/dev/ixl/i40e_adminq_cmd.h |  2 +-
 sys/dev/ixl/if_ixl.c          | 50 ++++++++++++++++++++++++++++++++++++-------
 sys/dev/ixl/ixl.h             |  2 ++
 sys/dev/ixl/ixl_debug.h       |  2 ++
 sys/dev/ixl/ixl_pf.h          |  4 ++++
 sys/dev/ixl/ixl_pf_iflib.c    |  4 +---
 sys/dev/ixl/ixl_pf_main.c     | 30 ++++++++++++++++++++------
 7 files changed, 75 insertions(+), 19 deletions(-)

diff --git a/sys/dev/ixl/i40e_adminq_cmd.h b/sys/dev/ixl/i40e_adminq_cmd.h
index 564a076761d0..679e191412cd 100644
--- a/sys/dev/ixl/i40e_adminq_cmd.h
+++ b/sys/dev/ixl/i40e_adminq_cmd.h
@@ -44,7 +44,7 @@
 
 #define I40E_FW_API_VERSION_MAJOR	0x0001
 #define I40E_FW_API_VERSION_MINOR_X722	0x000C
-#define I40E_FW_API_VERSION_MINOR_X710	0x000E
+#define I40E_FW_API_VERSION_MINOR_X710	0x000F
 
 #define I40E_FW_MINOR_VERSION(_h) ((_h)->mac.type == I40E_MAC_XL710 ? \
 					I40E_FW_API_VERSION_MINOR_X710 : \
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index 65f6a400569c..a18dd4361bac 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -449,6 +449,29 @@ ixl_admin_timer(void *arg)
 {
 	struct ixl_pf *pf = (struct ixl_pf *)arg;
 
+	if (ixl_test_state(&pf->state, IXL_STATE_LINK_POLLING)) {
+		struct i40e_hw *hw = &pf->hw;
+		sbintime_t stime;
+		enum i40e_status_code status;
+
+		hw->phy.get_link_info = TRUE;
+		status = i40e_get_link_status(hw, &pf->link_up);
+		if (status == I40E_SUCCESS) {
+			ixl_clear_state(&pf->state, IXL_STATE_LINK_POLLING);
+			/* OS link info is updated in the admin task */
+		} else {
+			device_printf(pf->dev,
+			    "%s: i40e_get_link_status status %s, aq error %s\n",
+			    __func__, i40e_stat_str(hw, status),
+			    i40e_aq_str(hw, hw->aq.asq_last_status));
+			stime = getsbinuptime();
+			if (stime - pf->link_poll_start > IXL_PF_MAX_LINK_POLL) {
+				device_printf(pf->dev, "Polling link status failed\n");
+				ixl_clear_state(&pf->state, IXL_STATE_LINK_POLLING);
+			}
+		}
+	}
+
 	/* Fire off the admin task */
 	iflib_admin_intr_deferred(pf->vsi.ctx);
 
@@ -711,12 +734,6 @@ ixl_if_attach_post(if_ctx_t ctx)
 		return (0);
 	}
 
-	/* Determine link state */
-	if (ixl_attach_get_link_status(pf)) {
-		error = EINVAL;
-		goto err;
-	}
-
 	error = ixl_switch_config(pf);
 	if (error) {
 		device_printf(dev, "Initial ixl_switch_config() failed: %d\n",
@@ -745,6 +762,11 @@ ixl_if_attach_post(if_ctx_t ctx)
 	device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n",
 	    pf->qtag.num_allocated, pf->qtag.num_active);
 
+	/* Determine link state */
+	error = ixl_attach_get_link_status(pf);
+	if (error == EINVAL)
+		goto err;
+
 	/* Limit PHY interrupts to link, autoneg, and modules failure */
 	status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK,
 	    NULL);
@@ -780,8 +802,20 @@ ixl_if_attach_post(if_ctx_t ctx)
 	ixl_set_link(pf, ixl_test_state(&pf->state, IXL_STATE_LINK_ACTIVE_ON_DOWN));
 
 	hw->phy.get_link_info = true;
-	i40e_get_link_status(hw, &pf->link_up);
-	ixl_update_link_status(pf);
+	status = i40e_get_link_status(hw, &pf->link_up);
+	if (status != I40E_SUCCESS) {
+		device_printf(dev,
+		    "%s get link status, status: %s aq_err=%s\n",
+		    __func__, i40e_stat_str(hw, status),
+		    i40e_aq_str(hw, hw->aq.asq_last_status));
+		/*
+		 * Most probably FW has not finished configuring PHY.
+		 * Retry periodically in a timer callback.
+		 */
+		ixl_set_state(&pf->state, IXL_STATE_LINK_POLLING);
+		pf->link_poll_start = getsbinuptime();
+	} else
+		ixl_update_link_status(pf);
 
 #ifdef PCI_IOV
 	ixl_initialize_sriov(pf);
diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h
index 9b49520a8851..2f6fe6c959d9 100644
--- a/sys/dev/ixl/ixl.h
+++ b/sys/dev/ixl/ixl.h
@@ -301,6 +301,8 @@
 /* For stats sysctl naming */
 #define IXL_QUEUE_NAME_LEN 32
 
+#define IXL_PF_MAX_LINK_POLL	SBT_1S * 5
+
 MALLOC_DECLARE(M_IXL);
 
 #define IXL_DEV_ERR(_dev, _format, ...) \
diff --git a/sys/dev/ixl/ixl_debug.h b/sys/dev/ixl/ixl_debug.h
index 0d8c624d2df9..818ba8a1df83 100644
--- a/sys/dev/ixl/ixl_debug.h
+++ b/sys/dev/ixl/ixl_debug.h
@@ -101,6 +101,8 @@ enum ixl_dbg_mask {
 	IXL_DBG_SWITCH_INFO		= 0x00010000,
 	IXL_DBG_I2C			= 0x00020000,
 
+	IXL_DBG_LINK			= 0x00100000,
+
 	IXL_DBG_ALL			= 0xFFFFFFFF
 };
 
diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h
index 6a73f5acc838..90236ac144c8 100644
--- a/sys/dev/ixl/ixl_pf.h
+++ b/sys/dev/ixl/ixl_pf.h
@@ -89,6 +89,7 @@ enum ixl_state {
 	IXL_STATE_FW_LLDP_DISABLED	= 9,
 	IXL_STATE_EEE_ENABLED	= 10,
 	IXL_STATE_LINK_ACTIVE_ON_DOWN = 11,
+	IXL_STATE_LINK_POLLING = 12,
 };
 
 #define IXL_PF_IN_RECOVERY_MODE(pf)	\
@@ -172,6 +173,8 @@ struct ixl_pf {
 	int			num_vfs;
 	uint16_t		veb_seid;
 	int			vc_debug_lvl;
+
+	sbintime_t		link_poll_start;
 };
 
 /*
@@ -282,6 +285,7 @@ struct ixl_pf {
 #define ixl_dbg_info(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_INFO, s, ##__VA_ARGS__)
 #define ixl_dbg_filter(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_FILTER, s, ##__VA_ARGS__)
 #define ixl_dbg_iov(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_IOV, s, ##__VA_ARGS__)
+#define ixl_dbg_link(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_LINK, s, ##__VA_ARGS__)
 
 /* PF-only function declarations */
 void	ixl_set_state(volatile u32 *s, enum ixl_state bit);
diff --git a/sys/dev/ixl/ixl_pf_iflib.c b/sys/dev/ixl/ixl_pf_iflib.c
index b70388bd6f6e..326c10ca8bfe 100644
--- a/sys/dev/ixl/ixl_pf_iflib.c
+++ b/sys/dev/ixl/ixl_pf_iflib.c
@@ -1028,9 +1028,7 @@ ixl_rebuild_hw_structs_after_reset(struct ixl_pf *pf, bool is_up)
 	i40e_aq_set_vsi_broadcast(&pf->hw, vsi->seid, TRUE, NULL);
 
 	/* Determine link state */
-	if (ixl_attach_get_link_status(pf)) {
-		error = EINVAL;
-	}
+	ixl_attach_get_link_status(pf);
 
 	i40e_aq_set_dcb_parameters(hw, TRUE, NULL);
 
diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c
index 5cf686c5b7cf..23da241315e7 100644
--- a/sys/dev/ixl/ixl_pf_main.c
+++ b/sys/dev/ixl/ixl_pf_main.c
@@ -4656,22 +4656,38 @@ ixl_attach_get_link_status(struct ixl_pf *pf)
 {
 	struct i40e_hw *hw = &pf->hw;
 	device_t dev = pf->dev;
-	int error = 0;
+	enum i40e_status_code status;
 
 	if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
 	    (hw->aq.fw_maj_ver < 4)) {
 		i40e_msec_delay(75);
-		error = i40e_aq_set_link_restart_an(hw, TRUE, NULL);
-		if (error) {
-			device_printf(dev, "link restart failed, aq_err=%d\n",
-			    pf->hw.aq.asq_last_status);
-			return error;
+		status = i40e_aq_set_link_restart_an(hw, TRUE, NULL);
+		if (status != I40E_SUCCESS) {
+			device_printf(dev,
+			    "%s link restart failed status: %s, aq_err=%s\n",
+			    __func__, i40e_stat_str(hw, status),
+			    i40e_aq_str(hw, hw->aq.asq_last_status));
+			return (EINVAL);
 		}
 	}
 
 	/* Determine link state */
 	hw->phy.get_link_info = TRUE;
-	i40e_get_link_status(hw, &pf->link_up);
+	status = i40e_get_link_status(hw, &pf->link_up);
+	if (status != I40E_SUCCESS) {
+		device_printf(dev,
+		    "%s get link status, status: %s aq_err=%s\n",
+		    __func__, i40e_stat_str(hw, status),
+		    i40e_aq_str(hw, hw->aq.asq_last_status));
+		/*
+		 * Most probably FW has not finished configuring PHY.
+		 * Retry periodically in a timer callback.
+		 */
+		ixl_set_state(&pf->state, IXL_STATE_LINK_POLLING);
+		pf->link_poll_start = getsbinuptime();
+		return (EAGAIN);
+	}
+ 	ixl_dbg_link(pf, "%s link_up: %d\n", __func__, pf->link_up);
 
 	/* Flow Control mode not set by user, read current FW settings */
 	if (pf->fc == -1)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202307272153.36RLrj30052725>