From: Guangbin Huang huangguangbin2@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
----------------------------
If duplex setting is half, mac and phy can not transmit and receive data at the same time, loopback test of serdes and phy will be failed, print message as follow: hns3 0000:bd:00.1 eth5: self test start hns3 0000:bd:00.1 eth5: net stop hns3 0000:bd:00.1 eth5: link down hns3 0000:bd:00.1 eth5: mode 1 recv fail, cnt=0x0, budget=0x1 hns3 0000:bd:00.1 eth5: mode 2 recv fail, cnt=0x0, budget=0x1 hns3 0000:bd:00.1 eth5: mode 3 recv fail, cnt=0x0, budget=0x1 hns3 0000:bd:00.1 eth5: net open hns3 0000:bd:00.1 eth5: self test end The test result is FAIL The test extra info: App Loopback test 0 Serdes serial Loopback test 3 Serdes parallel Loopback test 3 Phy Loopback test 3
To fix this problem, duplex setting of mac or phy will be set to full before serdes and phy starting loopback test, and restore duplex setting after test is end.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Reviewed-by: Jian Shen shenjian15@huawei.com Reviewed-by: Peng Li lipeng321@huawei.com Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 24 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.h | 2 ++ 2 files changed, 26 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9aed9b3b806b..aa6df095916e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6792,8 +6792,14 @@ static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en, static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, enum hnae3_loop loop_mode) { + u8 duplex; int ret;
+ duplex = en ? DUPLEX_FULL : hdev->hw.mac.duplex; + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, duplex); + if (ret) + return ret; + ret = hclge_cfg_serdes_loopback(hdev, en, loop_mode); if (ret) return ret; @@ -6819,6 +6825,12 @@ static int hclge_enable_phy_loopback(struct hclge_dev *hdev, return ret; }
+ hdev->hw.mac.duplex_last = phydev->duplex; + + ret = phy_set_bits(phydev, MII_BMCR, BMCR_FULLDPLX); + if (ret) + return ret; + ret = phy_resume(phydev); if (ret) return ret; @@ -6835,17 +6847,29 @@ static int hclge_disable_phy_loopback(struct hclge_dev *hdev, if (ret) return ret;
+ if (hdev->hw.mac.duplex_last == DUPLEX_HALF) { + ret = phy_clear_bits(phydev, MII_BMCR, BMCR_FULLDPLX); + if (ret) + return ret; + } + return phy_suspend(phydev); }
static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en) { struct phy_device *phydev = hdev->hw.mac.phydev; + u8 duplex; int ret;
if (!phydev) return -ENOTSUPP;
+ duplex = en ? DUPLEX_FULL : hdev->hw.mac.duplex; + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, duplex); + if (ret) + return ret; + if (en) ret = hclge_enable_phy_loopback(hdev, phydev); else diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 864f50c2c6ee..5ab8fd9f6518 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -261,7 +261,9 @@ struct hclge_mac { u8 media_type; /* port media type, e.g. fibre/copper/backplane */ u8 mac_addr[ETH_ALEN]; u8 autoneg; + u8 autoneg_last; u8 duplex; + u8 duplex_last; u8 support_autoneg; u8 speed_type; /* 0: sfp speed, 1: active speed */ u32 speed;