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

index 9cb7ce9fd311c63917e428ea341fefe7cb5327e3..442f15476af32a6a49b8262a34b4f408063a78de 100644 (file)
@@ -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;
 
index 2f1984930da235cb2a744ab4c729d8a962d15190..9fe6bc02d71e6bcfb5bb864f6fb1b1ad2754a117 100644 (file)
@@ -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;
 }