[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250917122954.1265844-4-shaojijie@huawei.com>
Date: Wed, 17 Sep 2025 20:29:54 +0800
From: Jijie Shao <shaojijie@...wei.com>
To: <davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
<pabeni@...hat.com>, <andrew+netdev@...n.ch>, <horms@...nel.org>
CC: <shenjian15@...wei.com>, <liuyonglong@...wei.com>,
<chenhao418@...wei.com>, <lantao5@...wei.com>,
<huangdonghua3@...artners.com>, <yangshuaisong@...artners.com>,
<huangdengdui@...artners.com>, <jonathan.cameron@...wei.com>,
<salil.mehta@...wei.com>, <netdev@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <shaojijie@...wei.com>
Subject: [PATCH net 3/3] net: hns3: use user configure after hardware reset when using kernel PHY
When a reset occurring, it's supposed to recover user's configuration.
Consider the case that reset was happened consecutively. During the first
reset, the port info is configured with a temporary value cause the PHY
is reset and looking for best link config. Second reset start and use
previous configuration which is not the user's. Therefore, in this case,
the network port may not link up.
In this patch, saving user configure to req_xxx variable after successful
configuration when using kernel PHY or firmware PHY. And then, use the
req_xxx variable after hardware reset. Compared to the previous commit
"net: hns3: using user configure after hardware reset", it adds handling
for kernel PHY and FIBER.
Fixes: 05eb60e9648c ("net: hns3: using user configure after hardware reset")
Signed-off-by: Jijie Shao <shaojijie@...wei.com>
---
.../ethernet/hisilicon/hns3/hns3_ethtool.c | 26 ++---
.../hisilicon/hns3/hns3pf/hclge_main.c | 110 +++++++++++++-----
.../hisilicon/hns3/hns3pf/hclge_main.h | 2 +-
3 files changed, 95 insertions(+), 43 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index d5454e126c85..f7ac84840a2f 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,20 @@ 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) {
+ if (media_type == HNAE3_MEDIA_TYPE_COPPER) {
+ if (!ops->set_phy_link_ksettings)
+ return -EOPNOTSUPP;
return ops->set_phy_link_ksettings(handle, cmd);
}
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 85f07219b8be..50150f1cd79c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1574,7 +1574,6 @@ static int hclge_configure(struct hclge_dev *hdev)
return ret;
}
hdev->hw.mac.req_speed = hdev->hw.mac.speed;
- hdev->hw.mac.req_autoneg = AUTONEG_ENABLE;
hdev->hw.mac.req_duplex = DUPLEX_FULL;
hclge_parse_link_mode(hdev, cfg.speed_ability);
@@ -2684,6 +2683,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) {
@@ -2695,7 +2695,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)
@@ -2957,20 +2960,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)) {
@@ -3358,8 +3347,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);
@@ -3369,12 +3358,6 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
u32 advertising;
int ret;
- if (cmd->base.autoneg == AUTONEG_DISABLE &&
- ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) ||
- (cmd->base.duplex != DUPLEX_HALF &&
- cmd->base.duplex != DUPLEX_FULL)))
- return -EINVAL;
-
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING,
false);
desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
@@ -3394,6 +3377,33 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
req1->master_slave_cfg = cmd->base.master_slave_cfg;
ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM);
+
+ if (!ret)
+ linkmode_copy(hdev->hw.mac.advertising,
+ cmd->link_modes.advertising);
+
+ return ret;
+}
+
+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;
+
+ if (cmd->base.autoneg == AUTONEG_DISABLE &&
+ ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) ||
+ (cmd->base.duplex != DUPLEX_HALF &&
+ cmd->base.duplex != DUPLEX_FULL)))
+ return -EINVAL;
+
+ if (hnae3_dev_phy_imp_supported(hdev))
+ ret = hclge_ethtool_ksettings_set(handle, cmd);
+ else
+ ret = phy_ethtool_ksettings_set(handle->netdev->phydev, cmd);
+
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to set phy link ksettings, ret = %d.\n", ret);
@@ -3401,9 +3411,10 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
}
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);
+ 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;
}
@@ -11747,6 +11758,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.req_autoneg);
+ if (ret)
+ return ret;
+ }
+
+ 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.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;
@@ -11908,6 +11940,23 @@ 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 = AUTONEG_ENABLE;
+ else
+ hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg;
+
+ /* When lane_num is 0, the firmware will automatically
+ * select the appropriate lane_num based on the speed.
+ */
+ hdev->hw.mac.lane_num = 0;
+
+ 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);
@@ -12238,6 +12287,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 36f2b06fa17d..f650b07bc739 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -285,7 +285,7 @@ struct hclge_mac {
u8 duplex;
u8 duplex_last;
u8 req_duplex;
- u8 support_autoneg;
+ u8 support_autoneg; /* for non-copper port */
u8 speed_type; /* 0: sfp speed, 1: active speed */
u8 lane_num;
u32 speed;
--
2.33.0
Powered by blists - more mailing lists