Commit 32288358 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'amd-xgbe-rx-adaptation-and-phy-handling-fixes'

Raju Rangoju says:

====================
amd-xgbe: RX adaptation and PHY handling fixes

This series fixes several issues in the amd-xgbe driver related to RX
adaptation and PHY handling in 10GBASE-KR mode, particularly when
auto-negotiation is disabled.

Patch 1 fixes link status handling during RX adaptation by correctly
reading the latched link status bit so transient link drops are
detected without losing the current state.

Patch 2 prevents CRC errors that can occur when performing RX
adaptation with auto-negotiation turned off. The driver now stops
TX/RX before re-triggering RX adaptation and only re-enables traffic
once adaptation completes and the link is confirmed up, ensuring
packets are not corrupted during the adaptation window.

Patch 3 restores the intended ordering of PHY reset relative to
phy_start(), making sure PHY settings are reset before the PHY is
started instead of afterwards.
====================

Link: https://patch.msgid.link/20260306111629.1515676-1-Raju.Rangoju@amd.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 7d86aa41 a8ba129a
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -1271,20 +1271,25 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
	if (ret)
		goto err_napi;

	/* Reset the phy settings */
	ret = xgbe_phy_reset(pdata);
	if (ret)
		goto err_irqs;

	/* Start the phy */
	ret = phy_if->phy_start(pdata);
	if (ret)
		goto err_irqs;

	hw_if->enable_tx(pdata);
	hw_if->enable_rx(pdata);
	/* Synchronize flag with hardware state after enabling TX/RX.
	 * This prevents stale state after device restart cycles.
	 */
	pdata->data_path_stopped = false;

	udp_tunnel_nic_reset_ntf(netdev);

	/* Reset the phy settings */
	ret = xgbe_phy_reset(pdata);
	if (ret)
		goto err_txrx;

	netif_tx_start_all_queues(netdev);

	xgbe_start_timers(pdata);
@@ -1294,10 +1299,6 @@ static int xgbe_start(struct xgbe_prv_data *pdata)

	return 0;

err_txrx:
	hw_if->disable_rx(pdata);
	hw_if->disable_tx(pdata);

err_irqs:
	xgbe_free_irqs(pdata);

+75 −7
Original line number Diff line number Diff line
@@ -1942,7 +1942,7 @@ static void xgbe_set_rx_adap_mode(struct xgbe_prv_data *pdata,
static void xgbe_rx_adaptation(struct xgbe_prv_data *pdata)
{
	struct xgbe_phy_data *phy_data = pdata->phy_data;
	unsigned int reg;
	int reg;

	/* step 2: force PCS to send RX_ADAPT Req to PHY */
	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_EQ_CTRL4,
@@ -1964,11 +1964,20 @@ static void xgbe_rx_adaptation(struct xgbe_prv_data *pdata)

	/* Step 4: Check for Block lock */

	/* Link status is latched low, so read once to clear
	 * and then read again to get current state
	 */
	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
	if (reg < 0)
		goto set_mode;

	/* Link status is latched low so that momentary link drops
	 * can be detected. If link was already down read again
	 * to get the latest state.
	 */
	if (!pdata->phy.link && !(reg & MDIO_STAT1_LSTATUS)) {
		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
		if (reg < 0)
			goto set_mode;
	}

	if (reg & MDIO_STAT1_LSTATUS) {
		/* If the block lock is found, update the helpers
		 * and declare the link up
@@ -2008,6 +2017,48 @@ static void xgbe_phy_rx_adaptation(struct xgbe_prv_data *pdata)
	xgbe_rx_adaptation(pdata);
}

/*
 * xgbe_phy_stop_data_path - Stop TX/RX to prevent packet corruption
 * @pdata: driver private data
 *
 * This function stops the data path (TX and RX) to prevent packet
 * corruption during critical PHY operations like RX adaptation.
 * Must be called before initiating RX adaptation when link goes down.
 */
static void xgbe_phy_stop_data_path(struct xgbe_prv_data *pdata)
{
	if (pdata->data_path_stopped)
		return;

	/* Stop TX/RX to prevent packet corruption during RX adaptation */
	pdata->hw_if.disable_tx(pdata);
	pdata->hw_if.disable_rx(pdata);
	pdata->data_path_stopped = true;

	netif_dbg(pdata, link, pdata->netdev,
		  "stopping data path for RX adaptation\n");
}

/*
 * xgbe_phy_start_data_path - Re-enable TX/RX after RX adaptation
 * @pdata: driver private data
 *
 * This function re-enables the data path (TX and RX) after RX adaptation
 * has completed successfully. Only called when link is confirmed up.
 */
static void xgbe_phy_start_data_path(struct xgbe_prv_data *pdata)
{
	if (!pdata->data_path_stopped)
		return;

	pdata->hw_if.enable_rx(pdata);
	pdata->hw_if.enable_tx(pdata);
	pdata->data_path_stopped = false;

	netif_dbg(pdata, link, pdata->netdev,
		  "restarting data path after RX adaptation\n");
}

static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
{
	int reg;
@@ -2801,13 +2852,27 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
	if (pdata->en_rx_adap) {
		/* if the link is available and adaptation is done,
		 * declare link up
		 *
		 * Note: When link is up and adaptation is done, we can
		 * safely re-enable the data path if it was stopped
		 * for adaptation.
		 */
		if ((reg & MDIO_STAT1_LSTATUS) && pdata->rx_adapt_done)
		if ((reg & MDIO_STAT1_LSTATUS) && pdata->rx_adapt_done) {
			xgbe_phy_start_data_path(pdata);
			return 1;
		}
		/* If either link is not available or adaptation is not done,
		 * retrigger the adaptation logic. (if the mode is not set,
		 * then issue mailbox command first)
		 */

		/* CRITICAL: Stop data path BEFORE triggering RX adaptation
		 * to prevent CRC errors from packets corrupted during
		 * the adaptation process. This is especially important
		 * when AN is OFF in 10G KR mode.
		 */
		xgbe_phy_stop_data_path(pdata);

		if (pdata->mode_set) {
			xgbe_phy_rx_adaptation(pdata);
		} else {
@@ -2815,8 +2880,11 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
			xgbe_phy_set_mode(pdata, phy_data->cur_mode);
		}

		if (pdata->rx_adapt_done)
		if (pdata->rx_adapt_done) {
			/* Adaptation complete, safe to re-enable data path */
			xgbe_phy_start_data_path(pdata);
			return 1;
		}
	} else if (reg & MDIO_STAT1_LSTATUS)
		return 1;

+4 −0
Original line number Diff line number Diff line
@@ -1243,6 +1243,10 @@ struct xgbe_prv_data {
	bool en_rx_adap;
	int rx_adapt_retries;
	bool rx_adapt_done;
	/* Flag to track if data path (TX/RX) was stopped for RX adaptation.
	 * This prevents packet corruption during the adaptation window.
	 */
	bool data_path_stopped;
	bool mode_set;
	bool sph;
};