From nobody Mon Feb 9 10:13:15 2026 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B61126560F; Mon, 21 Apr 2025 13:50:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745243444; cv=none; b=rwHpu5eqBp3GUi7+z6HZhnX8nH+PZMGedITNFlUd8v1XHjBL4F/MIk7gmz/NK8qQj0HmHKKXyFyiWADOaG2wXSmHNtjsngM0yNgr5oDRKIhcujS1zosFd43dM/1vQS1zQAF0iVJuODRgVE0pBIGvRWTy0Uki+H5PEg509ehxWk4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745243444; c=relaxed/simple; bh=7SD9ZhbVN138LPMEg8v/knYXG+Np5pyV2+V8KFGcnb4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IZUprKn+7/tm6h7wh9EvbEsHFNQaG1ubb2iNMqIXci3ZrRJR5djZUvl5a+mRCOaoGePvbQFNTPJQ3IS6i8DaM0AFgt7xpuStxvhVnktXL43pewFExdemDLOFXffGmEhvnsGXNr/1FRdQb8cmHqmjeOgJUAIL/hEsaTkd8bgXA9c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4Zh6CX0Z8bz1R7fH; Mon, 21 Apr 2025 21:48:40 +0800 (CST) Received: from kwepemk100013.china.huawei.com (unknown [7.202.194.61]) by mail.maildlp.com (Postfix) with ESMTPS id EFB18140119; Mon, 21 Apr 2025 21:50:38 +0800 (CST) Received: from localhost.localdomain (10.90.30.45) by kwepemk100013.china.huawei.com (7.202.194.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 21 Apr 2025 21:50:38 +0800 From: Jijie Shao To: , , , , , CC: , , , , , , , , , , Subject: [PATCH RFC net-next 1/2] net: selftest: add net_selftest_custom() interface Date: Mon, 21 Apr 2025 21:43:57 +0800 Message-ID: <20250421134358.1241851-2-shaojijie@huawei.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20250421134358.1241851-1-shaojijie@huawei.com> References: <20250421134358.1241851-1-shaojijie@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To kwepemk100013.china.huawei.com (7.202.194.61) Content-Type: text/plain; charset="utf-8" In net/core/selftests.c, net_selftest() supports loopback tests. However, the loopback content of this interface is a fixed common test and cannot be expanded to add the driver's own test. In this patch, the net_selftest_custom() interface is added to support driver customized loopback tests and extra common loopback tests. Signed-off-by: Jijie Shao --- include/net/selftests.h | 61 +++++++++++++ net/core/selftests.c | 188 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 4 deletions(-) diff --git a/include/net/selftests.h b/include/net/selftests.h index e65e8d230d33..a36e6ee0a41f 100644 --- a/include/net/selftests.h +++ b/include/net/selftests.h @@ -4,6 +4,48 @@ =20 #include =20 +#define NET_TEST_NETIF_CARRIER BIT(0) +#define NET_TEST_FULL_DUPLEX BIT(1) +#define NET_TEST_TCP BIT(2) +#define NET_TEST_UDP BIT(3) +#define NET_TEST_UDP_MAX_MTU BIT(4) + +#define NET_EXTRA_CARRIER_TEST BIT(0) +#define NET_EXTRA_FULL_DUPLEX_TEST BIT(1) +#define NET_EXTRA_PHY_TEST BIT(2) + +struct net_test_entry { + char name[ETH_GSTRING_LEN]; + + /* can set to NULL */ + int (*enable)(struct net_device *ndev, bool enable); + + /* can set to NULL */ + int (*fn)(struct net_device *ndev); + + /* if flag is set, fn() will be ignored, + * and will do test according to the flag, + * such as NET_TEST_UDP... + */ + unsigned long flags; +}; + +#define NET_TEST_E(_name, _enable, _flags) { \ + .name =3D _name, \ + .enable =3D _enable, \ + .fn =3D NULL, \ + .flags =3D _flags } + +#define NET_TEST_ENTRY_MAX_COUNT 10 +struct net_test { + /* extra tests will be added based on this flag */ + unsigned long extra_flags; + + struct net_test_entry entries[NET_TEST_ENTRY_MAX_COUNT]; + /* the count of entries, must <=3D NET_TEST_ENTRY_MAX_COUNT */ + u32 count; +}; + #if IS_ENABLED(CONFIG_NET_SELFTESTS) =20 void net_selftest(struct net_device *ndev, struct ethtool_test *etest, @@ -11,6 +53,11 @@ void net_selftest(struct net_device *ndev, struct ethtoo= l_test *etest, int net_selftest_get_count(void); void net_selftest_get_strings(u8 *data); =20 +void net_selftest_custom(struct net_device *ndev, const struct net_test *t= est, + struct ethtool_test *etest, u64 *buf); +int net_selftest_get_count_custom(const struct net_test *test); +void net_selftest_get_strings_custom(const struct net_test *test, u8 *data= ); + #else =20 static inline void net_selftest(struct net_device *ndev, struct ethtool_te= st *etest, @@ -27,5 +74,19 @@ static inline void net_selftest_get_strings(u8 *data) { } =20 +void net_selftest_custom(struct net_device *ndev, struct net_test *test, + struct ethtool_test *etest, u64 *buf) +{ +} + +int net_selftest_get_count_custom(struct net_test *test) +{ + return 0; +} + +void net_selftest_get_strings_custom(struct net_test *test, u8 *data) +{ +} + #endif #endif /* _NET_SELFTESTS */ diff --git a/net/core/selftests.c b/net/core/selftests.c index e99ae983fca9..e6abae17f324 100644 --- a/net/core/selftests.c +++ b/net/core/selftests.c @@ -289,6 +289,11 @@ static int net_test_netif_carrier(struct net_device *n= dev) return netif_carrier_ok(ndev) ? 0 : -ENOLINK; } =20 +static int net_test_full_duplex(struct net_device *ndev) +{ + return ndev->phydev->duplex =3D=3D DUPLEX_FULL ? 0 : -EINVAL; +} + static int net_test_phy_phydev(struct net_device *ndev) { return ndev->phydev ? 0 : -EOPNOTSUPP; @@ -336,10 +341,7 @@ static int net_test_phy_loopback_tcp(struct net_device= *ndev) return __net_test_loopback(ndev, &attr); } =20 -static const struct net_test { - char name[ETH_GSTRING_LEN]; - int (*fn)(struct net_device *ndev); -} net_selftests[] =3D { +static const struct net_test_entry net_selftests[] =3D { { .name =3D "Carrier ", .fn =3D net_test_netif_carrier, @@ -405,6 +407,184 @@ void net_selftest_get_strings(u8 *data) } EXPORT_SYMBOL_GPL(net_selftest_get_strings); =20 +static const struct net_do_test_func { + int flag; + int (*fn)(struct net_device *ndev); +} net_do_test_funcs[] =3D { + { NET_TEST_NETIF_CARRIER, net_test_netif_carrier }, + { NET_TEST_FULL_DUPLEX, net_test_full_duplex }, + { NET_TEST_UDP, net_test_phy_loopback_udp }, + { NET_TEST_TCP, net_test_phy_loopback_tcp }, + { NET_TEST_UDP_MAX_MTU, net_test_phy_loopback_udp_mtu }, +}; + +static int net_do_test(struct net_device *ndev, + const struct net_test_entry *entry) +{ + int ret =3D -EOPNOTSUPP; + u32 i; + + if (!entry->flags && entry->fn) + return entry->fn(ndev); + + for (i =3D 0; i < ARRAY_SIZE(net_do_test_funcs); i++) { + if (!(entry->flags & net_do_test_funcs[i].flag)) + continue; + + ret =3D net_do_test_funcs[i].fn(ndev); + if (ret) { + netdev_err(ndev, "failed to do test, bit: %#x\n", + net_do_test_funcs[i].flag); + return ret; + } + } + + return ret; +} + +static int net_selftest_entry(struct net_device *ndev, + const struct net_test_entry *entry) +{ + int ret; + + if (entry->enable) { + ret =3D entry->enable(ndev, true); + if (ret) { + netdev_err(ndev, + "failed to enable test, ret =3D %d\n", ret); + return ret; + } + } + + ret =3D net_do_test(ndev, entry); + if (entry->enable) + entry->enable(ndev, false); + return ret; +} + +static void net_selftest_check_result(struct net_device *ndev, + const struct net_test_entry *entry, + struct ethtool_test *etest, u64 *result) +{ + *result =3D net_selftest_entry(ndev, entry); + if (*result) + etest->flags |=3D ETH_TEST_FL_FAILED; +} + +static int net_test_prepare(struct net_device *ndev, + const struct net_test *test, + struct ethtool_test *etest, u64 *buf) +{ + u32 i; + + /* first set all results to -ENOEXEC, + * test->count is also checked in .net_selftest_get_count_custom() + */ + for (i =3D 0; i < net_selftest_get_count_custom(test); i++) + buf[i] =3D -ENOEXEC; + + if (etest->flags !=3D ETH_TEST_FL_OFFLINE) { + netdev_err(ndev, "Only offline tests are supported\n"); + etest->flags |=3D ETH_TEST_FL_FAILED; + return -EOPNOTSUPP; + } + + if (test->count > ARRAY_SIZE(test->entries)) { + netdev_err(ndev, "The count of entries exceeds the maximum\n"); + etest->flags |=3D ETH_TEST_FL_FAILED; + return -EINVAL; + } + + return 0; +} + +static int net_test_phy_enable(struct net_device *ndev, bool enable) +{ + if (!ndev->phydev) + return -EOPNOTSUPP; + + return phy_loopback(ndev->phydev, enable, 0); +} + +static const struct net_extra_test { + int flag; + struct net_test_entry entry; +} net_extra_tests[] =3D { + { + .flag =3D NET_EXTRA_CARRIER_TEST, + .entry =3D NET_TEST_E("Carrier", NULL, NET_TEST_NETIF_CARRIER), + }, { + .flag =3D NET_EXTRA_FULL_DUPLEX_TEST, + .entry =3D NET_TEST_E("Full Duplex", NULL, NET_TEST_FULL_DUPLEX), + }, { + /* this test must be the last one */ + .flag =3D NET_EXTRA_PHY_TEST, + .entry =3D NET_TEST_E("PHY internal loopback", + net_test_phy_enable, + NET_TEST_UDP_MAX_MTU | NET_TEST_TCP), + } +}; + +void net_selftest_custom(struct net_device *ndev, const struct net_test *t= est, + struct ethtool_test *etest, u64 *buf) +{ + u32 i, j =3D 0; + int ret; + + ret =3D net_test_prepare(ndev, test, etest, buf); + if (ret) + return; + + for (i =3D 0; i < test->count; i++) + net_selftest_check_result(ndev, &test->entries[i], + etest, &buf[j++]); + + for (i =3D 0; i < ARRAY_SIZE(net_extra_tests); i++) + if (test->extra_flags & net_extra_tests[i].flag) + net_selftest_check_result(ndev, + &net_extra_tests[i].entry, + etest, &buf[j++]); +} +EXPORT_SYMBOL_GPL(net_selftest_custom); + +int net_selftest_get_count_custom(const struct net_test *test) +{ + u32 i, exter_count =3D 0; + + if (test->count > ARRAY_SIZE(test->entries)) + return 0; + + for (i =3D 0; i < ARRAY_SIZE(net_extra_tests); i++) + if (test->extra_flags & net_extra_tests[i].flag) + exter_count++; + + return test->count + exter_count; +} +EXPORT_SYMBOL_GPL(net_selftest_get_count_custom); + +static void net_selftest_get_entry_string(const struct net_test_entry *ent= ry, + u32 index, u8 **data) +{ + ethtool_sprintf(data, "%2d. %-30s", index, entry->name); +} + +void net_selftest_get_strings_custom(const struct net_test *test, u8 *data) +{ + u32 i, j =3D 1; + + if (test->count > ARRAY_SIZE(test->entries)) + return; + + for (i =3D 0; i < test->count; i++) + net_selftest_get_entry_string(&test->entries[i], j++, &data); + + for (i =3D 0; i < ARRAY_SIZE(net_extra_tests); i++) + if (test->extra_flags & net_extra_tests[i].flag) + net_selftest_get_entry_string(&net_extra_tests[i].entry, + j++, &data); +} +EXPORT_SYMBOL_GPL(net_selftest_get_strings_custom); + MODULE_DESCRIPTION("Common library for generic PHY ethtool selftests"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Oleksij Rempel "); --=20 2.33.0 From nobody Mon Feb 9 10:13:15 2026 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F79D266580; Mon, 21 Apr 2025 13:50:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745243445; cv=none; b=GVVESh8pBvCIv9Za6yAmzuWRHsQWYTLvMBGwNDukyPf+H+o++WQ8HyRDYmW253urdTl0fdcQfeDpJ0J3mQCpCVX7/B8grQwwTOaKqgmIRj0KBmHbG745WlBst4Ua76d6r/u3kp300fC9Dl6V4XmCG4Fyw7CVCmfQBFEdKg6KH0Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745243445; c=relaxed/simple; bh=12mEl+1YTyr+7T+HiJM6voewpOKBSfOE4w8KgEwFzZA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DnOeh2td1MjdOhxAsSa8YVhRAeJUJzFixKlaPLjGyVynApN2zHS4fb3rHNU2XX45M6PhvLhA7zl2vvkthd5dFSACSGQNsOjn0UFYZOeJCGQuX/Dtoq2bATJKblH1N3+boP+c4yl/VRbvyrwafDjLD9tRd/AoN8mwxa4TkbclXTM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.163]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4Zh6CX4W13z1R7fN; Mon, 21 Apr 2025 21:48:40 +0800 (CST) Received: from kwepemk100013.china.huawei.com (unknown [7.202.194.61]) by mail.maildlp.com (Postfix) with ESMTPS id 8316E1800B2; Mon, 21 Apr 2025 21:50:39 +0800 (CST) Received: from localhost.localdomain (10.90.30.45) by kwepemk100013.china.huawei.com (7.202.194.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 21 Apr 2025 21:50:38 +0800 From: Jijie Shao To: , , , , , CC: , , , , , , , , , , Subject: [PATCH RFC net-next 2/2] net: hibmcge: add support for selftest Date: Mon, 21 Apr 2025 21:43:58 +0800 Message-ID: <20250421134358.1241851-3-shaojijie@huawei.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20250421134358.1241851-1-shaojijie@huawei.com> References: <20250421134358.1241851-1-shaojijie@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To kwepemk100013.china.huawei.com (7.202.194.61) Content-Type: text/plain; charset="utf-8" This patch implements selftest, including MAC and SerDes selftest, which is the driver's own test. The .enable() is implemented by the driver. In addition, the driver sets extra_flags to test the carrier status, full duplex, and PHY. For example: ethtool -t enp132s0f1 The test result is PASS The test extra info: 1. MAC internal loopback 0 2. Serdes internal loopback 0 3. Carrier 0 4. Full Duplex 0 5. PHY internal loopback 0 Signed-off-by: Jijie Shao --- .../ethernet/hisilicon/hibmcge/hbg_common.h | 2 + .../ethernet/hisilicon/hibmcge/hbg_ethtool.c | 60 ++++++++++++++++--- .../net/ethernet/hisilicon/hibmcge/hbg_hw.c | 6 ++ .../net/ethernet/hisilicon/hibmcge/hbg_hw.h | 1 + .../net/ethernet/hisilicon/hibmcge/hbg_reg.h | 1 + .../net/ethernet/hisilicon/hibmcge/hbg_txrx.c | 3 +- 6 files changed, 65 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/= net/ethernet/hisilicon/hibmcge/hbg_common.h index 7725cb0c5c8a..876933f88329 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h @@ -84,6 +84,8 @@ enum hbg_hw_event_type { HBG_HW_EVENT_INIT, /* driver is loading */ HBG_HW_EVENT_RESET, HBG_HW_EVENT_CORE_RESET, + HBG_HW_EVENT_SERDES_LOOP_ENABLE, + HBG_HW_EVENT_SERDES_LOOP_DISABLE =3D 5, }; =20 struct hbg_dev_specs { diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers= /net/ethernet/hisilicon/hibmcge/hbg_ethtool.c index 8f1107b85fbb..cc60bd76890d 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "hbg_common.h" #include "hbg_err.h" #include "hbg_ethtool.h" @@ -339,12 +340,55 @@ void hbg_update_stats(struct hbg_priv *priv) ARRAY_SIZE(hbg_ethtool_ctrl_stats_info)); } =20 +static int hbg_test_mac_loopback_enable(struct net_device *ndev, + bool enable) +{ + struct hbg_priv *priv =3D netdev_priv(ndev); + + hbg_hw_loop_enable(priv, enable); + return 0; +} + +static int hbg_test_serdes_loopback_enable(struct net_device *ndev, + bool enable) +{ + struct hbg_priv *priv =3D netdev_priv(ndev); + u32 event =3D enable ? HBG_HW_EVENT_SERDES_LOOP_ENABLE : + HBG_HW_EVENT_SERDES_LOOP_DISABLE; + + return hbg_hw_event_notify(priv, event); +} + +static const struct net_test hbg_test =3D { + .extra_flags =3D NET_EXTRA_CARRIER_TEST | + NET_EXTRA_FULL_DUPLEX_TEST | + NET_EXTRA_PHY_TEST, + .entries =3D { + NET_TEST_E("MAC internal loopback", + hbg_test_mac_loopback_enable, + NET_TEST_UDP_MAX_MTU | NET_TEST_TCP), + NET_TEST_E("Serdes internal loopback", + hbg_test_serdes_loopback_enable, + NET_TEST_UDP_MAX_MTU | NET_TEST_TCP), + }, + .count =3D 2, +}; + +static void hbg_ethtool_self_test(struct net_device *netdev, + struct ethtool_test *etest, + u64 *buf) +{ + net_selftest_custom(netdev, &hbg_test, etest, buf); +} + static int hbg_ethtool_get_sset_count(struct net_device *netdev, int strin= gset) { - if (stringset !=3D ETH_SS_STATS) - return -EOPNOTSUPP; + if (stringset =3D=3D ETH_SS_STATS) + return ARRAY_SIZE(hbg_ethtool_stats_info); + else if (stringset =3D=3D ETH_SS_TEST) + return net_selftest_get_count_custom(&hbg_test); =20 - return ARRAY_SIZE(hbg_ethtool_stats_info); + return -EOPNOTSUPP; } =20 static void hbg_ethtool_get_strings(struct net_device *netdev, @@ -352,11 +396,12 @@ static void hbg_ethtool_get_strings(struct net_device= *netdev, { u32 i; =20 - if (stringset !=3D ETH_SS_STATS) - return; + if (stringset =3D=3D ETH_SS_STATS) + for (i =3D 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++) + ethtool_puts(&data, hbg_ethtool_stats_info[i].name); + else if (stringset =3D=3D ETH_SS_TEST) + net_selftest_get_strings_custom(&hbg_test, data); =20 - for (i =3D 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++) - ethtool_puts(&data, hbg_ethtool_stats_info[i].name); } =20 static void hbg_ethtool_get_stats(struct net_device *netdev, @@ -488,6 +533,7 @@ static const struct ethtool_ops hbg_ethtool_ops =3D { .get_eth_mac_stats =3D hbg_ethtool_get_eth_mac_stats, .get_eth_ctrl_stats =3D hbg_ethtool_get_eth_ctrl_stats, .get_rmon_stats =3D hbg_ethtool_get_rmon_stats, + .self_test =3D hbg_ethtool_self_test, }; =20 void hbg_ethtool_set_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/= ethernet/hisilicon/hibmcge/hbg_hw.c index 9b65eef62b3f..ad3fc572bc13 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c @@ -264,6 +264,12 @@ void hbg_hw_set_rx_pause_mac_addr(struct hbg_priv *pri= v, u64 mac_addr) hbg_reg_write64(priv, HBG_REG_FD_FC_ADDR_LOW_ADDR, mac_addr); } =20 +void hbg_hw_loop_enable(struct hbg_priv *priv, u32 enable) +{ + hbg_reg_write_field(priv, HBG_REG_LOOP_REG_ADDR, + HBG_REG_CF_CG2MI_LP_EN_B, enable); +} + static void hbg_hw_init_transmit_ctrl(struct hbg_priv *priv) { u32 ctrl =3D 0; diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h b/drivers/net/= ethernet/hisilicon/hibmcge/hbg_hw.h index a4a049b5121d..f7917a5353c2 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h @@ -59,5 +59,6 @@ void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, = u32 enable); void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en); void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en= ); void hbg_hw_set_rx_pause_mac_addr(struct hbg_priv *priv, u64 mac_addr); +void hbg_hw_loop_enable(struct hbg_priv *priv, u32 enable); =20 #endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net= /ethernet/hisilicon/hibmcge/hbg_reg.h index a6e7f5e62b48..85b46f35b876 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h @@ -117,6 +117,7 @@ #define HBG_REG_MODE_CHANGE_EN_ADDR (HBG_REG_SGMII_BASE + 0x01B4) #define HBG_REG_MODE_CHANGE_EN_B BIT(0) #define HBG_REG_LOOP_REG_ADDR (HBG_REG_SGMII_BASE + 0x01DC) +#define HBG_REG_CF_CG2MI_LP_EN_B BIT(2) #define HBG_REG_RECV_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x01E0) #define HBG_REG_RECV_CTRL_STRIP_PAD_EN_B BIT(3) #define HBG_REG_VLAN_CODE_ADDR (HBG_REG_SGMII_BASE + 0x01E8) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/ne= t/ethernet/hisilicon/hibmcge/hbg_txrx.c index 8d814c8f19ea..5802748f3a13 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c @@ -258,7 +258,8 @@ static bool hbg_rx_check_l3l4_error(struct hbg_priv *pr= iv, break; case HBG_L4_ZERO_PORT_NUM: priv->stats.rx_desc_l4_zero_port_num_cnt++; - return false; + /* Don't drop packets whose L4 port number is 0. */ + break; default: priv->stats.rx_desc_l4_other_cnt++; return false; --=20 2.33.0