]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: hns3: refactor MAC autoneg and speed configuration
authorShuaisong Yang <yangshuaisong@h-partners.com>
Wed, 24 Jun 2026 14:13:17 +0000 (22:13 +0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 25 Jun 2026 16:15:44 +0000 (09:15 -0700)
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>
Link: https://patch.msgid.link/20260624141319.271439-3-shaojijie@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h

index 9fe6bc02d71e6bcfb5bb864f6fb1b1ad2754a117..fb12ba77228c95029f0fe657c69001199f4c84d6 100644 (file)
@@ -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",
index 87adeb64e6eab7f58cbd0b7b1f16f9963e082185..7419481422c310bda73e86971b30a590314ebc13 100644 (file)
@@ -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;