From 2d63dfbc66be0978f1d0e1393af422cfdff55bfc Mon Sep 17 00:00:00 2001 From: Guangbin Huang Date: Tue, 3 Nov 2020 20:33:08 +0800 Subject: [PATCH] net: hns3: fix loopback test of serdes and phy is failed if duplex is half driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICODLZ ---------------------------------------------------------------------- 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. Fixes: b47cfe1f402d ("net: hns3: add phy loopback support for imp-controlled PHYs") Signed-off-by: Guangbin Huang Signed-off-by: Jijie Shao --- .../hisilicon/hns3/hns3pf/hclge_main.c | 26 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + 2 files changed, 27 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 12a781f66c8c..4da98f06fc2d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8515,8 +8515,15 @@ static int hclge_cfg_common_loopback(struct hclge_dev *hdev, bool en, static int hclge_set_common_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, + hdev->hw.mac.lane_num); + if (ret) + return ret; + ret = hclge_cfg_common_loopback(hdev, en, loop_mode); if (ret) return ret; @@ -8542,6 +8549,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; @@ -8558,12 +8571,19 @@ 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) { @@ -8573,6 +8593,12 @@ static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en) return -ENOTSUPP; } + duplex = en ? DUPLEX_FULL : hdev->hw.mac.duplex; + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, duplex, + hdev->hw.mac.lane_num); + 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 dcc928dedc8c..38e8e8f878cc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -285,6 +285,7 @@ struct hclge_mac { u8 autoneg; u8 req_autoneg; u8 duplex; + u8 duplex_last; u8 req_duplex; u8 support_autoneg; u8 speed_type; /* 0: sfp speed, 1: active speed */ -- Gitee