* [PATCH 00/13] Wangxun fixes and new features
@ 2026-08-27 11:41 Zaiyu Wang
2026-08-27 20:11 ` Stephen Hemminger
` (2 more replies)
0 siblings, 3 replies; 21+ 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] 21+ 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
[not found] ` <20261012110518.1911-1-zaiyuwang@trustnetic.com>
2 siblings, 1 reply; 21+ 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] 21+ 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; 21+ 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] 21+ 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 siblings, 1 reply; 21+ 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] 21+ messages in thread
* [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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ messages in thread
end of thread, other threads:[~2026-10-12 21:41 UTC | newest]
Thread overview: 21+ 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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox