* [PATCH 00/13] Wangxun fixes and new features
@ 2026-08-27 11:41 Zaiyu Wang
2026-08-27 20:11 ` Stephen Hemminger
` (4 more replies)
0 siblings, 5 replies; 39+ messages in thread
From: Zaiyu Wang @ 2026-08-27 11:41 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang
This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and additionally refines UDP offload handling.
Zaiyu Wang (13):
net/txgbe: fix e56 PHY configuration error
net/txgbe: fix incorrect link state in 10G forced mode
net/txgbe: do not force reconfig on link retry
net/txgbe: set i2c sda hold time
net/txgbe: fix link speed display info for 10G mode
net/txgbe: remove stale outer UDP checksum offload flag
net/txgbe: add offload support for tunnel type UDP
net/txgbe: fix SFP hot-plug when auto-negotiation is on
net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation
net/txgbe: add backplane FFE and capability devargs
net/txgbe: add devarg to turn off Tx laser for 40G NIC
net/txgbe: fix CR/KR link training and recovery
net/txgbe: align link capabilities and DAC classification
doc/guides/nics/txgbe.rst | 18 +++
drivers/net/txgbe/base/txgbe_aml.c | 3 +-
drivers/net/txgbe/base/txgbe_aml40.c | 83 +++++++++++--
drivers/net/txgbe/base/txgbe_e56.c | 11 +-
drivers/net/txgbe/base/txgbe_e56.h | 6 +
drivers/net/txgbe/base/txgbe_e56_bp.c | 161 +++++++++++++++-----------
drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +
drivers/net/txgbe/base/txgbe_hw.c | 22 ++++
drivers/net/txgbe/base/txgbe_phy.c | 13 +++
drivers/net/txgbe/base/txgbe_phy.h | 1 +
drivers/net/txgbe/base/txgbe_regs.h | 3 +
drivers/net/txgbe/base/txgbe_type.h | 17 ++-
drivers/net/txgbe/txgbe_ethdev.c | 120 +++++++++++++++++--
drivers/net/txgbe/txgbe_rxtx.c | 16 ++-
14 files changed, 380 insertions(+), 96 deletions(-)
--
2.55.0.windows.2
^ permalink raw reply [flat|nested] 39+ messages in thread* Re: [PATCH 00/13] Wangxun fixes and new features 2026-08-27 11:41 [PATCH 00/13] Wangxun fixes and new features Zaiyu Wang @ 2026-08-27 20:11 ` Stephen Hemminger 2026-09-08 12:43 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 00/16] " Zaiyu Wang ` (3 subsequent siblings) 4 siblings, 1 reply; 39+ messages in thread From: Stephen Hemminger @ 2026-08-27 20:11 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Thu, 27 Aug 2026 19:41:52 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and additionally refines UDP offload handling. Using Claude AI review (versus the simpler CI AI review) shows several issues that need addressing before this can be merged. Here is my edit of the wordy AI feedbac. Patch 02: net/txgbe: fix incorrect link state in 10G forced mode Warning: the new else branch sets link_valid on a PHY init failure. ret_status = txgbe_set_link_to_amlite(hw, speed); if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; else hw->link_valid = true; txgbe_set_link_to_amlite() can also return TXGBE_ERR_PHY_INIT_NOT_DONE (VR_PCS_DIG_CTRL1 reset never cleared), which now falls into the else and marks the link valid after the PHY failed to come out of reset. The 25G sibling in txgbe_aml.c handles that code separately, before the timeout/else split, precisely so link_valid is left alone: if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) goto out; if (ret_status == TXGBE_ERR_TIMEOUT) { hw->link_valid = false; ... Suggest matching the aml.c structure here. Patch 05: net/txgbe: fix link speed display info for 10G mode Warning: allowed_speeds is not extended to match. txgbe_dev_start() still has if (hw->mac.type == txgbe_mac_aml40) allowed_speeds = RTE_ETH_LINK_SPEED_40G; so an application that explicitly requests RTE_ETH_LINK_SPEED_10G on an AML40 port is still rejected with "Invalid link setting", even though the driver now configures and reports 10G links. Either add RTE_ETH_LINK_SPEED_10G to allowed_speeds or explain why 10G is autoneg-only. See also the Error under patch 13 — the 40G|10G mask added here becomes harmful once patch 13 widens the capability mask. Patch 07: net/txgbe: add offload support for tunnel type UDP Error: unchecked rte_pktmbuf_read() return, then dereferenced. uh = rte_pktmbuf_read(mbuf, mbuf->outer_l2_len + mbuf->outer_l3_len, sizeof(udphdr), &udphdr); if (uh->dest == rte_cpu_to_be_16(6081)) rte_pktmbuf_read() returns NULL when off + len > pkt_len. outer_l2_len and outer_l3_len come from the application and are not validated by the driver, so a short or mis-annotated packet gives a NULL dereference in the Tx fast path. Please add a NULL check. Note the neighbouring GRE and GENEVE cases have the same unchecked pattern, so this is a pre-existing habit in the function rather than something the patch invents, but the new code should not extend it. Warning: txgbe_get_tun_len() rewrites the application's mbuf. mbuf->ol_flags &= ~RTE_MBUF_F_TX_TUNNEL_UDP; ... mbuf->ol_flags |= RTE_MBUF_F_TX_TUNNEL_GENEVE; /* or VXLAN */ The Tx burst should not mutate ol_flags of a buffer it does not own. The application still owns the mbuf and may inspect or re-transmit it (cloned/multicast paths transmit the same mbuf more than once), and a second pass then sees VXLAN/GENEVE instead of UDP. Only the local switch below needs the resolved type, so a local variable would do: uint64_t tun_type = mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK; if (tun_type == RTE_MBUF_F_TX_TUNNEL_UDP) { ... tun_type = (uh->dest == rte_cpu_to_be_16(RTE_GENEVE_DEFAULT_PORT)) ? RTE_MBUF_F_TX_TUNNEL_GENEVE : RTE_MBUF_F_TX_TUNNEL_VXLAN; } switch (tun_type) { This also removes an ordering subtlety: txgbe_xmit_pkts() snapshots ol_flags into tx_ol_req before calling txgbe_get_tun_len(), so tx_desc_ol_flags_to_ptid() and txgbe_set_xmit_ctx() see the original TUNNEL_UDP while the mbuf itself has been rewritten. The two new case labels are correct today only because of that ordering. Warning: Cc: stable@dpdk.org with no Fixes: tag. The commit body describes a defect (packets sent with a wrong descriptor or dropped), so a Fixes: tag looks appropriate; otherwise drop the stable Cc. Info: use RTE_GENEVE_DEFAULT_PORT from <rte_geneve.h> rather than the literal 6081. Patch 10: net/txgbe: add backplane FFE and capability devargs The move of txgbe_parse_devargs() to after txgbe_init_shared_code() is safe -- init_shared_code() only sets the MAC type, the ops tables, max_link_up_time and the LAN id, and reads no devarg. Wiring bp_capa up is a real fix too: txgbe_e56_bp.c already branched on hw->phy.bp_capa but nothing ever set it, so it was permanently 0. Warning: the patch adds two new devargs (ffe_pre2, bp_capa) under a Fixes: tag with Cc: stable@dpdk.org. New configuration options are not backport material. Suggest splitting the ffe_pre2/bp_capa plumbing out as a plain feature patch without the stable Cc, and keeping the stable Cc only for the 40G per-lane FFE replication, which is the actual bug. Warning: no release notes entry for the new devargs. Patch 11: net/txgbe: add devarg to turn off Tx laser for 40G NIC Error: the enable path is not guarded by the devarg. void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) { if (hw->mac.type == txgbe_mac_aml40) { ... txgbe_acquire_swfw_sync(hw, 1); hw->phy.write_i2c_eeprom(hw, 86, 0x0); txgbe_release_swfw_sync(hw, 1); laser_off defaults to 0 and is documented as opt-in, but this I2C write runs for every AML40 port on every enable_tx_laser(), whether or not the user asked for it. The disable path deliberately branches on txgbe_is_dac_cable() / sfp_type before touching I2C; the enable path does neither, so it also issues an I2C EEPROM write when a DAC cable or no module is present. Please guard it with hw->devarg.laser_off and mirror the DAC/QSFP branch from the disable path. Warning: with laser_off=1 on a DAC cable, disable clears PMD_CFG0 bits 19:16, 15:12 and bit 1. Bits 19:12 are restored by txgbe_e56_set_phy_link_mode() and by txgbe_set_link_to_amlite(), but I could not find anything that restores bit 1 on the xpcs AN path -- only txgbe_set_link_to_amlite() sets it, and that is not called when txgbe_xpcs_an_enabled() is true (DAC plus auto_neg=1, which is exactly the configuration this devarg targets). Could you confirm bit 1 is restored somewhere on the AN path, or clear only what gets restored? Warning: unchecked return values on the new calls. txgbe_acquire_swfw_sync() returns TXGBE_ERR_SWFW_SYNC on a semaphore timeout; on failure the code still performs the I2C write and then releases a semaphore it does not hold. write_i2c_eeprom() also returns s32. The convention elsewhere in the driver is err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); if (err != 0) return; Info: several magic numbers. 0x1400 has a define, PMD_CFG0, in the txgbe_e56.h that this patch now includes; 19:16 has one too, E56PHY_PMD_CFG_0_RX_EN_CFG. The semaphore mask 1 should be TXGBE_MNGSEM_SWPHY (same value, clearer). Byte 86 / 0xf is the SFF-8636 Tx disable register and its all-lanes value -- both deserve names. Info: no release notes entry for the new devarg. Patch 12: net/txgbe: fix CR/KR link training and recovery Error: leftover TODO and a C99 comment (checkpatch ERROR), txgbe_ethdev.c:3806: intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG;//aml40-to-do Error: txgbe_e56_exchange_page() can loop indefinitely. The loop bound is reset from inside the loop body: for (count = 0; count < 50; count++) { ... if (rdata & BIT(14)) { if (rdata & BIT(15)) { wr32_epcs(hw, 0x70016, 0x2001); next_page = 1; count = 0; /* reset count to wait next page */ } } ... usec_delay(1000); } The reset is not gated on base_page or on any independent budget, so as long as the link partner keeps asserting next-page at 0x70019 the loop never terminates. This runs from txgbe_dev_e56_check_bp_event() in the interrupt/alarm thread, so a peer that keeps requesting next pages wedges that thread and blocks every other alarm on the process. count2 already counts total iterations -- it just is not used as a bound. Something like if (count2 >= MAX_AN_PAGE_ITERATIONS) return -ETIMEDOUT; would cap the total while still allowing count to restart per page. Info: the "50ms timeout" comment no longer matches the code once count can be reset; the effective wait is 50 ms per page, unbounded overall. Info: falling out of the loop into the check_ability label and then distinguishing the two paths by testing count == 50 is hard to follow. An explicit "goto timeout" would read better. Patch 13: net/txgbe: align link capabilities and DAC classification Error: the widened capability mask lets a multi-bit speed reach code that tests it with ==, so backplane and multispeed-fiber ports get configured for 10G instead of 40G. After this patch, get_link_capabilities_aml40() returns 10GB_FULL | 40GB_FULL for backplane and for multispeed fiber. Patch 05 made txgbe_dev_start() request 40GB_FULL | 10GB_FULL on autoneg, so "speed &= link_capabilities" in txgbe_setup_phy_link_aml40() now leaves both bits set, where before patch 13 the mask reduced it to 40G alone. Both downstream consumers test for equality: /* txgbe_set_link_to_amlite() */ if (speed == TXGBE_LINK_SPEED_40GB_FULL) { ... 40G config ... } else { ... 10G config ... /* taken with both bits set */ } /* txgbe_e56_tx_ffe_cfg() */ if (speed == TXGBE_LINK_SPEED_10GB_FULL) ... else if (speed == TXGBE_LINK_SPEED_25GB_FULL) ... else if (speed == TXGBE_LINK_SPEED_40GB_FULL) ... /* no branch matches; ffe_main/pre1/pre2/post stay 0 and are * written to the PHY as zeros */ Reachable whenever txgbe_xpcs_an_enabled() is false, which is the case for backplane with auto_neg=0 and for multispeed fiber always (it requires DAC or backplane). For backplane the FFE path is entered unconditionally, so both symptoms occur together. Either resolve the mask to a single speed before calling setup_link, or have txgbe_set_link_to_amlite()/txgbe_e56_tx_ffe_cfg() select the highest set bit rather than comparing for equality. Warning: the commit message and the code disagree about active DACs. The message says "Unify DAC classification on txgbe_is_dac_cable(), so active DACs are no longer treated as optical modules." but txgbe_qsfp_type_40g_active_core0/1 is added to txgbe_is_40g_fiber_qsfp() and not to txgbe_is_dac_cable(). An active 40G cable therefore still takes the optical path: no DAC FFE values in txgbe_e56_tx_ffe_cfg(), bypass_ctle left true in txgbe_e56_rxs_calib_adapt_seq(), tx_ffe_cfg not called at all from txgbe_setup_phy_link_aml40(), and AN off. For comparison, the 10G equivalent txgbe_sfp_type_da_act_lmt_core0/1 is in txgbe_is_dac_cable(). SFF-8636 byte 131 bit 0 is "40G Active Cable (XLPPI)", which covers active copper as well as AOC. Please either add the 40g_active types to txgbe_is_dac_cable() or reword the commit message to say they are handled as optical. Info: the unification is incomplete. The 25G branch of txgbe_e56_tx_ffe_cfg() was converted to txgbe_is_dac_cable(), but the 40G branch a few lines above still open-codes if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || txgbe_is_backplane(hw)) which will keep missing any type added to txgbe_is_dac_cable() later. ^ permalink raw reply [flat|nested] 39+ messages in thread
* RE: [PATCH 00/13] Wangxun fixes and new features 2026-08-27 20:11 ` Stephen Hemminger @ 2026-09-08 12:43 ` Zaiyu Wang 0 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-09-08 12:43 UTC (permalink / raw) To: 'Stephen Hemminger'; +Cc: dev Hi Stephen, Thank you very much for the detailed review and for taking the time to go through each patch carefully. I have evaluated every comment and addressed them in v2. The points that are not changed in this revision are explained in the cover letter. > -----Original Message----- > From: Stephen Hemminger <stephen@networkplumber.org> > Sent: Friday, August 28, 2026 4:12 AM > To: Zaiyu Wang <zaiyuwang@trustnetic.com>; Zaiyu Wang <zaiyuwang@trustnetic.com> > Cc: dev@dpdk.org; dev@dpdk.org > Subject: Re: [PATCH 00/13] Wangxun fixes and new features > > On Thu, 27 Aug 2026 19:41:52 +0800 > Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > > > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state), and additionally > refines UDP offload handling. > > > Using Claude AI review (versus the simpler CI AI review) shows several issues that need addressing before this can be merged. > > Here is my edit of the wordy AI feedbac. > ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH v8 00/16] Wangxun fixes and new features 2026-08-27 11:41 [PATCH 00/13] Wangxun fixes and new features Zaiyu Wang 2026-08-27 20:11 ` Stephen Hemminger @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 21:41 ` Stephen Hemminger [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (2 subsequent siblings) 4 siblings, 1 reply; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). --- v8: - P05: keep a retry from reconfiguring an established AN73 link, while still restarting PHY configuration when the link is down or AN is incomplete. - P10: on AML40, mark unsupported and unclassifiable QSFP modules as unknown so the module poll does not repeatedly identify them or rerun module and link setup. - P12: place the txgbe release-note entries between the Solarflare and ZTE driver entries. - P13: rerun complete AML40 link setup on set_link_up() with laser_off enabled, restoring the DAC configuration without adding a separate state flag. - P14: correct the AN FSM condition described in the commit message and remove the stray line after the Signed-off-by trailer. - P15: assign the detected 10G speed for passive and active-limiting DACs, and remove the unreachable AML40 10G SFP capability branch. - P16: add a new patch to keep Amber-Lite ports administratively down by preventing the AN73 watchdog and setup-link retry paths from configuring PHY while hw->dev_start is cleared. --- v7: - P14: fix a TRAINING log-string typo. move the variable declarations in txgbe_e56_get_txffe(). clarify the comment of page-exchange timeout budget. --- v6: - fix the apply failure. --- v5: - drop the UDP tunnel patch: the generic UDP tunnel flag covers any UDP tunnel, so the tunnel type cannot be resolved from the destination port. - P02: advertise 10G, 25G, and 40G from the requested speed mask instead of the device ID, so the 25G and 40G parts advertise 10G by default as well. - P07: keep the patch limited to decoding the 10G link speed from PORTSTAT; the AML40 default 10G|40G advertisement change is now in P02. - P09: gate the SFP detection alarm and the AN73 watchdog on a new per-port flag that dev_stop clears before the first cancel. cancel SFP detection before the watchdog. - P10: re-arm the 40G module poll only while the SFP/AN73 alarm flag is set. - P12: treat the ffe_pre2 and bp_capa devargs as a feature rather than a fix; drop the Fixes tags and stable Cc, and document the 25G/40G Amber-Lite FFE defaults. - P14: bound the AN page exchange, propagate its timeout to the watchdog handler, and avoid register reads used only by disabled BP debug logs. - P15: stop clearing the auto_neg devarg when a 10G-only DAC disables AN; derive the effective AN73 state from the current module capabilities instead. Classify 40G active cables through the optical path, unify DAC checks on txgbe_is_dac_cable(). --- Not handled in this revision: - P10: On AML40, the poll caches unsupported or unclassifiable modules as unknown. A module replacement between polls without an observed absent level therefore cannot be detected, including replacement of an unsupported module by a supported one. An observed removal resets the cached state and allows the next inserted module to be identified. - P12: bp_capa and the other devargs are not range-checked yet. Input validation for all txgbe devargs will be added in a separate change. - P14: AN page exchange and CL72 training still run in the shared alarm callback. A later change will move negotiation out of that callback so that different ports can negotiate independently in parallel. --- Zaiyu Wang (16): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: use the requested speed in E56 AN setup net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 FFE tap and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification net/txgbe: respect manual link-down on Amber-Lite doc/guides/nics/txgbe.rst | 25 +++- doc/guides/rel_notes/release_26_11.rst | 11 ++ drivers/net/txgbe/base/txgbe_aml.c | 9 +- drivers/net/txgbe/base/txgbe_aml40.c | 83 ++++++++-- drivers/net/txgbe/base/txgbe_e56.c | 14 +- drivers/net/txgbe/base/txgbe_e56.h | 6 + drivers/net/txgbe/base/txgbe_e56_bp.c | 196 ++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- drivers/net/txgbe/base/txgbe_hw.c | 33 ++++ drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 38 ++++- drivers/net/txgbe/base/txgbe_phy.h | 7 + drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 ++- drivers/net/txgbe/txgbe_ethdev.c | 200 +++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 + drivers/net/txgbe/txgbe_rxtx.c | 1 - 17 files changed, 529 insertions(+), 132 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH v8 00/16] Wangxun fixes and new features 2026-10-12 10:56 ` [PATCH v8 00/16] " Zaiyu Wang @ 2026-10-12 21:41 ` Stephen Hemminger 0 siblings, 0 replies; 39+ messages in thread From: Stephen Hemminger @ 2026-10-12 21:41 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Mon, 12 Oct 2026 18:56:17 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). > > --- > v8: > - P05: keep a retry from reconfiguring an established AN73 link, while > still restarting PHY configuration when the link is down or AN is > incomplete. > - P10: on AML40, mark unsupported and unclassifiable QSFP modules as > unknown so the module poll does not repeatedly identify them or > rerun module and link setup. > - P12: place the txgbe release-note entries between the Solarflare and > ZTE driver entries. > - P13: rerun complete AML40 link setup on set_link_up() with laser_off > enabled, restoring the DAC configuration without adding a separate > state flag. > - P14: correct the AN FSM condition described in the commit message > and remove the stray line after the Signed-off-by trailer. > - P15: assign the detected 10G speed for passive and active-limiting > DACs, and remove the unreachable AML40 10G SFP capability branch. > - P16: add a new patch to keep Amber-Lite ports administratively down > by preventing the AN73 watchdog and setup-link retry paths from > configuring PHY while hw->dev_start is cleared. > --- Still lots of issues shown from running Claude AI review from web. Subject: Re: [PATCH v8 00/16] net/txgbe: Amber-Lite link fixes Series applies cleanly to main and every commit builds with -Dwerror=true. All Fixes: hashes resolve. Two errors: patch 16 can leave the link permanently down after a set_link_down/set_link_up cycle, and patch 13 adds a driver-specific devarg that changes set_link_down semantics. Errors ------ [PATCH v8 16/16] net/txgbe: respect manual link-down on Amber-Lite The early return in txgbe_dev_setup_link_alarm_handler_aml() skips clearing TXGBE_FLAG_NEED_LINK_CONFIG. On 25G SFP (media_type fiber) with LSC enabled, set_link_down() calls txgbe_dev_link_update(); link is down, so link_update_share() sets NEED_LINK_CONFIG and spawns the link thread. The thread calls the AML handler, which now returns because dev_start is false, and the flag stays set. After that, every txgbe_dev_link_update_share() returns link down at the NEED_LINK_CONFIG check before calling check_link or starting a new thread, including the call from set_link_up(). Nothing else clears the flag, so the port reports link down until the application restarts the process. Clear the flag before returning: struct rte_eth_dev *dev = hw->dev_back; struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev); ... if (!hw->dev_start) { intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; return; } [PATCH v8 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC NAK on the devarg. rte_eth_dev_set_link_down() is supposed to take the link down, and the peer seeing loss of signal is the point of it. Whether that happens should not depend on a per-driver knob. Make it the unconditional behaviour on AML40 when link is set down, and run link setup unconditionally in set_link_up(). The commit message already shows the cost of the knob: the enable path has to stay ungated because a previous run with laser_off=1 can leave the module transmitter disabled. Without the devarg that case goes away. Warnings -------- [PATCH v8 03/16] net/txgbe: fix e56 PHY configuration error Commit message says the wrong field degrades both 40G and 10G, but only txgbe_e56_cfg_40g() is changed. txgbe_e56_cfg_10g() still has the same write: addr = E56PHY_RXS_RINGO_0_ADDR; rdata = rd32_ephy(hw, addr); set_fields_e56(&rdata, 9, 4, 0x366); cfg_25g and the e56_bp.c copies already use (21, 12). Either fix cfg_10g in this patch or reword the message to say 40G only. [PATCH v8 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs bp_capa is not range checked. Any value other than 0..2 leaves the 40G block in txgbe_e56_set_phy_link_mode() advertising nothing for 40G. Validate it in txgbe_parse_devargs(): if (bp_capa > 2) { PMD_INIT_LOG(WARNING, "invalid bp_capa %u, using 0", bp_capa); bp_capa = 0; } Also, why is KR4 vs CR4 a user setting at all? This is a property of the board; derive it from the subsystem id if possible. Info ---- [PATCH v8 02/16] net/txgbe: use the requested speed in E56 AN setup The three ifs building autoneg_advertised reduce to: hw->phy.autoneg_advertised = speed & (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL | TXGBE_LINK_SPEED_40GB_FULL); Drop "as the base layer of the out-of-tree driver does" from the commit message; the change stands on its own. [PATCH v8 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation With no module plugged in, every 2 s poll goes to the NOT_PRESENT branch, logs "SFP not present." and cancels the watchdog again. Act only on the transition: } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { if (hw->phy.sfp_type != txgbe_sfp_type_not_present) { PMD_DRV_LOG(INFO, "SFP not present."); hw->phy.sfp_type = txgbe_sfp_type_not_present; rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } } [PATCH v8 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only On AML40 a user ffe_* value above 0xFF is silently truncated by S40G_TX_FFE_4LANE(). Reject or warn instead. [PATCH v8 12/16] and [PATCH v8 13/16] 12 adds a stray blank line in release_26_11.rst and 13 removes it. Drop the hunk from 12. [PATCH v8 15/16] net/txgbe: align link capabilities and DAC classification The comment "mirroring the temporary workaround in the previous version" describes patch history, not the code. Suggest: /* Unknown module: report 40G so setup_mac_link() does not * fail with TXGBE_ERR_LINK_SETUP. */ The DEBUGOUT added at the top of txgbe_get_link_capabilities_aml40() now runs on every watchdog tick, since txgbe_xpcs_an_enabled() calls get_link_capabilities(). Remove it. The bullet "Remove the AML40 10G SFP capability branch" describes a branch that is not in the tree this patch applies to. Drop it. ^ permalink raw reply [flat|nested] 39+ messages in thread
[parent not found: <20261012110518.1911-1-zaiyuwang@trustnetic.com>]
* [PATCH v8 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang ` (14 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Two checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. Remove both restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 15 +++++++++++---- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7c72b53f64 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -176,6 +177,12 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0734a1c63c..d4c635dc2f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1848,7 +1848,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 02/16] net/txgbe: use the requested speed in E56 AN setup [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> 2026-10-12 10:56 ` [PATCH v8 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (13 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the port does not use the argument: it is passed to UNREFERENCED_PARAMETER(), and the AN base page is built from the device id and from hw->phy.fiber_suppport_speed instead. The caller therefore cannot narrow what is advertised, which is what kept a 10G request from reaching the base page on a 10G/40G part even after the capability mask had been opened up. Take the argument as a speed bitmask, as the base layer of the out-of-tree driver does: gate the 10G, 25G, and 40G advertisement on the requested speed and use speed rather than hw->phy.fiber_suppport_speed on the fiber/DAC path. Both Amber-Lite MACs support 10GBASE-KR in addition to their nominal speed: the capability masks already report 10G|25G for the 25G MAC and 10G|40G for the 40G MAC, while the AN base page advertised exactly one speed picked from the device id. With automatic speed selection asking for 10G|40G on the 40G MAC as it already did 10G|25G on the 25G MAC, the base page advertises 10GBASE-KR together with 25GBASE-KR/CR on the 25G MAC and together with 40GBASE-KR4/CR4 on the 40G MAC. Explicit speed requests advertise only the requested modes. The AN restart paths also have no record of the caller speed to re-apply. Record it in hw->phy.autoneg_advertised before setup_link(), as the base layer does, and pass it from the watchdog and training-restart paths instead of the hardcoded 10. The two readers of that field keep their existing fallback to get_link_capabilities() when it is zero. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------ drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 25 +++++++++++++++++++++---- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7c72b53f64..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..760101a05e 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0; @@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8); @@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..8089e5b971 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index d4c635dc2f..2f59b0794f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1864,7 +1864,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); @@ -1888,6 +1889,20 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed before setup_link so that the AN + * restart paths can re-apply the same configuration. + */ + hw->phy.autoneg_advertised = 0; + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_40GB_FULL; + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL; + + if (speed & TXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL; + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error; @@ -2951,7 +2966,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; } @@ -2966,7 +2981,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n"); @@ -2975,7 +2991,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 03/16] net/txgbe: fix e56 PHY configuration error [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> 2026-10-12 10:56 ` [PATCH v8 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (12 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..2711863f2c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 04/16] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (11 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 05/16] net/txgbe: do not force reconfig on link retry [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang ` (10 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = false. On the AN73/xpcs path, this skips reconfiguration once the link is up and AN is complete. Passing true from the retry path instead resets an established AN73 link, which then drops and may not recover after DAC hot-plug. The setup flag is also passed to txgbe_e56_set_phy_link_mode() as its need_restart argument. Passing false unchanged would make a retry a no-op while the link is down or AN is incomplete if the PHY is already in 10G mode. Derive need_restart from the current link and AN state so retries recover an incomplete setup without reconfiguring an established link. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 5 ++++- drivers/net/txgbe/base/txgbe_aml40.c | 5 ++++- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..7a0839a7d1 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -213,6 +213,7 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + bool need_restart; int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; u32 value; @@ -246,8 +247,10 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; + + need_restart = autoneg_wait_to_complete || !link_up || !hw->an_done; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, need_restart); rte_spinlock_unlock(&hw->phy_lock); return 0; } diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..892dddd373 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -148,6 +148,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + bool need_restart; int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; u32 value; @@ -171,8 +172,10 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; + + need_restart = autoneg_wait_to_complete || !link_up || !hw->an_done; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, need_restart); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 2f59b0794f..a5ef0b3e54 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3237,7 +3237,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 06/16] net/txgbe: set i2c sda hold time [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (9 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 07/16] net/txgbe: fix link speed display info for 10G mode [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (8 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, so a 10G link is reported as 10G. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 892dddd373..b52702b197 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 08/16] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (7 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (6 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. The SFP detection alarm and the AN73 watchdog are gated on a per-port flag that txgbe_dev_start() sets before the alarms are armed and txgbe_dev_stop() clears before it cancels anything, so a handler already running on the alarm thread can neither re-arm itself nor arm the other one on a port that is being stopped. The flag goes low before the cancels because hw->adapter_stopped is only set at the end of txgbe_dev_stop(). The link thread can arm the AML link alarm while txgbe_dev_stop() waits for it, so cancel that alarm again after the thread has been joined. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 61 ++++++++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 ++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index a5ef0b3e54..83ef9d8bfc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1695,6 +1695,7 @@ txgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, static int txgbe_dev_start(struct rte_eth_dev *dev) { + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct txgbe_hw_stats *hw_stats = TXGBE_DEV_STATS(dev); struct txgbe_vf_info *vfinfo = *TXGBE_DEV_VFDATA(dev); @@ -1970,6 +1971,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_dev_rxq_interrupt_setup(dev); /* enable uio/vfio intr/eventfd mapping */ + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 1, + rte_memory_order_release); rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ @@ -2027,15 +2030,22 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 0, + rte_memory_order_release); + + /* Stop the producer before the watchdog it can arm. */ + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_check_aml_temp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); } - rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); /* disable interrupts */ txgbe_disable_intr(hw); @@ -2926,6 +2936,7 @@ void txgbe_dev_check_aml_temp_event(void *param) void txgbe_dev_e56_check_bp_event(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 an_int1 = 0, value = 0, fsm = 0; u32 __rte_unused an_int = 0; @@ -2935,6 +2946,27 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (!txgbe_is_backplane(hw)) { + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && + hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3022,7 +3054,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->bp_event_interval = 2000 * 1000; out: - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0 && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); } @@ -3030,10 +3065,15 @@ static void txgbe_dev_detect_sfp(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; s32 err; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { @@ -3056,14 +3096,31 @@ txgbe_dev_detect_sfp(void *param) err = hw->phy.identify_sfp(hw); out: + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) { PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (!hw->adapter_stopped && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index a617b70e3c..08f41e628d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -368,6 +368,8 @@ struct txgbe_adapter { uint8_t rss_reta_updated; RTE_ATOMIC(uint32_t) link_thread_running; + /* SFP detection and AN73 watchdog alarm state. */ + RTE_ATOMIC(uint32_t) sfp_an_alarm_enabled; rte_thread_t link_thread_tid; }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (5 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. Three problems are in the way. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. Identification is attempted only when the cached module state is not present, and the poll re-arms itself only while the SFP/AN73 alarm gate is set, so that it cannot survive txgbe_dev_stop(). Second, on AML40, an unsupported QSFP identifier, or a QSFP module with no supported capability bit, previously left the cached state as not present. The poll then repeated the delay and I2C reads indefinitely, and the latter case also repeated module and link setup. Record these modules as unknown and return not supported so polling resumes only after an observed removal. Third, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 7 +++++++ drivers/net/txgbe/base/txgbe_phy.c | 9 +++++++++ drivers/net/txgbe/txgbe_ethdev.c | 18 +++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index b52702b197..cee2f2880a 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -180,6 +180,13 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, need_restart); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid, as the non-xpcs path below does. An + * earlier txgbe_set_link_to_amlite() timeout, for example when + * the port was started with no module plugged in, left it + * false, which keeps the check_phy_link and check_mac_link + * gates forcing the link down even after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..a50fa986b9 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1125,6 +1125,8 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, identifier = 0x%x", hw->bus.lan_id, identifier); hw->phy.type = txgbe_phy_sfp_unsupported; + if (hw->mac.type == txgbe_mac_aml40) + hw->phy.sfp_type = txgbe_sfp_type_unknown; err = TXGBE_ERR_SFP_NOT_SUPPORTED; } else { err = hw->phy.read_i2c_sff8636(hw, 0, @@ -1158,6 +1160,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) } } + if (err == 0 && hw->mac.type == txgbe_mac_aml40 && + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + hw->phy.type = txgbe_phy_sfp_unsupported; + hw->phy.sfp_type = txgbe_sfp_type_unknown; + err = TXGBE_ERR_SFP_NOT_SUPPORTED; + } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 83ef9d8bfc..8e2adb245e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1984,6 +1984,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3068,7 +3073,7 @@ txgbe_dev_detect_sfp(void *param) struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, rte_memory_order_acquire) == 0) @@ -3080,6 +3085,9 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* Re-identification is only attempted from the not-present state. */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3123,6 +3131,14 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0) { + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); + } } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang ` (4 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 5 +++++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..fe9a83ae01 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,11 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* The 40G PHY holds one FFE byte per lane, so a user supplied value has to + * be replicated over the four lanes. + */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 5c16c4f07e..60298800ee 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 8e2adb245e..25a65f6a6d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -483,6 +483,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u16 pballoc = 0; @@ -492,6 +493,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -540,6 +550,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -642,7 +660,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -650,6 +667,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (3 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The Amber-Lite E56 PHY has per-MAC FFE defaults that differ from the Sapphire defaults. In particular, the second pre-cursor tap defaults to zero, but callers need a devarg to override it when ffe_set is enabled. Add ffe_pre2 for the E56 second pre-cursor tap, and bp_capa for the 40G backplane advertisement selection. The latter supports the existing default of both KR4 and CR4, or either capability alone. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 18 +++++++++++++++--- doc/guides/rel_notes/release_26_11.rst | 9 +++++++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++++- drivers/net/txgbe/txgbe_ethdev.c | 23 +++++++++++++++++++---- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..61766cc4ac 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -132,17 +132,23 @@ Please note that following ``devargs`` are only set for backplane NICs. If disabled, the FFE parameters will not take effect. Otherwise, set 1 for SFI mode, set 2 for KR mode, set 3 for KX4 mode, set 4 for KX mode. -- ``ffe_main`` (default **27**) +- ``ffe_main`` (default **42** on the 25G Amber-Lite, **43** on the 40G + Amber-Lite, **27** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_pre`` (default **8**) +- ``ffe_pre`` (default **3** on Amber-Lite, **8** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_post`` (default **44**) +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + +- ``ffe_post`` (default **17** on Amber-Lite, **44** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. @@ -177,6 +183,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index e282fa5581..f40f9e7da3 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -142,6 +142,14 @@ New Features * Added VF support on AMD Solarflare X45xx adapters. +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * **Updated ZTE zxdh ethernet driver.** * Added a fast single-segment Rx path (``zxdh_recv_single_pkts``) @@ -164,6 +172,7 @@ New Features for a specific queue, complementing the existing device-level statistics API. + Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 60298800ee..d65a50530f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 25a65f6a6d..07b6d13ce1 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -492,13 +492,20 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. + /* The E56 PHY needs its own FFE defaults, as the ones above only + * apply to the Sapphire PHY. */ - if (hw->mac.type == txgbe_mac_aml40) { + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -523,6 +530,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -535,6 +544,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -548,7 +559,9 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + hw->phy.bp_capa = bp_capa; /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { @@ -6479,12 +6492,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 14/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang ` (2 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss, for example for link-state tracking at the peer. Add a laser_off devarg: when enabled, bring the Tx laser down on port link-down -- for DAC cables disable the PCS, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. Replace the raw register offsets and bit masks with named constants (PMD_CFG0, E56PHY_PMD_CFG_0_RX_EN_CFG, TXGBE_MNGSEM_SWPHY, TXGBE_SFF_8636_TX_DISABLE). For AML40, rerun normal link setup when link is brought up with laser_off enabled. Re-enabling the transmitter alone does not restore the configuration disabled for DAC on link-down. The setup is not gated on the current module classification because the module may have changed while the port was down. Restoring the Tx enable state is deliberately not gated on laser_off in txgbe_enable_tx_laser_multispeed_fiber(). The SFF-8636 Tx disable byte keeps its value while the module stays powered, so a module left with Tx disabled by a run that exited with laser_off=1 is still disabled when the driver next starts with laser_off=0. Nothing else clears that byte when the link comes up, so gating this write would leave the laser off for good. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 ++++++ doc/guides/rel_notes/release_26_11.rst | 4 +++- drivers/net/txgbe/base/txgbe_hw.c | 33 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 24 ++++++++++++++++++- 6 files changed, 75 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 61766cc4ac..6aa6d4597f 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -189,6 +189,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled, for QSFP modules the Tx disable bit is + written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index f40f9e7da3..d62f787747 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -149,6 +149,9 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable for DAC cables, SFF-8636 Tx disable for QSFP modules). * **Updated ZTE zxdh ethernet driver.** @@ -172,7 +175,6 @@ New Features for a specific queue, complementing the existing device-level statistics API. - Removed Items ------------- diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..cbf859c54f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,30 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown || + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3313,14 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (!txgbe_is_dac_cable(hw) && + hw->phy.sfp_type != txgbe_sfp_type_unknown && + hw->phy.sfp_type != txgbe_sfp_type_not_present && + hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index d65a50530f..33e306ac70 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 07b6d13ce1..ae3dbf076e 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -493,6 +493,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY needs its own FFE defaults, as the ones above only * apply to the Sapphire PHY. @@ -546,6 +547,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -556,6 +559,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -2158,6 +2162,9 @@ static int txgbe_dev_set_link_up(struct rte_eth_dev *dev) { struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + bool autoneg = false; + u32 speed; + int err; if (hw->phy.media_type == txgbe_media_type_copper) { /* Turn on the copper */ @@ -2165,6 +2172,20 @@ txgbe_dev_set_link_up(struct rte_eth_dev *dev) } else { /* Turn on the laser */ hw->mac.enable_tx_laser(hw); + + if (hw->mac.type == txgbe_mac_aml40 && hw->devarg.laser_off) { + speed = hw->phy.autoneg_advertised; + if (speed == 0) { + err = hw->mac.get_link_capabilities(hw, &speed, &autoneg); + if (err != 0) + return -EIO; + } + + err = hw->mac.setup_link(hw, speed, true); + if (err != 0) + return -EIO; + } + hw->dev_start = true; txgbe_dev_link_update(dev, 0); } @@ -6499,7 +6520,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 14/16] net/txgbe: fix CR/KR link training and recovery [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 15/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 16/16] net/txgbe: respect manual link-down on Amber-Lite Zaiyu Wang 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010) for CL72 completion until bits 0 and 3 are set, ((rdata & 0x9) == 0x9), with a 1 ms step and a 400 ms budget. This replaces the ephy 0x163c mask-0xe poll that tested the wrong condition. The per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt (1 ms step, 50 ms per exchange round, 200 ms total, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds. The inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Avoid register reads that are only used by disabled BP debug logs, and drop a leftover debug line in the watchdog. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 173 ++++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 24 +++- 7 files changed, 146 insertions(+), 72 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 2711863f2c..8e986daf96 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index fe9a83ae01..32d95b61b9 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index 760101a05e..7656da5cd0 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2121,6 +2122,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2350,24 +2352,35 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +#define AN_PAGE_EXCHANGE_TIMEOUT_MS 200 +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* Allow up to 50 ms per page-exchange round, with a 200 ms total budget. */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; + if (count2 >= AN_PAGE_EXCHANGE_TIMEOUT_MS) { + BP_LOG("Wait for next page timeout after %d ms\n", + count2); + return -ETIMEDOUT; + } BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2382,31 +2395,87 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + if (!rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) + return; + + /* 21. read txffe to check kr training status */ + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; + u32 lane_num = 0; + u32 __rte_unused pmd_ctrl = 0; int ret = 0; u32 rdata; - u8 pll_en_cfg = 0; u8 pmd_mode = 0; @@ -2436,6 +2505,7 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); status = txgbe_set_phy_link_mode(hw, bylinkmode); + ret |= status; /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ rdata = rd32_ephy(hw, 0x1434); @@ -2462,51 +2532,49 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); + ret |= status; if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + ret |= status; + + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); return ret; } @@ -2516,27 +2584,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2582,11 +2630,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 8089e5b971..f667a052ec 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index da069e94f6..83fee14d12 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -31,10 +31,14 @@ extern int txgbe_logtype_bp; #define RTE_LOGTYPE_TXGBE_BP txgbe_logtype_bp #define BP_LOG(fmt, ...) \ - RTE_LOG(DEBUG, TXGBE_BP, \ - "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ - usec_stamp() / 1000000, usec_stamp() % 1000000, \ - __func__, __LINE__, ## __VA_ARGS__) + do { \ + if (rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) \ + RTE_LOG(DEBUG, TXGBE_BP, \ + "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ + usec_stamp() / 1000000, \ + usec_stamp() % 1000000, \ + __func__, __LINE__, ## __VA_ARGS__); \ + } while (0) #define ASSERT(x) do { \ if (!(x)) \ diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index a50fa986b9..decfcbadd6 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1956,6 +1956,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index ae3dbf076e..f87fca5b19 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3001,6 +3001,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3026,7 +3027,7 @@ void txgbe_dev_e56_check_bp_event(void *param) } } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!txgbe_xpcs_an_enabled(hw)) return; if (!hw->devarg.auto_neg) @@ -3046,6 +3047,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3063,7 +3065,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3782,8 +3798,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 15/16] net/txgbe: align link capabilities and DAC classification [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 14/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 2026-10-12 10:56 ` [PATCH v8 16/16] net/txgbe: respect manual link-down on Amber-Lite Zaiyu Wang 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu A 10G active-limiting DAC on an Amber-Lite 25G NIC has no fiber_suppport_speed value, so the capability path rejects it. A 10G-only passive DAC can also retain a stale 25G bit after hot-plug. DACs and optical modules are additionally treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Use the detected DAC speed in the capability paths. Assign 10G for passive 10G-only and active-limiting DACs instead of preserving a speed value left by the previously installed module. - Keep the bp_auto devarg unchanged when a 10G-only DAC disables AN. The XPCS AN gate queries the current link capabilities, so a subsequently hot-plugged AN-capable DAC is re-evaluated and can enable AN73 again. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. - Remove the AML40 10G SFP capability branch. AML40 identifies QSFP modules and cannot produce the SFP SR/LR types tested by that branch. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 4 +-- drivers/net/txgbe/base/txgbe_aml40.c | 52 +++++++++++++++++++++------- drivers/net/txgbe/base/txgbe_e56.c | 9 ++--- drivers/net/txgbe/base/txgbe_phy.c | 23 ++++++++++-- drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 ++ 6 files changed, 68 insertions(+), 23 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 7a0839a7d1..ae5c7d7f0d 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,11 +103,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { - hw->devarg.auto_neg = false; *autoneg = false; } else { *autoneg = true; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index cee2f2880a..4080302ce7 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,55 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static bool txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + DEBUGOUT("port[%d] hw->phy.sfp_type = %d", + hw->bus.lan_id, hw->phy.sfp_type); + + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; } else { /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + * Unknown / unsupported module: keep 40G default to avoid + * TXGBE_ERR_LINK_SETUP returned by setup_mac_link, mirroring + * the temporary workaround in the previous version. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 8e986daf96..f996113ab8 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index decfcbadd6..896fe7eecf 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -917,7 +917,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) TXGBE_LINK_SPEED_25GB_FULL | TXGBE_LINK_SPEED_10GB_FULL; } else { - hw->phy.fiber_suppport_speed |= + hw->phy.fiber_suppport_speed = TXGBE_LINK_SPEED_10GB_FULL; } } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 || @@ -938,6 +938,8 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type = (hw->bus.lan_id == 0 ? txgbe_sfp_type_da_act_lmt_core0 : txgbe_sfp_type_da_act_lmt_core1); + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_10GB_FULL; } else { hw->phy.sfp_type = txgbe_sfp_type_unknown; } @@ -1158,6 +1160,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } if (err == 0 && hw->mac.type == txgbe_mac_aml40 && @@ -2430,10 +2439,20 @@ int txgbe_is_dac_cable(struct txgbe_hw *hw) int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) { + u32 speed; + bool autoneg; + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) return false; - return hw->devarg.auto_neg ? true : false; + if (!hw->devarg.auto_neg) + return false; + + /* Re-evaluate AN support for the currently detected module. */ + if (hw->mac.get_link_capabilities(hw, &speed, &autoneg) != 0) + return false; + + return autoneg; } /** diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 33e306ac70..a1ce78623b 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v8 16/16] net/txgbe: respect manual link-down on Amber-Lite [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> ` (14 preceding siblings ...) 2026-10-12 10:56 ` [PATCH v8 15/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang @ 2026-10-12 10:56 ` Zaiyu Wang 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-12 10:56 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_dev_set_link_down() clears hw->dev_start, but the Amber-Lite AN73 watchdog treats a down link as a recovery condition and can start negotiation again. The setup-link alarm handler can likewise configure the PHY after a link update or a previous setup retry. As a result, a port brought down through rte_eth_dev_set_link_down() can link up again without a matching rte_eth_dev_set_link_up() call. Use hw->dev_start as the administrative link gate. Keep the AN73 watchdog armed so that monitoring resumes after link-up, but skip link recovery while the port is administratively down. Also make the setup-link alarm handler return before it configures the PHY in that state. This keeps the link down until rte_eth_dev_set_link_up() explicitly re-enables it. The link-up path then restores the required PHY configuration. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index f87fca5b19..e733514826 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3033,8 +3033,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw->devarg.auto_neg) return; - /* only continue if link is down */ - if (dev->data->dev_link.link_status) + /* Continue only for an administratively up port with link down. */ + if (!hw->dev_start || dev->data->dev_link.link_status) goto out; value = rd32_epcs(hw, VR_AN_INTR); @@ -3362,6 +3362,9 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) if (!hw) return; + if (!hw->dev_start) + return; + struct rte_eth_dev *dev = (struct rte_eth_dev *)hw->dev_back; struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev); u32 speed; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 00/16] Wangxun fixes and new features 2026-08-27 11:41 [PATCH 00/13] Wangxun fixes and new features Zaiyu Wang ` (2 preceding siblings ...) [not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com> @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 17:17 ` Stephen Hemminger [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> 4 siblings, 1 reply; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). --- v9: - P02: build autoneg_advertised from one mask instead of three ifs, and drop the out-of-tree reference from the message. - P03: fix the same wrong RXS field in txgbe_e56_cfg_10g(), and add the Fixes tag for the 25G commit that introduced that copy. - P10: report module removal and cancel the AN73 watchdog only on the transition to not-present, so an empty cage no longer repeats both on every poll. - P12: reset invalid bp_capa values to 0, log AML40 ffe_* values above 0xFF before their low bytes are replicated across the four lanes, and document the applicable FFE value range. - P13: clarify that laser_off disables the E56 PHY PMD through PMD_CFG0 for DAC cables, while QSFP modules use the SFF-8636 Tx-disable byte. - P15: rewrite the unknown-module comment, drop the debug print that ran on every watchdog tick, and drop a commit-message bullet for a branch that is not in the parent tree. - P16: clear TXGBE_FLAG_NEED_LINK_CONFIG before the administrative-down early return, so a 25G SFP port can recover after set_link_down() and set_link_up(). Not handled in this revision: - P12: Range validation currently covers only bp_capa and the AML40 FFE values. Consistent validation for all txgbe devargs will be added in a follow-up after the ongoing community work on the common devarg parsing and validation functions is finalized. - P13: keep the laser_off devarg. On AML40, forcing physical loss of signal is a stronger operation than an administrative link-down. Bringing the link back up then requires complete PHY configuration and restarts AN73 negotiation (if auto neg on). This has a visible link recovery cost on high-speed ports. The default laser_off=0 preserves the existing behavior and link stability for users that only need local link-down. Deployments which need the peer to observe loss of signal, for example for peer-side link-state tracking, can explicitly enable laser_off=1. --- v8: - P05: keep a retry from reconfiguring an established AN73 link, while still restarting PHY configuration when the link is down or AN is incomplete. - P10: on AML40, mark unsupported and unclassifiable QSFP modules as unknown so the module poll does not repeatedly identify them or rerun module and link setup. - P12: place the txgbe release-note entries between the Solarflare and ZTE driver entries. - P13: rerun complete AML40 link setup on set_link_up() with laser_off enabled, restoring the DAC configuration without adding a separate state flag. - P14: correct the AN FSM condition described in the commit message and remove the stray line after the Signed-off-by trailer. - P15: assign the detected 10G speed for passive and active-limiting DACs, and remove the unreachable AML40 10G SFP capability branch. - P16: add a new patch to keep Amber-Lite ports administratively down by preventing the AN73 watchdog and setup-link retry paths from configuring PHY while hw->dev_start is cleared. --- v7: - P14: fix a TRAINING log-string typo. move the variable declarations in txgbe_e56_get_txffe(). clarify the comment of page-exchange timeout budget. --- Zaiyu Wang (16): net/txgbe: fix failure to configure 10G on dual-speed DAC net/txgbe: use the requested speed in E56 AN setup net/txgbe: fix e56 PHY configuration error net/txgbe: fix incorrect link state in 10G forced mode net/txgbe: do not force reconfig on link retry net/txgbe: set i2c sda hold time net/txgbe: fix link speed display info for 10G mode net/txgbe: remove stale outer UDP checksum offload flag net/txgbe: fix SFP hot-plug when auto-negotiation is on net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation net/txgbe: fix 40G FFE tuning applied to first lane only net/txgbe: add pre2 FFE tap and backplane capability devargs net/txgbe: add devarg to turn off Tx laser for 40G NIC net/txgbe: fix CR/KR link training and recovery net/txgbe: align link capabilities and DAC classification net/txgbe: respect manual link-down on Amber-Lite doc/guides/nics/txgbe.rst | 32 +++- doc/guides/rel_notes/release_26_11.rst | 12 ++ drivers/net/txgbe/base/txgbe_aml.c | 9 +- drivers/net/txgbe/base/txgbe_aml40.c | 78 +++++++-- drivers/net/txgbe/base/txgbe_e56.c | 16 +- drivers/net/txgbe/base/txgbe_e56.h | 4 + drivers/net/txgbe/base/txgbe_e56_bp.c | 196 +++++++++++++--------- drivers/net/txgbe/base/txgbe_e56_bp.h | 4 +- drivers/net/txgbe/base/txgbe_hw.c | 33 ++++ drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 38 ++++- drivers/net/txgbe/base/txgbe_phy.h | 7 + drivers/net/txgbe/base/txgbe_regs.h | 3 + drivers/net/txgbe/base/txgbe_type.h | 17 +- drivers/net/txgbe/txgbe_ethdev.c | 220 +++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 + drivers/net/txgbe/txgbe_rxtx.c | 1 - 17 files changed, 549 insertions(+), 135 deletions(-) -- 2.55.0.windows.2 ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH v9 00/16] Wangxun fixes and new features 2026-10-22 11:03 ` [PATCH v9 00/16] Wangxun fixes and new features Zaiyu Wang @ 2026-10-22 17:17 ` Stephen Hemminger 0 siblings, 0 replies; 39+ messages in thread From: Stephen Hemminger @ 2026-10-22 17:17 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Thu, 22 Oct 2026 19:03:06 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series addresses link-related issues on Wangxun Amber-lite 25G/40G NICs (CR/KR training, hot-plug, 10G link state). > > --- > v9: > - P02: build autoneg_advertised from one mask instead of three ifs, and > drop the out-of-tree reference from the message. > - P03: fix the same wrong RXS field in txgbe_e56_cfg_10g(), and add the > Fixes tag for the 25G commit that introduced that copy. > - P10: report module removal and cancel the AN73 watchdog only on the > transition to not-present, so an empty cage no longer repeats both > on every poll. > - P12: reset invalid bp_capa values to 0, log AML40 ffe_* values above > 0xFF before their low bytes are replicated across the four lanes, > and document the applicable FFE value range. > - P13: clarify that laser_off disables the E56 PHY PMD through PMD_CFG0 > for DAC cables, while QSFP modules use the SFF-8636 Tx-disable byte. > - P15: rewrite the unknown-module comment, drop the debug print that ran > on every watchdog tick, and drop a commit-message bullet for a branch > that is not in the parent tree. > - P16: clear TXGBE_FLAG_NEED_LINK_CONFIG before the administrative-down > early return, so a 25G SFP port can recover after set_link_down() and > set_link_up(). Still seeing errors in AI review ^ permalink raw reply [flat|nested] 39+ messages in thread
[parent not found: <20261022111017.3605-1-zaiyuwang@trustnetic.com>]
* [PATCH v9 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang ` (14 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Setting "port config speed 10000" on a 10G/40G dual-speed DAC cable fails with LINK_SETUP_ERR, and the AN base page always advertises only 40G. Two checks independently blocked 10G: 1. allowed_speeds in dev_start was restricted to 40G, so the user request was rejected before reaching setup_link. 2. get_link_capabilities_aml40() returned only 40G for all DAC cables, so the link_capabilities mask in setup_phy_link_aml40() stripped any 10G bit from the caller speed. Remove both restrictions so 10G flows through from user configuration to the AN base page advertisement. On DAC cables the capability is read from hw->phy.fiber_suppport_speed, which reflects the actual SFP module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 15 +++++++++++---- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 1098efe5e6..7c72b53f64 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -98,11 +98,12 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, { if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = hw->phy.fiber_suppport_speed; + *autoneg = hw->devarg.auto_neg; } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *speed = TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + *autoneg = hw->devarg.auto_neg; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -176,6 +177,12 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, return status; } + /* setup the highest link when no autoneg */ + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + speed = TXGBE_LINK_SPEED_40GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || hw->phy.ffe_set) { rte_spinlock_lock(&hw->phy_lock); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0734a1c63c..d4c635dc2f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1848,7 +1848,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; if (hw->mac.type == txgbe_mac_aml40) - allowed_speeds = RTE_ETH_LINK_SPEED_40G; + allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_40G; else if (hw->mac.type == txgbe_mac_aml) allowed_speeds = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G; else -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 02/16] net/txgbe: use the requested speed in E56 AN setup [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> 2026-10-22 11:03 ` [PATCH v9 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang ` (13 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the port does not use the argument: it is passed to UNREFERENCED_PARAMETER(), and the AN base page is built from the device id and from hw->phy.fiber_suppport_speed instead. The caller therefore cannot narrow what is advertised, which is what kept a 10G request from reaching the base page on a 10G/40G part even after the capability mask had been opened up. Take the argument as a speed bitmask, gate the 10G, 25G, and 40G advertisement on the requested speed and use speed rather than hw->phy.fiber_suppport_speed on the fiber/DAC path. Both Amber-Lite MACs support 10GBASE-KR in addition to their nominal speed: the capability masks already report 10G|25G for the 25G MAC and 10G|40G for the 40G MAC, while the AN base page advertised exactly one speed picked from the device id. With automatic speed selection asking for 10G|40G on the 40G MAC as it already did 10G|25G on the 25G MAC, the base page advertises 10GBASE-KR together with 25GBASE-KR/CR on the 25G MAC and together with 40GBASE-KR4/CR4 on the 40G MAC. Explicit speed requests advertise only the requested modes. The AN restart paths also have no record of the caller speed to re-apply. Record it in hw->phy.autoneg_advertised before setup_link(), and pass it from the watchdog and training-restart paths instead of the hardcoded 10. The two readers of that field keep their existing fallback to get_link_capabilities() when it is zero. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------ drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +- drivers/net/txgbe/txgbe_ethdev.c | 16 ++++++++++++---- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7c72b53f64..7476759d4d 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index d376d918df..760101a05e 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0; @@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8); @@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; } diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index d2c49c2fce..8089e5b971 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index d4c635dc2f..f20e57125d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1864,7 +1864,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) speed = 0x0; if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) { if (hw->mac.type == txgbe_mac_aml40) { - speed = TXGBE_LINK_SPEED_40GB_FULL; + speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; } else if (hw->mac.type == txgbe_mac_aml) { speed = (TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL); @@ -1888,6 +1889,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed first: the AN restart paths re-apply it. */ + hw->phy.autoneg_advertised = speed & (TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL); + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error; @@ -2951,7 +2957,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; } @@ -2966,7 +2972,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n"); @@ -2975,7 +2982,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 03/16] net/txgbe: fix e56 PHY configuration error [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> 2026-10-22 11:03 ` [PATCH v9 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang ` (12 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The e56 PHY RXS ring equalizer/tap configuration is written to the wrong bit field: set_fields_e56(&rdata, 9, 4, 0x366) targets the unrelated lower bits, so the configured tap values are never applied and the equalizer stays at its default setting, which can degrade the received signal on both the 40G and 10G paths. Fix the field range to (21, 12), so the equalizer/tap configuration takes effect. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index cbcc05333e..c0e5cc3894 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -423,7 +423,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); } @@ -1251,7 +1251,7 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_RXS_RINGO_0_ADDR; rdata = rd32_ephy(hw, addr); - set_fields_e56(&rdata, 9, 4, 0x366); + set_fields_e56(&rdata, 21, 12, 0x366); wr32_ephy(hw, addr, rdata); addr = E56PHY_PMD_CFG_3_ADDR; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 04/16] net/txgbe: fix incorrect link state in 10G forced mode [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (2 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang ` (11 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port is configured in 10G forced mode (auto_neg=0), the hardware can link up but the driver keeps reporting link down after a peer link failure: link_valid is cleared on timeout but never restored when the peer recovers, so the link stays down until the port is restarted. Restore hw->link_valid = true in the success path of txgbe_setup_phy_link_aml40(), symmetric to the 40G path. Handle TXGBE_ERR_PHY_INIT_NOT_DONE before the timeout split and leave link_valid untouched, matching the 25G path in txgbe_setup_phy_link_aml(); the alarm retry then attempts the setup again. Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 7476759d4d..5fa7c6a243 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -202,9 +202,18 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + /* The PHY did not come out of reset; leave link_valid alone and + * let the retry in the alarm handler attempt the setup again. + */ + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; + if (ret_status == TXGBE_ERR_TIMEOUT) hw->link_valid = false; - rte_spinlock_unlock(&hw->phy_lock); + else + hw->link_valid = true; for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 05/16] net/txgbe: do not force reconfig on link retry [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (3 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang ` (10 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link alarm retry calls mac.setup_link() with autoneg_wait_to_complete = false. On the AN73/xpcs path, this skips reconfiguration once the link is up and AN is complete. Passing true from the retry path instead resets an established AN73 link, which then drops and may not recover after DAC hot-plug. The setup flag is also passed to txgbe_e56_set_phy_link_mode() as its need_restart argument. Passing false unchanged would make a retry a no-op while the link is down or AN is incomplete if the PHY is already in 10G mode. Derive need_restart from the current link and AN state so retries recover an incomplete setup without reconfiguring an established link. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 5 ++++- drivers/net/txgbe/base/txgbe_aml40.c | 5 ++++- drivers/net/txgbe/txgbe_ethdev.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index ac80d85f08..7a0839a7d1 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -213,6 +213,7 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + bool need_restart; int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; u32 value; @@ -246,8 +247,10 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; + + need_restart = autoneg_wait_to_complete || !link_up || !hw->an_done; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, need_restart); rte_spinlock_unlock(&hw->phy_lock); return 0; } diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 5fa7c6a243..892dddd373 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -148,6 +148,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + bool need_restart; int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; u32 value; @@ -171,8 +172,10 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; + + need_restart = autoneg_wait_to_complete || !link_up || !hw->an_done; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, need_restart); rte_spinlock_unlock(&hw->phy_lock); return status; } diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index f20e57125d..2f513e20b9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3228,7 +3228,7 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) return; } - hw->mac.setup_link(hw, speed, true); + hw->mac.setup_link(hw, speed, false); u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 06/16] net/txgbe: set i2c sda hold time [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (4 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang ` (9 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The data_in_hold_time measured on the oscilloscope does not meet the hardware requirement, which can corrupt SFP EEPROM reads over I2C. Set the I2C SDA hold time to 100 (0x64) I2C clock periods for both RX and TX in txgbe_i2c_start(). Fixes: 00970f6398c8 ("net/txgbe: fix reading SFP module SFF-8472 data") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 3 +++ drivers/net/txgbe/base/txgbe_regs.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 2fbe50e242..8b653f0aeb 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1334,6 +1334,9 @@ static void txgbe_i2c_start(struct txgbe_hw *hw, u8 dev_addr) wr32(hw, TXGBE_I2CSCLTMOUT, 0xFFFFFF); wr32(hw, TXGBE_I2CSDATMOUT, 0xFFFFFF); + wr32m(hw, TXGBE_I2C_SDA_HOLD, + TXGBE_I2C_SDA_RX_HOLD | TXGBE_I2C_SDA_TX_HOLD, 0x640064); + wr32(hw, TXGBE_I2CICM, 0); wr32(hw, TXGBE_I2CENA, 1); } diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bf46a80862..b0042dc0d6 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1610,6 +1610,9 @@ enum txgbe_5tuple_protocol { #define TXGBE_I2CSTAT_MST ((1U << 5)) #define TXGBE_I2CSCLTMOUT 0x0149AC #define TXGBE_I2CSDATMOUT 0x0149B0 /*I2C SDA Stuck at Low Timeout*/ +#define TXGBE_I2C_SDA_HOLD 0x1497C /* SDA hold time length reg */ +#define TXGBE_I2C_SDA_RX_HOLD 0xff0000 /* SDA rx hold time length reg */ +#define TXGBE_I2C_SDA_TX_HOLD 0xffff /* SDA tx hold time length reg */ /* port cfg Registers */ #define TXGBE_PORTSTAT 0x014404 -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 07/16] net/txgbe: fix link speed display info for 10G mode [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (5 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang ` (8 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When an AML40 port links up at 10G, DPDK reports the speed as 100M instead of 10G. The 10G link status bit is not recognized in txgbe_check_mac_link_aml40(), so any non-40G speed falls through to the default case (UNKNOWN) which is then reported as 100M. Add the 10G port status bit recognition, so a 10G link is reported as 10G. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 892dddd373..b52702b197 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -85,6 +85,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; } else { *speed = TXGBE_LINK_SPEED_UNKNOWN; } -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 08/16] net/txgbe: remove stale outer UDP checksum offload flag [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (6 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang ` (7 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu RTE_MBUF_F_TX_OUTER_UDP_CKSUM is no longer advertised in dev_info->tx_offload_capa, but it is still listed in TXGBE_TX_OFFLOAD_MASK. The two are now inconsistent: a packet carrying the flag is accepted by the offload mask check although the driver no longer handles it. Drop the flag from TXGBE_TX_OFFLOAD_MASK so the advertised capability and the accepted offload flags match. Fixes: 25fe1c780d39 ("net/txgbe: remove outer UDP checksum capability") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 794ba041a4..a295666f9d 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -61,7 +61,6 @@ static const u64 TXGBE_TX_OFFLOAD_MASK = (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_TUNNEL_MASK | RTE_MBUF_F_TX_OUTER_IP_CKSUM | - RTE_MBUF_F_TX_OUTER_UDP_CKSUM | #ifdef RTE_LIB_SECURITY RTE_MBUF_F_TX_SEC_OFFLOAD | #endif -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (7 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang ` (6 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When a port is started before the DAC cable is plugged in, hot-plugging the cable never brings the link up and the port has to be stopped and started again. The AN73 watchdog txgbe_dev_e56_check_bp_event() is armed once in txgbe_dev_start(). Its first tick finds no module, so txgbe_xpcs_an_enabled() returns false and the handler returns without re-arming itself. Once the cable is inserted, nobody polls the AN73 completion any more and the link stays down. Re-arm the watchdog from txgbe_dev_detect_sfp() once a module has been identified, cancelling any pending instance first so that only one of them is running at a time. On the removal path, drop the cached SFP type and cancel the watchdog. Also sample the module-present pin (GPIO_EXT bit 2 on 25G, bit 4 on 40G) on every watchdog tick, so that pulling the cable is noticed even if no GPIO interrupt is delivered. The SFP detection alarm and the AN73 watchdog are gated on a per-port flag, set in txgbe_dev_start() before arming and cleared in txgbe_dev_stop() before cancelling, so a handler already running on the alarm thread cannot re-arm on a port being stopped. The flag goes low first because hw->adapter_stopped is only set at the end of txgbe_dev_stop(). Cancel the AML link alarm again after joining the link thread, which can arm it while the stop is waiting. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 61 ++++++++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.h | 2 ++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 2f513e20b9..77e8b9dea7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1695,6 +1695,7 @@ txgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, static int txgbe_dev_start(struct rte_eth_dev *dev) { + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct txgbe_hw_stats *hw_stats = TXGBE_DEV_STATS(dev); struct txgbe_vf_info *vfinfo = *TXGBE_DEV_VFDATA(dev); @@ -1961,6 +1962,8 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_dev_rxq_interrupt_setup(dev); /* enable uio/vfio intr/eventfd mapping */ + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 1, + rte_memory_order_release); rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ @@ -2018,15 +2021,22 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + rte_atomic_store_explicit(&adapter->sfp_an_alarm_enabled, 0, + rte_memory_order_release); + + /* Stop the producer before the watchdog it can arm. */ + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_check_aml_temp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); } - rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); /* disable interrupts */ txgbe_disable_intr(hw); @@ -2917,6 +2927,7 @@ void txgbe_dev_check_aml_temp_event(void *param) void txgbe_dev_e56_check_bp_event(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 an_int1 = 0, value = 0, fsm = 0; u32 __rte_unused an_int = 0; @@ -2926,6 +2937,27 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw) return; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + + /* Sample the module-present pin on every tick. When the cable is + * pulled, drop the cached SFP type so that txgbe_xpcs_an_enabled() + * turns false and this alarm stops re-arming itself. + */ + if (!txgbe_is_backplane(hw)) { + if (hw->mac.type == txgbe_mac_aml) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_ABS_LS; + else if (hw->mac.type == txgbe_mac_aml40) + value = rd32(hw, TXGBE_GPIOEXT) & TXGBE_SFP1_MOD_PRST_LS; + + if (value != 0 && + hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP module removed, stop AN73 watchdog."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + } + } + if (!(txgbe_xpcs_an_enabled(hw))) return; @@ -3013,7 +3045,10 @@ void txgbe_dev_e56_check_bp_event(void *param) hw->bp_event_interval = 2000 * 1000; out: - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0 && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); } @@ -3021,10 +3056,15 @@ static void txgbe_dev_detect_sfp(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; s32 err; + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (hw->mac.type == txgbe_mac_aml40) { value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { @@ -3047,14 +3087,31 @@ txgbe_dev_detect_sfp(void *param) err = hw->phy.identify_sfp(hw); out: + if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) == 0) + return; + if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) { PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { PMD_DRV_LOG(INFO, "SFP not present."); + /* Module removed: drop the cached type and stop the watchdog. */ + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); txgbe_dev_setup_link_alarm_handler(dev); + /* Re-arm the AN73 watchdog for the newly inserted module, so + * that only one instance of it is running at a time. + */ + if (!hw->adapter_stopped && + (hw->mac.type == txgbe_mac_aml || + hw->mac.type == txgbe_mac_aml40)) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + rte_eal_alarm_set(hw->bp_event_interval, + txgbe_dev_e56_check_bp_event, dev); + } txgbe_dev_link_update(dev, 0); } } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index a617b70e3c..08f41e628d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -368,6 +368,8 @@ struct txgbe_adapter { uint8_t rss_reta_updated; RTE_ATOMIC(uint32_t) link_thread_running; + /* SFP detection and AN73 watchdog alarm state. */ + RTE_ATOMIC(uint32_t) sfp_an_alarm_enabled; rte_thread_t link_thread_tid; }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (8 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang ` (5 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Hot-plugging a DAC cable while an Amber-Lite 40G port is running does not bring the link up. First, the 40G NIC never delivers the GPIO interrupt for module insertion or removal, so txgbe_dev_detect_sfp() is not called and the new module is never identified (the 25G part is not affected). Poll the module-present level every 2 seconds instead. Identification is attempted only when the cached module state is not present, and the poll re-arms itself only while the SFP/AN73 alarm gate is set, so that it cannot survive txgbe_dev_stop(). With an empty cage that poll reported the absence and cancelled the AN73 watchdog on every pass; do both only when the cached state changes to not present. Second, on AML40, an unsupported QSFP identifier, or a QSFP module with no supported capability bit, previously left the cached state as not present. The poll then repeated the delay and I2C reads indefinitely, and the latter case also repeated module and link setup. Record these modules as unknown and return not supported so polling resumes only after an observed removal. Third, when the port is started with no module plugged in, txgbe_set_link_to_amlite() times out and leaves hw->link_valid false. The xpcs path of txgbe_setup_phy_link_aml40() never restores it, so txgbe_e56_check_phy_link() and txgbe_check_mac_link_aml40() keep forcing the link down even once AN73 has brought it up. Restore link_valid on the xpcs path, as the non-xpcs path already does. Fixes: a2d92608d3b0 ("net/txgbe: add GPIO configuration") Fixes: f7cfc21e9f75 ("net/txgbe: fix link stability for 40G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 5 +++++ drivers/net/txgbe/base/txgbe_phy.c | 9 +++++++++ drivers/net/txgbe/txgbe_ethdev.c | 30 +++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index b52702b197..b28eb5f8ff 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -180,6 +180,11 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, rte_spinlock_lock(&hw->phy_lock); txgbe_e56_set_phy_link_mode(hw, speed, need_restart); rte_spinlock_unlock(&hw->phy_lock); + /* Restore link_valid: a txgbe_set_link_to_amlite() timeout + * leaves it false, and check_phy_link()/check_mac_link() then + * keep forcing the link down after AN73 brings it up. + */ + hw->link_valid = true; return status; } diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index 8b653f0aeb..a50fa986b9 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1125,6 +1125,8 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, identifier = 0x%x", hw->bus.lan_id, identifier); hw->phy.type = txgbe_phy_sfp_unsupported; + if (hw->mac.type == txgbe_mac_aml40) + hw->phy.sfp_type = txgbe_sfp_type_unknown; err = TXGBE_ERR_SFP_NOT_SUPPORTED; } else { err = hw->phy.read_i2c_sff8636(hw, 0, @@ -1158,6 +1160,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) } } + if (err == 0 && hw->mac.type == txgbe_mac_aml40 && + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + hw->phy.type = txgbe_phy_sfp_unsupported; + hw->phy.sfp_type = txgbe_sfp_type_unknown; + err = TXGBE_ERR_SFP_NOT_SUPPORTED; + } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 77e8b9dea7..ececbfb13f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -1975,6 +1975,11 @@ txgbe_dev_start(struct rte_eth_dev *dev) if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_set(1000 * 1000 * 2, txgbe_dev_check_aml_temp_event, dev); + /* The 40G NIC does not deliver a GPIO interrupt on module + * insertion or removal, so poll the module-present level. + */ + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw)) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); } if (tm_conf->root && !tm_conf->committed) @@ -3059,7 +3064,7 @@ txgbe_dev_detect_sfp(void *param) struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); struct txgbe_hw *hw = TXGBE_DEV_HW(dev); u32 value = 0; - s32 err; + s32 err = 0; if (rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, rte_memory_order_acquire) == 0) @@ -3071,6 +3076,9 @@ txgbe_dev_detect_sfp(void *param) err = TXGBE_ERR_SFP_NOT_PRESENT; goto out; } + /* Re-identification is only attempted from the not-present state. */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) + goto rearm; } if (hw->mac.type == txgbe_mac_aml) { @@ -3094,10 +3102,14 @@ txgbe_dev_detect_sfp(void *param) if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) { PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected."); } else if (err == TXGBE_ERR_SFP_NOT_PRESENT) { - PMD_DRV_LOG(INFO, "SFP not present."); - /* Module removed: drop the cached type and stop the watchdog. */ - hw->phy.sfp_type = txgbe_sfp_type_not_present; - rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + /* The poll runs every two seconds while the cage is empty, so + * only the removal itself is reported. + */ + if (hw->phy.sfp_type != txgbe_sfp_type_not_present) { + PMD_DRV_LOG(INFO, "SFP not present."); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); + } } else if (err == 0) { hw->mac.setup_sfp(hw); PMD_DRV_LOG(INFO, "detected SFP+: %d", hw->phy.sfp_type); @@ -3114,6 +3126,14 @@ txgbe_dev_detect_sfp(void *param) } txgbe_dev_link_update(dev, 0); } + +rearm: + if (hw->mac.type == txgbe_mac_aml40 && !txgbe_is_backplane(hw) && + rte_atomic_load_explicit(&adapter->sfp_an_alarm_enabled, + rte_memory_order_acquire) != 0) { + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); + rte_eal_alarm_set(2000 * 1000, txgbe_dev_detect_sfp, dev); + } } static void -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (9 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang ` (4 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On the 40G NIC, an FFE value only reaches the first of the four lanes: the E56 PHY holds one FFE byte per lane, but the tuned taps were written as a single byte value, so the other three lanes keep their default equalizer setting and the received signal on them can be degraded. Use the E56 PHY FFE defaults on the 40G NIC and replicate each tap value over the four lanes. The FFE fields grow to 32 bits to hold the replicated value, and the devargs are parsed after the shared code init so the MAC type is known when the 40G defaults are picked. Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.h | 3 +++ drivers/net/txgbe/base/txgbe_type.h | 8 ++++---- drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 1922a2eb92..a2ae7ccb7e 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1714,6 +1714,9 @@ typedef union { #define S40G_TX_FFE_CFG_PRE2 0x0 #define S40G_TX_FFE_CFG_POST 0x11111111 +/* One FFE byte per lane: replicate a user value over all four. */ +#define S40G_TX_FFE_4LANE(v) ((u32)((v) & 0xFF) * 0x01010101u) + #define BYPASS_CTLE_TAG 0x0 #define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 5c16c4f07e..60298800ee 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -739,10 +739,10 @@ struct txgbe_phy_info { /* Some features need tri-state capability */ u16 ffe_set; - u16 ffe_main; - u16 ffe_pre; - u16 ffe_pre2; - u16 ffe_post; + u32 ffe_main; + u32 ffe_pre; + u32 ffe_pre2; + u32 ffe_post; u16 fec_mode; u16 bp_capa; }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index ececbfb13f..4529d34ca3 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -483,6 +483,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 ffe_set = 0; u16 ffe_main = 27; u16 ffe_pre = 8; + u16 ffe_pre2 = 0; u16 ffe_post = 44; /* FDIR args */ u16 pballoc = 0; @@ -492,6 +493,15 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults + * below are later replicated over the four lanes. + */ + if (hw->mac.type == txgbe_mac_aml40) { + ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; + ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; + } + if (devargs == NULL) goto null; @@ -540,6 +550,14 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_pre = ffe_pre; hw->phy.ffe_post = ffe_post; + /* The 40G PHY expects one FFE byte per lane. */ + if (hw->mac.type == txgbe_mac_aml40) { + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); + hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); + hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); + hw->phy.ffe_post = S40G_TX_FFE_4LANE(ffe_post); + } + fdir_conf->pballoc = pballoc; fdir_conf->drop_queue = drop_queue; } @@ -642,7 +660,6 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) hw->isb_dma = TMZ_PADDR(mz); hw->isb_mem = TMZ_VADDR(mz); - txgbe_parse_devargs(eth_dev); /* Initialize the shared code (base driver) */ err = txgbe_init_shared_code(hw); if (err != 0) { @@ -650,6 +667,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + /* Parsing the devargs requires a known MAC type. */ + txgbe_parse_devargs(eth_dev); + if (hw->mac.type == txgbe_mac_aml) txgbe_override_mac_ops(hw); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (10 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang ` (3 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu The Amber-Lite E56 PHY has per-MAC FFE defaults that differ from the Sapphire defaults. In particular, the second pre-cursor tap defaults to zero, but callers need a devarg to override it when ffe_set is enabled. Add ffe_pre2 for the E56 second pre-cursor tap, and bp_capa for the 40G backplane advertisement selection. The latter supports the existing default of both KR4 and CR4, or either capability alone. Some switches do not reach the mode the board is wired for when both are advertised, and then the NIC has to offer only one of them. The subsystem device ID cannot decide this: it only separates a backplane assembly from an SFP assembly, with no KR4-only or CR4-only value. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 25 ++++++++++++-- doc/guides/rel_notes/release_26_11.rst | 8 +++++ drivers/net/txgbe/base/txgbe_type.h | 6 +++- drivers/net/txgbe/txgbe_ethdev.c | 46 +++++++++++++++++++++++--- 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 90c55141f1..0f5b48683d 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -126,27 +126,40 @@ Please note that following ``devargs`` are only set for backplane NICs. Special treatment for KX SGMII cards. +The following ``devargs`` override the transmitter equalizer taps. +``ffe_main``, ``ffe_pre`` and ``ffe_post`` are used by the backplane link +tuning and by the Amber-Lite E56 PHY; ``ffe_pre2`` is used by the E56 PHY +only. + - ``ffe_set`` (default **0**) Use to set PHY link mode and enable FFE parameters for user debugging. If disabled, the FFE parameters will not take effect. Otherwise, set 1 for SFI mode, set 2 for KR mode, set 3 for KX4 mode, set 4 for KX mode. -- ``ffe_main`` (default **27**) +- ``ffe_main`` (default **42** on the 25G Amber-Lite, **43** on the 40G + Amber-Lite, **27** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_pre`` (default **8**) +- ``ffe_pre`` (default **3** on Amber-Lite, **8** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. -- ``ffe_post`` (default **44**) +- ``ffe_pre2`` (default **0**) + + PHY parameter used for user debugging, only for the Amber-Lite E56 PHY. + Setting other values to take effect requires setting the ``ffe_set``. + +- ``ffe_post`` (default **17** on Amber-Lite, **44** otherwise) PHY parameter used for user debugging. Setting other values to take effect requires setting the ``ffe_set``. +The following ``devargs`` configure the flow director. + - ``pkt-filter-size`` (default **0**) Memory allocation for the flow director filter. @@ -177,6 +190,12 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. In this mode, the hardware merges and writes back a group of RX descriptors together to reduce memory access times, which helps improve performance. +- ``bp_capa`` (default **0**) + + Backplane capability selection for the 40G NIC. Set 0 for both + 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for + 40GBASE-CR4 only. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index be758a0c02..7b6bf917a0 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -200,6 +200,14 @@ New Features * Added VF support on AMD Solarflare X45xx adapters. +* **Updated Wangxun txgbe driver.** + + * Added the ``ffe_pre2`` device argument to tune the second pre-cursor + tap of the Amber-Lite E56 PHY (requires ``ffe_set``). + * Added the ``bp_capa`` device argument to select the advertised + backplane capability on the 40G NIC + (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * **Updated ZTE zxdh ethernet driver.** * Added a fast single-segment Rx path (``zxdh_recv_single_pkts``) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 60298800ee..d65a50530f 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -741,7 +741,7 @@ struct txgbe_phy_info { u16 ffe_set; u32 ffe_main; u32 ffe_pre; - u32 ffe_pre2; + u32 ffe_pre2; /* only for the Amber-Lite E56 PHY */ u32 ffe_post; u16 fec_mode; u16 bp_capa; @@ -754,12 +754,14 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_FFE_SET "ffe_set" #define TXGBE_DEVARG_FFE_MAIN "ffe_main" #define TXGBE_DEVARG_FFE_PRE "ffe_pre" +#define TXGBE_DEVARG_FFE_PRE2 "ffe_pre2" #define TXGBE_DEVARG_FFE_POST "ffe_post" #define TXGBE_DEVARG_FDIR_PBALLOC "pkt-filter-size" #define TXGBE_DEVARG_FDIR_DROP_QUEUE "pkt-filter-drop-queue" #define TXGBE_DEVARG_TX_HEAD_WB "tx_headwb" #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" +#define TXGBE_DEVARG_BP_CAPA "bp_capa" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -769,12 +771,14 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_FFE_SET, TXGBE_DEVARG_FFE_MAIN, TXGBE_DEVARG_FFE_PRE, + TXGBE_DEVARG_FFE_PRE2, TXGBE_DEVARG_FFE_POST, TXGBE_DEVARG_FDIR_PBALLOC, TXGBE_DEVARG_FDIR_DROP_QUEUE, TXGBE_DEVARG_TX_HEAD_WB, TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, + TXGBE_DEVARG_BP_CAPA, NULL }; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4529d34ca3..909457c536 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -492,13 +492,18 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb = 1; u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; + u16 bp_capa = 0; - /* The 40G NIC holds one FFE byte per lane, so the E56 PHY defaults - * below are later replicated over the four lanes. - */ - if (hw->mac.type == txgbe_mac_aml40) { + /* The E56 PHY has its own FFE defaults; the ones above are Sapphire. */ + if (hw->mac.type == txgbe_mac_aml) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + ffe_pre = S25G_TX_FFE_CFG_DAC_PRE1; + ffe_pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + ffe_post = S25G_TX_FFE_CFG_DAC_POST; + } else if (hw->mac.type == txgbe_mac_aml40) { ffe_main = S40G_TX_FFE_CFG_MAIN & 0xFF; ffe_pre = S40G_TX_FFE_CFG_PRE1 & 0xFF; + ffe_pre2 = S40G_TX_FFE_CFG_PRE2 & 0xFF; ffe_post = S40G_TX_FFE_CFG_POST & 0xFF; } @@ -523,6 +528,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &ffe_main); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE, &txgbe_handle_devarg, &ffe_pre); + rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE2, + &txgbe_handle_devarg, &ffe_pre2); rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST, &txgbe_handle_devarg, &ffe_post); rte_kvargs_process(kvlist, TXGBE_DEVARG_FDIR_PBALLOC, @@ -535,6 +542,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &tx_headwb_size); rte_kvargs_process(kvlist, TXGBE_DEVARG_RX_DESC_MERGE, &txgbe_handle_devarg, &rx_desc_merge); + rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, + &txgbe_handle_devarg, &bp_capa); rte_kvargs_free(kvlist); null: @@ -548,10 +557,35 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; + hw->phy.ffe_pre2 = ffe_pre2; hw->phy.ffe_post = ffe_post; + /* The 40G backplane block takes 0, 1 or 2; any other value leaves + * it advertising nothing for 40G. + */ + if (bp_capa > 2) { + PMD_INIT_LOG(ERR, "devarg '%s' value %u exceeds 2, using 0", + TXGBE_DEVARG_BP_CAPA, bp_capa); + bp_capa = 0; + } + hw->phy.bp_capa = bp_capa; + /* The 40G PHY expects one FFE byte per lane. */ if (hw->mac.type == txgbe_mac_aml40) { + /* S40G_TX_FFE_4LANE() keeps the low byte of each value. */ + if (ffe_main > 0xFF) + PMD_INIT_LOG(ERR, "devarg '%s' value %u exceeds 0xFF", + TXGBE_DEVARG_FFE_MAIN, ffe_main); + if (ffe_pre > 0xFF) + PMD_INIT_LOG(ERR, "devarg '%s' value %u exceeds 0xFF", + TXGBE_DEVARG_FFE_PRE, ffe_pre); + if (ffe_pre2 > 0xFF) + PMD_INIT_LOG(ERR, "devarg '%s' value %u exceeds 0xFF", + TXGBE_DEVARG_FFE_PRE2, ffe_pre2); + if (ffe_post > 0xFF) + PMD_INIT_LOG(ERR, "devarg '%s' value %u exceeds 0xFF", + TXGBE_DEVARG_FFE_POST, ffe_post); + hw->phy.ffe_main = S40G_TX_FFE_4LANE(ffe_main); hw->phy.ffe_pre = S40G_TX_FFE_4LANE(ffe_pre); hw->phy.ffe_pre2 = S40G_TX_FFE_4LANE(ffe_pre2); @@ -6474,12 +6508,14 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_FFE_SET "=<0-4>" TXGBE_DEVARG_FFE_MAIN "=<uint16>" TXGBE_DEVARG_FFE_PRE "=<uint16>" + TXGBE_DEVARG_FFE_PRE2 "=<uint16>" TXGBE_DEVARG_FFE_POST "=<uint16>" TXGBE_DEVARG_FDIR_PBALLOC "=<0|1|2>" TXGBE_DEVARG_FDIR_DROP_QUEUE "=<uint8>" TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" - TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>"); + TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" + TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (11 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 14/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang ` (2 subsequent siblings) 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, Jiawen Wu When the port is brought down, the Tx laser stays on, so the peer keeps seeing a live signal and cannot detect the link loss, for example for link-state tracking at the peer. Add a laser_off devarg: when enabled, bring the Tx laser down on port link-down -- for DAC cables disable the PCS through PMD_CFG0, for QSFP modules write the Tx disable bit via I2C -- and restore the Tx enable state when the link comes up. The SFF-8636 Tx disable register is only touched while the management semaphore is held, and the acquire_swfw_sync() result is checked so a failed acquire does not release a semaphore that is not held. For AML40, rerun normal link setup when link is brought up with laser_off enabled. Re-enabling the transmitter alone does not restore the configuration disabled for DAC on link-down. The setup is not gated on the current module classification because the module may have changed while the port was down. That setup resets the PHY and restarts the AN73 negotiation, so the additional disable is opt-in: a port that only has to report link down does not pay for it on the next link-up. Restoring the Tx enable state is deliberately not gated on laser_off in txgbe_enable_tx_laser_multispeed_fiber(). The SFF-8636 Tx disable byte keeps its value while the module stays powered, so a module left with Tx disabled by a run that exited with laser_off=1 is still disabled when the driver next starts with laser_off=0. Nothing else clears that byte when the link comes up, so gating this write would leave the laser off for good. Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- doc/guides/nics/txgbe.rst | 7 ++++++ doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/txgbe/base/txgbe_hw.c | 33 ++++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_phy.h | 6 +++++ drivers/net/txgbe/base/txgbe_type.h | 3 +++ drivers/net/txgbe/txgbe_ethdev.c | 24 ++++++++++++++++++- 6 files changed, 76 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index 0f5b48683d..f45be2c6aa 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -196,6 +196,13 @@ Please note that following ``devargs`` are only set for Amber-Lite NICs. 40GBASE-KR4 and 40GBASE-CR4, set 1 for 40GBASE-KR4 only, set 2 for 40GBASE-CR4 only. +- ``laser_off`` (default **0**) + + Toggle behavior to disable the Tx laser when the port is brought down + on the 40G NIC. By default the Tx laser is left on. When enabled, for + DAC cables the PCS is disabled through PMD_CFG0, for QSFP modules the + Tx disable bit is written via I2C. + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 7b6bf917a0..4f6ff9ea62 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -207,6 +207,10 @@ New Features * Added the ``bp_capa`` device argument to select the advertised backplane capability on the 40G NIC (0 for 40GBASE-KR4 + 40GBASE-CR4, 1 for KR4 only, 2 for CR4 only). + * Added the ``laser_off`` device argument: when set, the 40G NIC + turns its Tx laser off on port down + (PCS disable through PMD_CFG0 for DAC cables, SFF-8636 Tx disable + for QSFP modules). * **Updated ZTE zxdh ethernet driver.** diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 2650b8b7f1..cbf859c54f 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -11,6 +11,7 @@ #include "txgbe_eeprom.h" #include "txgbe_mng.h" #include "txgbe_hw.h" +#include "txgbe_e56.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" @@ -3259,6 +3260,30 @@ void txgbe_disable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg &= ~TXGBE_GPIOBIT_1; + if (hw->devarg.laser_off) { + if (txgbe_is_dac_cable(hw) || + hw->phy.sfp_type == txgbe_sfp_type_unknown || + hw->phy.sfp_type == txgbe_sfp_type_not_present) { + u32 rdata = 0; + + rte_spinlock_lock(&hw->phy_lock); + rdata = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&rdata, + E56PHY_PMD_CFG_0_RX_EN_CFG, + 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, PMD_CFG0, rdata); + rte_spinlock_unlock(&hw->phy_lock); + } else if (hw->mac.acquire_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, + TXGBE_SFF_8636_TX_DISABLE_ALL_LANES); + hw->mac.release_swfw_sync(hw, + TXGBE_MNGSEM_SWPHY); + } + } } else if (hw->mac.type == txgbe_mac_aml) { esdp_reg |= TXGBE_GPIOBIT_1; } else { @@ -3288,6 +3313,14 @@ void txgbe_enable_tx_laser_multispeed_fiber(struct txgbe_hw *hw) if (hw->mac.type == txgbe_mac_aml40) { wr32m(hw, TXGBE_GPIODIR, TXGBE_GPIOBIT_1, TXGBE_GPIOBIT_1); esdp_reg |= TXGBE_GPIOBIT_1; + if (!txgbe_is_dac_cable(hw) && + hw->phy.sfp_type != txgbe_sfp_type_unknown && + hw->phy.sfp_type != txgbe_sfp_type_not_present && + hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY) == 0) { + hw->phy.write_i2c_eeprom(hw, + TXGBE_SFF_8636_TX_DISABLE, 0x0); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + } } else { esdp_reg &= ~(TXGBE_GPIOBIT_0 | TXGBE_GPIOBIT_1); } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a5df015a4d..a06c0eb04e 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -251,6 +251,12 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 + +/* SFF-8636 PMD Tx disable register (byte 0x56); bit per lane, + * 0xF disables the transmitter on all four lanes. + */ +#define TXGBE_SFF_8636_TX_DISABLE 0x56 +#define TXGBE_SFF_8636_TX_DISABLE_ALL_LANES 0x0F #define TXGBE_SFF_10GBE_COMP_CODES 0x03 #define TXGBE_SFF_25GBE_COMP_CODES 0x24 #define TXGBE_SFF_COPPER_LENGTH 0x12 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index d65a50530f..33e306ac70 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -762,6 +762,7 @@ struct txgbe_phy_info { #define TXGBE_DEVARG_TX_HEAD_WB_SIZE "tx_headwb_size" #define TXGBE_DEVARG_RX_DESC_MERGE "rx_desc_merge" #define TXGBE_DEVARG_BP_CAPA "bp_capa" +#define TXGBE_DEVARG_LASER_OFF "laser_off" static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_BP_AUTO, @@ -779,6 +780,7 @@ static const char * const txgbe_valid_arguments[] = { TXGBE_DEVARG_TX_HEAD_WB_SIZE, TXGBE_DEVARG_RX_DESC_MERGE, TXGBE_DEVARG_BP_CAPA, + TXGBE_DEVARG_LASER_OFF, NULL }; @@ -834,6 +836,7 @@ struct txgbe_devargs { u16 tx_headwb; u16 tx_headwb_size; u16 rx_desc_merge; + u16 laser_off; }; struct txgbe_hw { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 909457c536..a72cb15d1a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -493,6 +493,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) u16 tx_headwb_size = 16; u16 rx_desc_merge = 1; u16 bp_capa = 0; + u16 laser_off = 0; /* The E56 PHY has its own FFE defaults; the ones above are Sapphire. */ if (hw->mac.type == txgbe_mac_aml) { @@ -544,6 +545,8 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) &txgbe_handle_devarg, &rx_desc_merge); rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_CAPA, &txgbe_handle_devarg, &bp_capa); + rte_kvargs_process(kvlist, TXGBE_DEVARG_LASER_OFF, + &txgbe_handle_devarg, &laser_off); rte_kvargs_free(kvlist); null: @@ -554,6 +557,7 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) hw->devarg.tx_headwb = tx_headwb; hw->devarg.tx_headwb_size = tx_headwb_size; hw->devarg.rx_desc_merge = rx_desc_merge; + hw->devarg.laser_off = laser_off; hw->phy.ffe_set = ffe_set; hw->phy.ffe_main = ffe_main; hw->phy.ffe_pre = ffe_pre; @@ -2170,6 +2174,9 @@ static int txgbe_dev_set_link_up(struct rte_eth_dev *dev) { struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + bool autoneg = false; + u32 speed; + int err; if (hw->phy.media_type == txgbe_media_type_copper) { /* Turn on the copper */ @@ -2177,6 +2184,20 @@ txgbe_dev_set_link_up(struct rte_eth_dev *dev) } else { /* Turn on the laser */ hw->mac.enable_tx_laser(hw); + + if (hw->mac.type == txgbe_mac_aml40 && hw->devarg.laser_off) { + speed = hw->phy.autoneg_advertised; + if (speed == 0) { + err = hw->mac.get_link_capabilities(hw, &speed, &autoneg); + if (err != 0) + return -EIO; + } + + err = hw->mac.setup_link(hw, speed, true); + if (err != 0) + return -EIO; + } + hw->dev_start = true; txgbe_dev_link_update(dev, 0); } @@ -6515,7 +6536,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_txgbe, TXGBE_DEVARG_TX_HEAD_WB "=<0|1>" TXGBE_DEVARG_TX_HEAD_WB_SIZE "=<1|16>" TXGBE_DEVARG_RX_DESC_MERGE "=<0|1>" - TXGBE_DEVARG_BP_CAPA "=<0|1|2>"); + TXGBE_DEVARG_BP_CAPA "=<0|1|2>" + TXGBE_DEVARG_LASER_OFF "=<0|1>"); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 14/16] net/txgbe: fix CR/KR link training and recovery [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (12 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 15/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 16/16] net/txgbe: respect manual link-down on Amber-Lite Zaiyu Wang 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Backplane CR/KR link training on the E56 PHY is unreliable and does not recover after a link event: the completion poll can block for a second on a condition that never triggers, the page exchange is only run once and its result is assumed to stay valid, and the FFE init mode and calibration ordering are also wrong. - Poll the AN FSM (0x78010) for CL72 completion until bits 0 and 3 are set, ((rdata & 0x9) == 0x9), with a 1 ms step and a 400 ms budget. This replaces the ephy 0x163c mask-0xe poll that tested the wrong condition. The per-lane TX-FFE dumps move into txgbe_e56_get_txffe(), called once AN completes. - Re-run the page exchange on every AN next-page interrupt (1 ms step, 50 ms per exchange round, 200 ms total, explicit next-page handshake, -ETIMEDOUT on expiry) and only enter training after it succeeds. The inline exchange in the AN73 flow is removed and a CL72 failure no longer aborts the flow, so every link event re-runs the exchange instead of assuming the previous one is still valid. - Initialize the FFE init mode bits in cfg_40g()/cfg_10g(), run txgbe_e56_set_rxs_ufine_le_max() after the RXS osc init, and write 0x78001 = 0x7 in the AN programming sequence. - Clear hw->bp_link_mode in txgbe_set_link_to_sfi() so a port that trained on the backplane does not keep a stale backplane mode after switching to SFI. - Avoid register reads that are only used by disabled BP debug logs, and drop a leftover debug line in the watchdog. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_e56.c | 3 + drivers/net/txgbe/base/txgbe_e56.h | 1 + drivers/net/txgbe/base/txgbe_e56_bp.c | 173 ++++++++++++++++---------- drivers/net/txgbe/base/txgbe_e56_bp.h | 2 + drivers/net/txgbe/base/txgbe_osdep.h | 12 +- drivers/net/txgbe/base/txgbe_phy.c | 3 + drivers/net/txgbe/txgbe_ethdev.c | 24 +++- 7 files changed, 146 insertions(+), 72 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index c0e5cc3894..279c9740c1 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -551,6 +551,7 @@ u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); @@ -1377,6 +1378,8 @@ txgbe_e56_cfg_10g(struct txgbe_hw *hw) addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0, + 0x2); set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); wr32_ephy(hw, addr, rdata); diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index a2ae7ccb7e..8897ddde62 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -435,6 +435,7 @@ typedef union { #define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 #define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_0 1, 0 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 #define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c index 760101a05e..17fce56ced 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.c +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -813,6 +813,7 @@ static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + txgbe_e56_set_rxs_ufine_le_max(hw, bp_link_mode); /* Wait an fsm_rx_sts 25G */ BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); @@ -2121,6 +2122,7 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, set_fields_e56(&rdata, 12, 12, 0x1); wr32_epcs(hw, 0x070000, rdata); wr32_epcs(hw, 0x078002, 0x0000); + wr32_epcs(hw, 0x78001, 0x7); /* pcs case fec en to work around first */ wr32_epcs(hw, 0x100ab, 1); @@ -2350,24 +2352,35 @@ static int chk_bkp_ability(struct txgbe_hw *hw, return 0; } -static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +#define AN_PAGE_EXCHANGE_TIMEOUT_MS 200 +int txgbe_e56_exchange_page(struct txgbe_hw *hw) { struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; u32 an_int, base_page = 0; - int count = 0; + int count = 0, count2 = 0; an_int = rd32_epcs(hw, 0x78002); - /* 500ms timeout */ if (!(an_int & VR_AN_INTR_PG_RCV)) return -EINVAL; - for (count = 0; count < 500; count++) { + /* Allow up to 50 ms per page-exchange round, with a 200 ms total budget. */ + for (count = 0; count < 50; count++) { u32 fsm = rd32_epcs(hw, 0x78010); - u32 rdata = rd32_epcs(hw, 0x78002); + u32 next_page = 0; + u32 rdata; + + count2++; + if (count2 >= AN_PAGE_EXCHANGE_TIMEOUT_MS) { + BP_LOG("Wait for next page timeout after %d ms\n", + count2); + return -ETIMEDOUT; + } BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); - BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + rdata = rd32_epcs(hw, 0x78002); + /* clear an pacv int */ an_int = rdata; + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); set_fields_e56(&rdata, 2, 2, 0x0); wr32_epcs(hw, 0x78002, rdata); if (an_int & VR_AN_INTR_PG_RCV) { @@ -2382,33 +2395,89 @@ static int txgbe_e56_exchange_page(struct txgbe_hw *hw) wr32_epcs(hw, 0x70016, 0x2001); BP_LOG("write 70016 0x%0x\n", 0x2001); + next_page = 1; + count = 0; /* reset count to wait next page */ + } else { + next_page = 0; } base_page = 1; } } - if ((fsm & 0x8) == 0x8) { - hw->fsm = 0x8; - goto check_ability; + if (!next_page) { + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } } - usec_delay(100); + usec_delay(1000); } check_ability: + if (count == 50) { + BP_LOG("Wait for next page timeout\n"); + return -ETIMEDOUT; + } + BP_LOG("AN exchange page done in %d ms\n", count2); return chk_bkp_ability(hw, local_ability, lp_ability); } +void txgbe_e56_get_txffe(struct txgbe_hw *hw) +{ + u32 rdata = 0, pmd_ctrl = 0, lane_idx = 0, lane_num = 0, txffe = 0; + + if (!rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) + return; + + /* 21. read txffe to check kr training status */ + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + return; + } + + BP_LOG("%dG phy kr training check.... fsm: %x\n", + hw->bp_link_mode, rd32_epcs(hw, 0x78010)); + rdata = rd32_ephy(hw, 0x163c) & GENMASK(lane_num, 1); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINING CHECK = %x. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } +} + static int txgbe_e56_cl72_training(struct txgbe_hw *hw) { u32 bylinkmode = hw->bp_link_mode; u8 bypass_ctle = hw->bypass_ctle; int status = 0, temp_data = 0; - u32 lane_num = 0, lane_idx = 0; - u32 __rte_unused pmd_ctrl = 0, txffe = 0; int ret = 0; u32 rdata; - + u32 lane_num = 0; u8 pll_en_cfg = 0; u8 pmd_mode = 0; + u32 __rte_unused pmd_ctrl = 0; switch (bylinkmode) { case 10: @@ -2436,6 +2505,7 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); status = txgbe_set_phy_link_mode(hw, bylinkmode); + ret |= status; /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ rdata = rd32_ephy(hw, 0x1434); @@ -2462,51 +2532,49 @@ static int txgbe_e56_cl72_training(struct txgbe_hw *hw) /* 18 */ /* 19. rxs calibration and adaptation sequence */ - BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.4 Wait %dG RXS.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); ret |= status; /* 20 */ - BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_get_temp(hw, &temp_data); + ret |= status; if (bylinkmode == 40) status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); else status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + + ret |= status; /* 21 */ - BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); - status = kr_read_poll(rd32_ephy, rdata, - ((rdata & 0xe) & GENMASK(lane_num, 1)) == - (0xe & GENMASK(lane_num, 1)), 100, - 10000, hw, 0x163c); + BP_LOG("2.6 Wait %dG phy kr fsm check : %x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); + status = kr_read_poll(rd32_epcs, rdata, + (rdata & 0x9) == 0x9, 1000, + 400, hw, 0x78010); pmd_ctrl = rd32_ephy(hw, 0x1644); - BP_LOG("KR TRAINING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + BP_LOG("KR FSM CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", rdata, status ? "FAILED" : "SUCCESS", FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); ret |= status; - BP_LOG("before: %x-%x-%x-%x\n", - rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), - rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); - - for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { - txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); - BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, - FIELD_GET_M(GENMASK(6, 0), txffe), - FIELD_GET_M(GENMASK(21, 16), txffe), - FIELD_GET_M(GENMASK(29, 24), txffe), - FIELD_GET_M(GENMASK(13, 8), txffe)); - } /* 22 */ - BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", - bylinkmode, rd32_epcs(hw, 0x78010)); + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x, an_int: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + ret |= status; + + BP_LOG("2.8 ===end ret : %d.... fsm:%x, an_int: %x\n", + ret, rd32_epcs(hw, 0x78010), + rd32_epcs(hw, 0x78002)); return ret; } @@ -2516,27 +2584,7 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) int status = 0; u32 rdata; - BP_LOG("2.1 Wait page changed ....\n"); - status = txgbe_e56_exchange_page(hw); - if (status) { - BP_LOG("Exchange page failed\n"); - return status; - } - - BP_LOG("2.2 Wait page changed ..done..\n"); - wr32_epcs(hw, 0x100ab, 0); - if (AN_TRAINING_MODE) { - rdata = rd32_epcs(hw, 0x70000); - BP_LOG("read 0x70000 data %0x\n", rdata); - wr32_epcs(hw, 0x70000, 0); - BP_LOG("write 0x70000 0x%0x\n", 0); - } - - rdata = rd32_epcs(hw, 0x78002); - BP_LOG("read 78002 data %0x and clear page int\n", rdata); - set_fields_e56(&rdata, 2, 2, 0x0); - wr32_epcs(hw, 0x78002, rdata); - + /* 10 RXS_DISABLE - TXS_DISABLE - CMS_DISABLE */ /* dis phy tx/rx lane */ rdata = rd32_ephy(hw, 0x1400); set_fields_e56(&rdata, 19, 16, 0x0); @@ -2582,11 +2630,6 @@ int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw) } status = txgbe_e56_cl72_training(hw); - if (status) { - BP_LOG("CL72 training failed, status = %d\n", status); - return status; - } - rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 8089e5b971..f667a052ec 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -279,4 +279,6 @@ typedef union { int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); +int txgbe_e56_exchange_page(struct txgbe_hw *hw); +void txgbe_e56_get_txffe(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index da069e94f6..bb8e49a185 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -31,10 +31,14 @@ extern int txgbe_logtype_bp; #define RTE_LOGTYPE_TXGBE_BP txgbe_logtype_bp #define BP_LOG(fmt, ...) \ - RTE_LOG(DEBUG, TXGBE_BP, \ - "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ - usec_stamp() / 1000000, usec_stamp() % 1000000, \ - __func__, __LINE__, ## __VA_ARGS__) + do { \ + if (rte_log_can_log(RTE_LOGTYPE_TXGBE_BP, RTE_LOG_DEBUG)) \ + RTE_LOG(DEBUG, TXGBE_BP, \ + "[%" PRIu64 ".%" PRIu64 "]%s(%d): " fmt, \ + usec_stamp() / 1000000, \ + usec_stamp() % 1000000, \ + __func__, __LINE__, ## __VA_ARGS__); \ + } while (0) #define ASSERT(x) do { \ if (!(x)) \ diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index a50fa986b9..decfcbadd6 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -1956,6 +1956,9 @@ txgbe_set_link_to_sfi(struct txgbe_hw *hw, s32 err = 0; u32 value = 0; + /* Switching to SFI mode clears backplane link mode. */ + hw->bp_link_mode = 0; + /* Set the module link speed */ hw->mac.set_rate_select_speed(hw, speed); /* 1. Wait xpcs power-up good */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index a72cb15d1a..22ca36210d 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3013,6 +3013,7 @@ void txgbe_dev_e56_check_bp_event(void *param) u32 __rte_unused an_int = 0; int ret = 0; bool need_link_update = false; + bool exchange_done = false; if (!hw) return; @@ -3038,7 +3039,7 @@ void txgbe_dev_e56_check_bp_event(void *param) } } - if (!(txgbe_xpcs_an_enabled(hw))) + if (!txgbe_xpcs_an_enabled(hw)) return; if (!hw->devarg.auto_neg) @@ -3058,6 +3059,7 @@ void txgbe_dev_e56_check_bp_event(void *param) need_link_update = true; value &= ~VR_AN_INTR_CMPLT; wr32_epcs(hw, VR_AN_INTR, value); + txgbe_e56_get_txffe(hw); } if (value & VR_AN_INTR_LINK) { @@ -3075,7 +3077,21 @@ void txgbe_dev_e56_check_bp_event(void *param) } if (value & VR_AN_INTR_PG_RCV) { - BP_LOG("%d Enter training\n", hw->port_id); + BP_LOG("%d 2.1 *** Wait page changed ....\n", hw->port_id); + ret = txgbe_e56_exchange_page(hw); + if (ret) { + BP_LOG("%d 2.2 *** Exchange page failed\n", hw->port_id); + goto an_status; + } else { + BP_LOG("%d 2.2 *** Wait page changed ..done..\n", + hw->port_id); + wr32_epcs(hw, 0x100ab, 0); + exchange_done = true; + } + } + + if (exchange_done) { + BP_LOG("%d 2.2.2 *** Enter training\n", hw->port_id); ret = txgbe_handle_e56_bkp_an73_flow(hw); if (!AN_TRAINING_MODE) { fsm = rd32_epcs(hw, 0x78010); @@ -3798,8 +3814,10 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev, if (eicr & TXGBE_ICRMISC_LSC) intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE; - if (eicr & TXGBE_ICRMISC_ANDONE) + if (eicr & TXGBE_ICRMISC_ANDONE) { + PMD_DRV_LOG(DEBUG, "an int eicr=0x%08x", eicr); intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG; + } if (eicr & TXGBE_ICRMISC_VFMBX) intr->flags |= TXGBE_FLAG_MAILBOX; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 15/16] net/txgbe: align link capabilities and DAC classification [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (13 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 14/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 2026-10-22 11:03 ` [PATCH v9 16/16] net/txgbe: respect manual link-down on Amber-Lite Zaiyu Wang 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu A 10G active-limiting DAC on an Amber-Lite 25G NIC has no fiber_suppport_speed value, so the capability path rejects it. A 10G-only passive DAC can also retain a stale 25G bit after hot-plug. DACs and optical modules are additionally treated differently in the FFE, CTLE and capability-report paths. Rework the AML40/AML link capabilities and DAC classification: - Use the detected DAC speed in the capability paths. Assign 10G for passive 10G-only and active-limiting DACs instead of preserving a speed value left by the previously installed module. - Keep the bp_auto devarg unchanged when a 10G-only DAC disables AN. The XPCS AN gate queries the current link capabilities, so a subsequently hot-plugged AN-capable DAC is re-evaluated and can enable AN73 again. - Add the 40G-active transceiver identification (sfp_type enum and identify branch). Like the kernel driver, 40G active cables are handled through the optical path, as SFF-8636 byte 131 bit 0 ("40G Active Cable") also covers active optical cables. - Unify DAC classification on txgbe_is_dac_cable(), including the 40G FFE selection in txgbe_e56_tx_ffe_cfg() which still open-coded the qsfp_type_40g_cu check; the 10G active cable type (da_act_lmt) is no longer treated as an optical module. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 4 +-- drivers/net/txgbe/base/txgbe_aml40.c | 49 ++++++++++++++++++++-------- drivers/net/txgbe/base/txgbe_e56.c | 9 ++--- drivers/net/txgbe/base/txgbe_phy.c | 23 +++++++++++-- drivers/net/txgbe/base/txgbe_phy.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 ++ 6 files changed, 64 insertions(+), 24 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 7a0839a7d1..ae5c7d7f0d 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -103,11 +103,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; - } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + } else if (txgbe_is_dac_cable(hw)) { if (hw->phy.fiber_suppport_speed == TXGBE_LINK_SPEED_10GB_FULL) { - hw->devarg.auto_neg = false; *autoneg = false; } else { *autoneg = true; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index b28eb5f8ff..a338880345 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -95,27 +95,50 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, return 0; } +static bool txgbe_is_40g_fiber_qsfp(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_sr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_lr_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_active_core1) + return true; + + return false; +} + s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg) { - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { - *speed = hw->phy.fiber_suppport_speed; - *autoneg = hw->devarg.auto_neg; - } else if (txgbe_is_backplane(hw)) { - *speed = TXGBE_LINK_SPEED_40GB_FULL | - TXGBE_LINK_SPEED_10GB_FULL; + /* Backplane */ + if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_40GB_FULL; + /* Backplane supports autonegotiation */ *autoneg = hw->devarg.auto_neg; + return 0; + } + + /* Fiber or DAC cable */ + if (txgbe_is_dac_cable(hw)) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + *autoneg = false; + } else { + *autoneg = hw->devarg.auto_neg; + } + *speed = hw->phy.fiber_suppport_speed; + } else if (txgbe_is_40g_fiber_qsfp(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = false; } else { - /* - * Temporary workaround: set speed to 40G even if sfp not present - * to avoid TXGBE_ERR_LINK_SETUP returned by setup_mac_link, but - * a more reasonable solution is don't execute setup_mac_link when - * sfp module not present. + /* Unknown module: report 40G so setup_mac_link() does not + * fail with TXGBE_ERR_LINK_SETUP. */ *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = true; + *autoneg = false; } return 0; diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 279c9740c1..f966faf56b 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -73,8 +73,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; @@ -92,8 +91,7 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) pre2 = S10G_TX_FFE_CFG_PRE2; post = S10G_TX_FFE_CFG_POST; - if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + if (txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; @@ -2622,8 +2620,7 @@ txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) u32 rdata = 0x0; bool bypass_ctle = true; - if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + if (txgbe_is_dac_cable(hw)) bypass_ctle = 0; if (hw->mac.type == txgbe_mac_aml) { diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index decfcbadd6..896fe7eecf 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -917,7 +917,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) TXGBE_LINK_SPEED_25GB_FULL | TXGBE_LINK_SPEED_10GB_FULL; } else { - hw->phy.fiber_suppport_speed |= + hw->phy.fiber_suppport_speed = TXGBE_LINK_SPEED_10GB_FULL; } } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 || @@ -938,6 +938,8 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type = (hw->bus.lan_id == 0 ? txgbe_sfp_type_da_act_lmt_core0 : txgbe_sfp_type_da_act_lmt_core1); + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_10GB_FULL; } else { hw->phy.sfp_type = txgbe_sfp_type_unknown; } @@ -1158,6 +1160,13 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) else hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } + + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_active_core1; + } } if (err == 0 && hw->mac.type == txgbe_mac_aml40 && @@ -2430,10 +2439,20 @@ int txgbe_is_dac_cable(struct txgbe_hw *hw) int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) { + u32 speed; + bool autoneg; + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) return false; - return hw->devarg.auto_neg ? true : false; + if (!hw->devarg.auto_neg) + return false; + + /* Re-evaluate AN support for the currently detected module. */ + if (hw->mac.get_link_capabilities(hw, &speed, &autoneg) != 0) + return false; + + return autoneg; } /** diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index a06c0eb04e..552fedadab 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -316,6 +316,7 @@ #define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) #define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) #define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE MS(0, 0x1) #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 33e306ac70..a1ce78623b 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -249,6 +249,8 @@ enum txgbe_sfp_type { txgbe_qsfp_type_40g_sr_core1, txgbe_qsfp_type_40g_lr_core0, txgbe_qsfp_type_40g_lr_core1, + txgbe_qsfp_type_40g_active_core0, + txgbe_qsfp_type_40g_active_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* [PATCH v9 16/16] net/txgbe: respect manual link-down on Amber-Lite [not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com> ` (14 preceding siblings ...) 2026-10-22 11:03 ` [PATCH v9 15/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang @ 2026-10-22 11:03 ` Zaiyu Wang 15 siblings, 0 replies; 39+ messages in thread From: Zaiyu Wang @ 2026-10-22 11:03 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu txgbe_dev_set_link_down() clears hw->dev_start, but the Amber-Lite AN73 watchdog treats a down link as a recovery condition and can start negotiation again. The setup-link alarm handler can likewise configure the PHY after a link update or a previous setup retry. As a result, a port brought down through rte_eth_dev_set_link_down() can link up again without a matching rte_eth_dev_set_link_up() call. Use hw->dev_start as the administrative link gate. Keep the AN73 watchdog armed so that monitoring resumes after link-up, but skip link recovery while the port is administratively down. Also make the setup-link alarm handler return before it configures the PHY in that state. This keeps the link down until rte_eth_dev_set_link_up() explicitly re-enables it. The link-up path then restores the required PHY configuration. Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode") Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 22ca36210d..f53fd4cdde 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -3045,8 +3045,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (!hw->devarg.auto_neg) return; - /* only continue if link is down */ - if (dev->data->dev_link.link_status) + /* Continue only for an administratively up port with link down. */ + if (!hw->dev_start || dev->data->dev_link.link_status) goto out; value = rd32_epcs(hw, VR_AN_INTR); @@ -3384,6 +3384,11 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param) bool autoneg = false; u32 gssr = hw->phy.phy_semaphore_mask; + if (!hw->dev_start) { + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; + return; + } + speed = hw->phy.autoneg_advertised; if (!speed) hw->mac.get_link_capabilities(hw, &speed, &autoneg); -- 2.55.0.windows.2 ^ permalink raw reply related [flat|nested] 39+ messages in thread
end of thread, other threads:[~2026-10-22 17:17 UTC | newest]
Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 11:41 [PATCH 00/13] Wangxun fixes and new features Zaiyu Wang
2026-08-27 20:11 ` Stephen Hemminger
2026-09-08 12:43 ` Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 00/16] " Zaiyu Wang
2026-10-12 21:41 ` Stephen Hemminger
[not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com>
2026-10-12 10:56 ` [PATCH v8 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 14/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 15/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-10-12 10:56 ` [PATCH v8 16/16] net/txgbe: respect manual link-down on Amber-Lite Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 00/16] Wangxun fixes and new features Zaiyu Wang
2026-10-22 17:17 ` Stephen Hemminger
[not found] ` <20261022111017.3605-1-zaiyuwang@trustnetic.com>
2026-10-22 11:03 ` [PATCH v9 01/16] net/txgbe: fix failure to configure 10G on dual-speed DAC Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 02/16] net/txgbe: use the requested speed in E56 AN setup Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 03/16] net/txgbe: fix e56 PHY configuration error Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 04/16] net/txgbe: fix incorrect link state in 10G forced mode Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 05/16] net/txgbe: do not force reconfig on link retry Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 06/16] net/txgbe: set i2c sda hold time Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 07/16] net/txgbe: fix link speed display info for 10G mode Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 08/16] net/txgbe: remove stale outer UDP checksum offload flag Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 09/16] net/txgbe: fix SFP hot-plug when auto-negotiation is on Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 10/16] net/txgbe: fix DAC hot-plug on 40G NIC with auto-negotiation Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 11/16] net/txgbe: fix 40G FFE tuning applied to first lane only Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 12/16] net/txgbe: add pre2 FFE tap and backplane capability devargs Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 13/16] net/txgbe: add devarg to turn off Tx laser for 40G NIC Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 14/16] net/txgbe: fix CR/KR link training and recovery Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 15/16] net/txgbe: align link capabilities and DAC classification Zaiyu Wang
2026-10-22 11:03 ` [PATCH v9 16/16] net/txgbe: respect manual link-down on Amber-Lite Zaiyu Wang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox