* [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup
@ 2026-06-24 14:13 Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 1/4] net: hns3: unify copper port ksettings configuration path Jijie Shao
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Jijie Shao @ 2026-06-24 14:13 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, huangdonghua3, yangshuaisong,
netdev, linux-kernel, shaojijie
This patch series addresses a sequence of link configuration deadlocks
and parameter contamination issues in the hns3 network driver, which
typically occur during hardware resets or driver initialization under
specific user-configured scenarios.
The bugs root from asynchronous discrepancies between the MAC state
machine and cached user requests during sudden hardware resets, leading
to invalid parameter combos or frozen registers.
Changes in V2:
- Squashed the former patch 5 ("fix init failure caused by lane_num
contamination") into patch 2, introducing the req_lane_num separation
directly where the helper is created. This avoids a bisect-time
regression where an intermediate commit could fail probe with an
inconsistent (speed, lane_num) pair.
- Added a NULL phydev guard in patch 1 (hclge_set_phy_link_ksettings)
to prevent a kernel panic when firmware reports PHY_INEXISTENT on a
copper port. The previous netdev->phydev check was lost during the
ethtool refactor.
- In patch 1, for copper ports where neither IMP firmware nor a kernel
PHY is available (e.g. PHY_INEXISTENT), hclge_set_phy_link_ksettings()
now returns -ENODEV, and hns3_set_link_ksettings() catches this error
to proceed to the existing MAC-level path (check_ksettings_param
-> cfg_mac_speed_dup_h), preserving compatibility with PHY-less copper
deployments.
- Preserved the 1000BASE-T forced-mode rejection in the kernel PHY
path inside the new hclge_set_phy_link_ksettings() wrapper, closing
a gap identified in community review.
- Fixed a link-loss regression in patch 4 where fiber ports in forced
mode would be configured with the static default_speed instead of the
firmware-probed SFP speed, by synchronizing req_speed from mac.speed
when req_autoneg is overridden to AUTONEG_DISABLE.
- Rewrote the commit message of patch 2 to accurately describe the
init/reset path asymmetry and the req_lane_num rationale.
The series is organized as follows:
- Patch 1 refactors the ethtool link settings entry path to unify copper
port handling (both native kernel PHY_LIB and firmware-controlled PHY)
and ensures req_xxx configurations are uniformly saved across all modes.
For PHY_INEXISTENT copper ports, -ENODEV is returned to allow fallthrough
to MAC-level configuration.
- Patch 2 refactors the MAC initialization by extracting the autoneg and
speed configuration logic out of hclge_mac_init() into a dedicated
helper function, and introduces req_lane_num to isolate the user-
requested lane count from firmware-overwritten mac.lane_num.
- Patch 3 fixes a permanent link-down deadlock after a reset by ensuring
that the driver caches and uses the user's intended autoneg/speed
settings (req_***) rather than unsynchronized runtime states or
SPEED_UNKNOWN tokens.
- Patch 4 fixes a link loss issue on optical ports during initialization
by differentiating autoneg default values between copper and fiber
media types, and synchronizing req_speed with the firmware-probed
SFP speed when forced mode is detected.
Shuaisong Yang (4):
net: hns3: unify copper port ksettings configuration path
net: hns3: refactor MAC autoneg and speed configuration
net: hns3: fix permanent link down deadlock after reset
net: hns3: differentiate autoneg default values between copper and
fiber
.../ethernet/hisilicon/hns3/hns3_ethtool.c | 31 +++--
.../hisilicon/hns3/hns3pf/hclge_main.c | 108 ++++++++++++++----
.../hisilicon/hns3/hns3pf/hclge_main.h | 1 +
3 files changed, 102 insertions(+), 38 deletions(-)
base-commit: d87363b0edfc7504ff2b144fe4cdd8154f90f42e
--
2.33.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH V2 net 1/4] net: hns3: unify copper port ksettings configuration path
2026-06-24 14:13 [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup Jijie Shao
@ 2026-06-24 14:13 ` Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 2/4] net: hns3: refactor MAC autoneg and speed configuration Jijie Shao
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2026-06-24 14:13 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, huangdonghua3, yangshuaisong,
netdev, linux-kernel, shaojijie
From: Shuaisong Yang <yangshuaisong@h-partners.com>
Refactor hns3_set_link_ksettings() and hclge_set_phy_link_ksettings()
to unify the configuration path for copper ports.
Previously, netdevs with a native kernel phy attached bypassed the main
MAC parameter caching logic and returned early via
phy_ethtool_ksettings_set(). This prevented the driver from updating
hdev->hw.mac.req_xxx variables for kernel PHY setups, leaving them
out-of-sync during reset recovery.
Clean this up by routing all copper port configurations through
ops->set_phy_link_ksettings(), and perform driver-level or kernel-level
PHY arbitration inside hclge_set_phy_link_ksettings() via
hnae3_dev_phy_imp_supported(). This ensures that the user's intended link
profiles (req_speed, req_duplex, req_autoneg) are uniformly recorded
across all copper and fiber deployment topologies, laying the groundwork
for stable reset recovery.
For copper ports where neither IMP firmware nor a kernel PHY is available
(e.g. PHY_INEXISTENT), hclge_set_phy_link_ksettings() returns -ENODEV.
In hns3_set_link_ksettings(), this is caught so the configuration falls
through to the existing MAC-level path (check_ksettings_param ->
cfg_mac_speed_dup_h), preserving compatibility with PHY-less copper
deployments.
Signed-off-by: Shuaisong Yang <yangshuaisong@h-partners.com>
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
Changes in V2:
- Add NULL phydev guard in hclge_set_phy_link_ksettings() to prevent
kernel panic when firmware reports PHY_INEXISTENT on a copper port.
- For PHY_INEXISTENT copper ports, return -ENODEV from
hclge_set_phy_link_ksettings() and catch it in
hns3_set_link_ksettings() to fall through to the existing MAC-level
path, preserving compatibility with PHY-less copper deployments.
- Preserve the 1000BASE-T forced-mode (SPEED_1000 + AUTONEG_DISABLE)
rejection in the kernel PHY path, closing a validation gap.
---
.../ethernet/hisilicon/hns3/hns3_ethtool.c | 31 +++++++++----------
.../hisilicon/hns3/hns3pf/hclge_main.c | 28 +++++++++++++++--
2 files changed, 40 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 9cb7ce9fd311..64bee0e78db3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -811,12 +811,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
}
static int hns3_check_ksettings_param(const struct net_device *netdev,
- const struct ethtool_link_ksettings *cmd)
+ const struct ethtool_link_ksettings *cmd,
+ u8 media_type)
{
struct hnae3_handle *handle = hns3_get_handle(netdev);
const struct hnae3_ae_ops *ops = hns3_get_ops(handle);
- u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
- u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
u32 lane_num;
u8 autoneg;
u32 speed;
@@ -836,9 +835,6 @@ static int hns3_check_ksettings_param(const struct net_device *netdev,
return 0;
}
- if (ops->get_media_type)
- ops->get_media_type(handle, &media_type, &module_type);
-
if (cmd->base.duplex == DUPLEX_HALF &&
media_type != HNAE3_MEDIA_TYPE_COPPER) {
netdev_err(netdev,
@@ -863,6 +859,8 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
struct hnae3_handle *handle = hns3_get_handle(netdev);
struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle);
const struct hnae3_ae_ops *ops = hns3_get_ops(handle);
+ u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
+ u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
int ret;
/* Chip don't support this mode. */
@@ -878,22 +876,23 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
cmd->base.autoneg, cmd->base.speed, cmd->base.duplex,
cmd->lanes);
- /* Only support ksettings_set for netdev with phy attached for now */
- if (netdev->phydev) {
- if (cmd->base.speed == SPEED_1000 &&
- cmd->base.autoneg == AUTONEG_DISABLE)
- return -EINVAL;
+ if (!ops->get_media_type)
+ return -EOPNOTSUPP;
+ ops->get_media_type(handle, &media_type, &module_type);
- return phy_ethtool_ksettings_set(netdev->phydev, cmd);
- } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
- ops->set_phy_link_ksettings) {
- return ops->set_phy_link_ksettings(handle, cmd);
+ if (media_type == HNAE3_MEDIA_TYPE_COPPER) {
+ if (!ops->set_phy_link_ksettings)
+ return -EOPNOTSUPP;
+ ret = ops->set_phy_link_ksettings(handle, cmd);
+ if (ret != -ENODEV)
+ return ret;
+ /* PHY_INEXISTENT, use MAC-level configuration */
}
if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
return -EOPNOTSUPP;
- ret = hns3_check_ksettings_param(netdev, cmd);
+ ret = hns3_check_ksettings_param(netdev, cmd, media_type);
if (ret)
return ret;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 2f1984930da2..9fe6bc02d71e 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3285,8 +3285,8 @@ static int hclge_get_phy_link_ksettings(struct hnae3_handle *handle,
}
static int
-hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
- const struct ethtool_link_ksettings *cmd)
+hclge_ethtool_ksettings_set(struct hnae3_handle *handle,
+ const struct ethtool_link_ksettings *cmd)
{
struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM];
struct hclge_vport *vport = hclge_get_vport(handle);
@@ -3327,10 +3327,32 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
return ret;
}
+ linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising);
+ return 0;
+}
+
+static int
+hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+ int ret = -ENODEV;
+
+ if (hnae3_dev_phy_imp_supported(hdev)) {
+ ret = hclge_ethtool_ksettings_set(handle, cmd);
+ } else if (handle->netdev->phydev) {
+ if (cmd->base.speed == SPEED_1000 &&
+ cmd->base.autoneg == AUTONEG_DISABLE)
+ return -EINVAL;
+ ret = phy_ethtool_ksettings_set(handle->netdev->phydev, cmd);
+ }
+ if (ret)
+ return ret;
+
hdev->hw.mac.req_autoneg = cmd->base.autoneg;
hdev->hw.mac.req_speed = cmd->base.speed;
hdev->hw.mac.req_duplex = cmd->base.duplex;
- linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising);
return 0;
}
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH V2 net 2/4] net: hns3: refactor MAC autoneg and speed configuration
2026-06-24 14:13 [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 1/4] net: hns3: unify copper port ksettings configuration path Jijie Shao
@ 2026-06-24 14:13 ` Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 3/4] net: hns3: fix permanent link down deadlock after reset Jijie Shao
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2026-06-24 14:13 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, huangdonghua3, yangshuaisong,
netdev, linux-kernel, shaojijie
From: Shuaisong Yang <yangshuaisong@h-partners.com>
Extract the MAC autoneg and speed/duplex/lane configuration logic out
of hclge_mac_init() and encapsulate it into a new dedicated helper
function hclge_set_autoneg_speed_dup().
In the init path (hclge_init_ae_dev), this helper is now called after
hclge_update_port_info() so that firmware-reported autoneg values are
already populated before applying the link configuration.
Introduce a separate req_lane_num field in struct hclge_mac to isolate
the user-requested lane count from mac.lane_num, which firmware may
overwrite via hclge_get_sfp_info() with stale values from a prior link
lifecycle (e.g., lane_num=4 from 100G). During probe, req_lane_num is
initialized to 0, which instructs firmware to auto-select the correct
lane count for the current speed, rather than reusing the firmware-
reported mac.lane_num that may be inconsistent with the target speed.
This prevents probe failures from mismatched (speed, lane_num) pairs.
In the reset path (hclge_reset_ae_dev), it runs immediately after
hclge_mac_init(), using the previously cached req_* values to restore
the link without re-querying firmware.
Signed-off-by: Shuaisong Yang <yangshuaisong@h-partners.com>
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
Changes in V2:
- Squashed the former patch 5 ("fix init failure caused by lane_num
contamination") into this patch. The req_lane_num separation is
introduced here to avoid a bisect-time regression where an
intermediate commit could fail probe with an inconsistent
(speed, lane_num) pair.
- Rewrote the commit message to accurately describe the init/reset
path asymmetry and the req_lane_num rationale.
---
.../hisilicon/hns3/hns3pf/hclge_main.c | 55 ++++++++++++++-----
.../hisilicon/hns3/hns3pf/hclge_main.h | 1 +
2 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 9fe6bc02d71e..fb12ba77228c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1504,6 +1504,11 @@ static int hclge_configure(struct hclge_dev *hdev)
hdev->hw.mac.req_autoneg = AUTONEG_ENABLE;
hdev->hw.mac.req_duplex = DUPLEX_FULL;
+ /* When lane_num is 0, the firmware will automatically
+ * select the appropriate lane_num based on the speed.
+ */
+ hdev->hw.mac.req_lane_num = 0;
+
hclge_parse_link_mode(hdev, cfg.speed_ability);
hdev->hw.mac.max_speed = hclge_get_max_speed(cfg.speed_ability);
@@ -2579,6 +2584,7 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed,
if (ret)
return ret;
+ hdev->hw.mac.req_lane_num = lane_num;
hdev->hw.mac.req_speed = (u32)speed;
hdev->hw.mac.req_duplex = duplex;
@@ -2884,20 +2890,6 @@ static int hclge_mac_init(struct hclge_dev *hdev)
if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
hdev->hw.mac.duplex = HCLGE_MAC_FULL;
- if (hdev->hw.mac.support_autoneg) {
- ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg);
- if (ret)
- return ret;
- }
-
- if (!hdev->hw.mac.autoneg) {
- ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed,
- hdev->hw.mac.req_duplex,
- hdev->hw.mac.lane_num);
- if (ret)
- return ret;
- }
-
mac->link = 0;
if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) {
@@ -9316,6 +9308,27 @@ static int hclge_set_wol(struct hnae3_handle *handle,
return ret;
}
+static int hclge_set_autoneg_speed_dup(struct hclge_dev *hdev)
+{
+ int ret;
+
+ if (hdev->hw.mac.support_autoneg) {
+ ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg);
+ if (ret)
+ return ret;
+ }
+
+ if (!hdev->hw.mac.autoneg) {
+ ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed,
+ hdev->hw.mac.req_duplex,
+ hdev->hw.mac.req_lane_num);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
{
struct pci_dev *pdev = ae_dev->pdev;
@@ -9477,6 +9490,13 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
if (ret)
goto err_ptp_uninit;
+ ret = hclge_set_autoneg_speed_dup(hdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to set autoneg speed duplex, ret = %d\n", ret);
+ goto err_ptp_uninit;
+ }
+
INIT_KFIFO(hdev->mac_tnl_log);
hclge_dcb_ops_set(hdev);
@@ -9807,6 +9827,13 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
return ret;
}
+ ret = hclge_set_autoneg_speed_dup(hdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to set autoneg speed duplex, ret = %d\n", ret);
+ return ret;
+ }
+
ret = hclge_tp_port_init(hdev);
if (ret) {
dev_err(&pdev->dev, "failed to init tp port, ret = %d\n",
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 87adeb64e6ea..7419481422c3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -287,6 +287,7 @@ struct hclge_mac {
u8 support_autoneg;
u8 speed_type; /* 0: sfp speed, 1: active speed */
u8 lane_num;
+ u8 req_lane_num;
u32 speed;
u32 req_speed;
u32 max_speed;
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH V2 net 3/4] net: hns3: fix permanent link down deadlock after reset
2026-06-24 14:13 [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 1/4] net: hns3: unify copper port ksettings configuration path Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 2/4] net: hns3: refactor MAC autoneg and speed configuration Jijie Shao
@ 2026-06-24 14:13 ` Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 4/4] net: hns3: differentiate autoneg default values between copper and fiber Jijie Shao
2026-06-25 16:20 ` [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2026-06-24 14:13 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, huangdonghua3, yangshuaisong,
netdev, linux-kernel, shaojijie
From: Shuaisong Yang <yangshuaisong@h-partners.com>
Fix a critical race condition deadlock where the network interface
remains permanently Link Down after a hardware reset under specific
ethtool sequences.
This issue exclusively manifests in firmware-controlled PHY topologies
where the driver relies on the IMP firmware to arbitrate link parameters.
Standard devices driven by the kernel's native PHY_LIB are unaffected.
The deadlock occurs via the following path:
1. User disables autoneg and forces an unmatched speed, forcing link
down: `ethtool -s ethx autoneg off speed 10 duplex full`
2. User re-enables autoneg: `ethtool -s ethx autoneg on`. The netdev
stack passes cmd->base.speed as SPEED_UNKNOWN (0xffffffff).
3. Driver saves req_autoneg=1, but before the interface can link up,
a hardware reset is triggered.
4. During reset recovery, MAC init reads the un-synchronized runtime
state mac.autoneg (which is still 0/OFF), misinterprets it as
forced mode, and pushes the cached SPEED_UNKNOWN into the hardware
registers, causing the MAC firmware state machine to freeze.
Meanwhile, PHY init reads req_autoneg=1 and enables PHY autoneg.
Since the MAC is frozen with 0xffffffff and PHY is running autoneg,
they mismatch permanently.
Fix this by:
1. Intercepting SPEED_UNKNOWN/DUPLEX_UNKNOWN in
hclge_set_phy_link_ksettings() and hclge_cfg_mac_speed_dup_h() to
prevent it from corrupting the driver's cached valid configuration.
2. Save req_autoneg in hclge_set_autoneg().
3. Aligning the state judgment in hclge_set_autoneg_speed_dup() to use
req_autoneg instead of the un-synchronized runtime mac.autoneg,
ensuring both MAC and PHY consistently enter the autoneg branch to
eliminate configuration discrepancies during reset recovery.
Fixes: 05eb60e9648c ("net: hns3: using user configure after hardware reset")
Signed-off-by: Shuaisong Yang <yangshuaisong@h-partners.com>
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
.../hisilicon/hns3/hns3pf/hclge_main.c | 22 +++++++++++++------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index fb12ba77228c..d176100d3e4c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -2585,8 +2585,10 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed,
return ret;
hdev->hw.mac.req_lane_num = lane_num;
- hdev->hw.mac.req_speed = (u32)speed;
- hdev->hw.mac.req_duplex = duplex;
+ if (speed != SPEED_UNKNOWN)
+ hdev->hw.mac.req_speed = (u32)speed;
+ if (duplex != DUPLEX_UNKNOWN)
+ hdev->hw.mac.req_duplex = duplex;
return 0;
}
@@ -2617,6 +2619,7 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
+ int ret;
if (!hdev->hw.mac.support_autoneg) {
if (enable) {
@@ -2628,7 +2631,10 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable)
}
}
- return hclge_set_autoneg_en(hdev, enable);
+ ret = hclge_set_autoneg_en(hdev, enable);
+ if (!ret)
+ hdev->hw.mac.req_autoneg = enable;
+ return ret;
}
static int hclge_get_autoneg(struct hnae3_handle *handle)
@@ -3343,8 +3349,10 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
return ret;
hdev->hw.mac.req_autoneg = cmd->base.autoneg;
- hdev->hw.mac.req_speed = cmd->base.speed;
- hdev->hw.mac.req_duplex = cmd->base.duplex;
+ if (cmd->base.speed != SPEED_UNKNOWN)
+ hdev->hw.mac.req_speed = cmd->base.speed;
+ if (cmd->base.duplex != DUPLEX_UNKNOWN)
+ hdev->hw.mac.req_duplex = cmd->base.duplex;
return 0;
}
@@ -9313,12 +9321,12 @@ static int hclge_set_autoneg_speed_dup(struct hclge_dev *hdev)
int ret;
if (hdev->hw.mac.support_autoneg) {
- ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg);
+ ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.req_autoneg);
if (ret)
return ret;
}
- if (!hdev->hw.mac.autoneg) {
+ if (!hdev->hw.mac.req_autoneg) {
ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed,
hdev->hw.mac.req_duplex,
hdev->hw.mac.req_lane_num);
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH V2 net 4/4] net: hns3: differentiate autoneg default values between copper and fiber
2026-06-24 14:13 [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup Jijie Shao
` (2 preceding siblings ...)
2026-06-24 14:13 ` [PATCH V2 net 3/4] net: hns3: fix permanent link down deadlock after reset Jijie Shao
@ 2026-06-24 14:13 ` Jijie Shao
2026-06-25 16:20 ` [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: Jijie Shao @ 2026-06-24 14:13 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, huangdonghua3, yangshuaisong,
netdev, linux-kernel, shaojijie
From: Shuaisong Yang <yangshuaisong@h-partners.com>
Fix a link loss issue during driver initialization on optical ports
connected to forced-mode (non-autoneg) remote switches.
Previously, during driver probe or initialization, hclge_configure()
blindly hardcoded hdev->hw.mac.req_autoneg to AUTONEG_ENABLE for all
media types. While this is necessary for copper (BASE-T) ports to
establish a link, many high-speed optical (fiber) ports in data
centers are connected to switches running in forced mode (fixed speed,
autoneg disabled). Forcing autoneg on these optical ports during
initialization causes a permanent link failure since the remote end
refuses to respond to autoneg pulses.
Fix this by implementing media-type differentiated initialization in
hclge_init_ae_dev(). Copper ports continue to default to
AUTONEG_ENABLE, while optical ports strictly inherit the preset
autoneg status pre-configured by the firmware (hdev->hw.mac.autoneg),
preserving native compatibility with forced-mode network environments.
Fixes: 05eb60e9648c ("net: hns3: using user configure after hardware reset")
Signed-off-by: Shuaisong Yang <yangshuaisong@h-partners.com>
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
Changes in V2:
- Fix a link-loss regression on fiber ports in forced mode where the
helper would configure hardware with the static default_speed instead
of the firmware-probed SFP speed, by synchronizing req_speed from
mac.speed when req_autoneg is overridden to AUTONEG_DISABLE.
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index d176100d3e4c..fc8587c80813 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -9498,6 +9498,13 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
if (ret)
goto err_ptp_uninit;
+ if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER) {
+ hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg;
+ if (hdev->hw.mac.autoneg == AUTONEG_DISABLE &&
+ hdev->hw.mac.speed != SPEED_UNKNOWN)
+ hdev->hw.mac.req_speed = hdev->hw.mac.speed;
+ }
+
ret = hclge_set_autoneg_speed_dup(hdev);
if (ret) {
dev_err(&pdev->dev,
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup
2026-06-24 14:13 [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup Jijie Shao
` (3 preceding siblings ...)
2026-06-24 14:13 ` [PATCH V2 net 4/4] net: hns3: differentiate autoneg default values between copper and fiber Jijie Shao
@ 2026-06-25 16:20 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-06-25 16:20 UTC (permalink / raw)
To: Jijie Shao
Cc: davem, edumazet, kuba, pabeni, andrew+netdev, horms, shenjian15,
liuyonglong, chenhao418, huangdonghua3, yangshuaisong, netdev,
linux-kernel
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 24 Jun 2026 22:13:15 +0800 you wrote:
> This patch series addresses a sequence of link configuration deadlocks
> and parameter contamination issues in the hns3 network driver, which
> typically occur during hardware resets or driver initialization under
> specific user-configured scenarios.
>
> The bugs root from asynchronous discrepancies between the MAC state
> machine and cached user requests during sudden hardware resets, leading
> to invalid parameter combos or frozen registers.
>
> [...]
Here is the summary with links:
- [V2,net,1/4] net: hns3: unify copper port ksettings configuration path
https://git.kernel.org/netdev/net/c/d77e98f8b2b3
- [V2,net,2/4] net: hns3: refactor MAC autoneg and speed configuration
https://git.kernel.org/netdev/net/c/c01f6e6bdc1c
- [V2,net,3/4] net: hns3: fix permanent link down deadlock after reset
https://git.kernel.org/netdev/net/c/c711f6d1cee9
- [V2,net,4/4] net: hns3: differentiate autoneg default values between copper and fiber
https://git.kernel.org/netdev/net/c/d9d349c4e8a0
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-25 16:20 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-24 14:13 [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 1/4] net: hns3: unify copper port ksettings configuration path Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 2/4] net: hns3: refactor MAC autoneg and speed configuration Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 3/4] net: hns3: fix permanent link down deadlock after reset Jijie Shao
2026-06-24 14:13 ` [PATCH V2 net 4/4] net: hns3: differentiate autoneg default values between copper and fiber Jijie Shao
2026-06-25 16:20 ` [PATCH V2 net 0/4] net: hns3: fix configuration deadlocks and refactor link setup patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox