[rdkb][common][bsp][Refactor and sync kernel from openwrt]

[Description]
68c27229 [kernel][mt7988][eth][remove XFRM offload related code]
8e0c3427 [kernel][common][eth][Add MIB read feature to the Aquantia PHY driver]
a6ac22c6 [kernel][mt7988][eth][i2.5Gphy: Add 20230731 version firmware]

[Release-log]

Change-Id: I6f24b3d195da60efd817f1472b9accf4eb0e067d
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
old mode 100755
new mode 100644
index 13d852c..634640d
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
@@ -6,4 +6,3 @@
 obj-$(CONFIG_NET_MEDIATEK_SOC)			+= mtk_eth.o
 mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
 obj-$(CONFIG_NET_MEDIATEK_HNAT)			+= mtk_hnat/
-obj-$(CONFIG_XFRM_OFFLOAD)			+= mtk_ipsec.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
old mode 100755
new mode 100644
index 353b656..6272f11
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -31,12 +31,6 @@
 #include "mtk_hnat/nf_hnat_mtk.h"
 #endif
 
-#if defined(CONFIG_XFRM_OFFLOAD)
-#include <crypto/sha.h>
-#include <net/xfrm.h>
-#include "mtk_ipsec.h"
-#endif
-
 static int mtk_msg_level = -1;
 atomic_t reset_lock = ATOMIC_INIT(0);
 atomic_t force = ATOMIC_INIT(0);
@@ -4935,9 +4929,6 @@
 				       mtk_napi_rx, MTK_NAPI_WEIGHT);
 	}
 
-#if defined(CONFIG_XFRM_OFFLOAD)
-	mtk_ipsec_offload_init(eth);
-#endif
 	mtketh_debugfs_init(eth);
 	debug_proc_init(eth);
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_ipsec.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_ipsec.c
deleted file mode 100644
index ff61b90..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_ipsec.c
+++ /dev/null
@@ -1,326 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2022 MediaTek Inc.
-
-#include <crypto/aes.h>
-#include <crypto/hash.h>
-#include <crypto/hmac.h>
-#include <crypto/sha.h>
-#include <crypto/sha3.h>
-#include <net/xfrm.h>
-#include <linux/ip.h>
-#include <linux/psp-sev.h>
-#include <linux/netdevice.h>
-
-#include "mtk_eth_soc.h"
-#include "mtk_ipsec.h"
-
-static inline void write_state_le(__le32 *dst, const u32 *src, u32 size)
-{
-	int i;
-
-	for (i = 0; i < SIZE_IN_WORDS(size); i++)
-		dst[i] = cpu_to_le32(src[i]);
-}
-
-static inline void write_state_be(__le32 *dst, const u32 *src, u32 size)
-{
-	int i;
-
-	for (i = 0; i < SIZE_IN_WORDS(size); i++)
-		dst[i] = cpu_to_be32(src[i]);
-}
-
-static int hmac_init_iv(struct crypto_shash *tfm,
-			unsigned int blocksize, u8 *pad, void *state)
-{
-	SHASH_DESC_ON_STACK(desc, tfm);
-	int ret;
-
-	desc->tfm = tfm;
-
-	ret = crypto_shash_init(desc);
-	if (ret)
-		return ret;
-
-	ret = crypto_shash_update(desc, pad, blocksize);
-	if (ret && ret != -EINPROGRESS && ret != -EBUSY)
-		return ret;
-
-	crypto_shash_export(desc, state);
-	shash_desc_zero(desc);
-
-	return 0;
-}
-
-static int hmac_init_pad(unsigned int blocksize, const u8 *key,
-			 unsigned int keylen, u8 *ipad, u8 *opad)
-{
-	int i;
-
-	if (keylen <= blocksize)
-		memcpy(ipad, key, keylen);
-
-	memset(ipad + keylen, 0, blocksize - keylen);
-	memcpy(opad, ipad, blocksize);
-
-	for (i = 0; i < blocksize; i++) {
-		ipad[i] ^= HMAC_IPAD_VALUE;
-		opad[i] ^= HMAC_OPAD_VALUE;
-	}
-
-	return 0;
-}
-
-int hmac_setkey(const char *alg, const u8 *key, unsigned int keylen,
-		void *istate, void *ostate)
-{
-	struct crypto_shash *tfm;
-	unsigned int blocksize;
-	u8 *ipad, *opad;
-	int ret;
-
-	tfm = crypto_alloc_shash(alg, 0, 0);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-
-	crypto_shash_clear_flags(tfm, ~0);
-	blocksize = crypto_tfm_alg_blocksize(crypto_shash_tfm(tfm));
-
-	ipad = kcalloc(2, blocksize, GFP_KERNEL);
-	if (!ipad) {
-		ret = -ENOMEM;
-		goto free_request;
-	}
-
-	opad = ipad + blocksize;
-
-	ret = hmac_init_pad(blocksize, key, keylen, ipad, opad);
-	if (ret)
-		goto free_ipad;
-
-	ret = hmac_init_iv(tfm, blocksize, ipad, istate);
-	if (ret)
-		goto free_ipad;
-
-	ret = hmac_init_iv(tfm, blocksize, opad, ostate);
-
-free_ipad:
-	kfree(ipad);
-free_request:
-	crypto_free_shash(tfm);
-
-	return ret;
-}
-
-static int mtk_ipsec_add_sa(struct xfrm_state *xs)
-{
-	struct net_device *dev = xs->xso.dev;
-	struct mtk_mac *mac = netdev_priv(dev);
-	struct mtk_eth *eth = mac->hw;
-	struct context_record *context;
-	struct ahash_export_state istate, ostate;
-	unsigned char *key_aalg;
-	unsigned char *key_ealg;
-	unsigned int checksum;
-	unsigned int key_len;
-	int i;
-	int cdrt_idx;
-
-	if (xs->props.family != AF_INET) {
-		netdev_info(dev, "Only IPv4 xfrm states may be offloaded\n");
-		return -EINVAL;
-	}
-
-	if (xs->id.proto != IPPROTO_ESP) {
-		netdev_info(dev, "Unsupported protocol 0x%04x\n",
-			    xs->id.proto);
-		return -EINVAL;
-	}
-
-	context = kzalloc(sizeof(*context), GFP_KERNEL);
-	if (unlikely(!context))
-		return -ENOMEM;
-
-	/**
-	 * Set Transform record
-	 * cdrt_idx=0, outbound for encryption
-	 * cdrt_idx=1, inbound for decryption
-	 **/
-	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
-		/* rx path */
-		context->control0 = CTRL_WORD0_IN;
-		context->control1 = CTRL_WORD1_IN;
-		context->data[46] = 0x01020000;
-		context->data[49] = 0x6117d6a5;
-		context->data[50] = 0x07040c10;
-		context->data[52] = 0xdd07000c;
-		context->data[53] = 0xe4561820;
-		cdrt_idx = 1;
-
-	} else {
-		/* tx path */
-		context->control0 = CTRL_WORD0_OUT;
-		context->control1 = CTRL_WORD1_OUT;
-		memcpy(context->data + 38, &xs->props.saddr.a4, 4);
-		memcpy(context->data + 42, &xs->id.daddr.a4, 4);
-		context->data[46] = 0x04020000;
-		context->data[49] = 0x9e14ed69;
-		context->data[50] = 0x01020c10;
-		context->data[52] = 0xd0060000;
-		context->data[53] = 0xe1560811;
-		context->data[55] = 0x00000049;
-		cdrt_idx = 0;
-	}
-	context->data[47] = 0x00080000;
-	context->data[48] = 0x00f00008;
-	context->data[51] = 0x94119411;
-
-	/* Calculate Checksum */
-	checksum = 0;
-	checksum += context->data[38] % 0x10000;
-	checksum += context->data[38] / 0x10000;
-	checksum += context->data[42] % 0x10000;
-	checksum += context->data[42] / 0x10000;
-	checksum += checksum / 0x10000;
-	checksum = checksum % 0x10000;
-	context->data[39] = checksum;
-
-	/* EIP-96 context words[2...39]*/
-	if (strcmp(xs->aalg->alg_name, "hmac(sha1)") == 0) {
-		key_aalg = &xs->aalg->alg_key[0];
-		hmac_setkey("sha1-generic", key_aalg,
-			    xs->aalg->alg_key_len / 8,
-			    &istate.state, &ostate.state);
-		key_ealg = &xs->ealg->alg_key[0];
-		key_len = xs->ealg->alg_key_len / 8;
-		write_state_le(context->data, (const u32 *)key_ealg, key_len);
-		write_state_be(context->data + SIZE_IN_WORDS(key_len),
-			       (const u32 *)&istate.state, SHA1_DIGEST_SIZE);
-
-		key_len += SHA1_DIGEST_SIZE;
-		write_state_be(context->data + SIZE_IN_WORDS(key_len),
-			       (const u32 *)&ostate.state, SHA1_DIGEST_SIZE);
-
-		key_len += SHA1_DIGEST_SIZE;
-		memcpy(context->data + SIZE_IN_WORDS(key_len),
-		       &xs->id.spi, 4);
-	} else if (strcmp(xs->aalg->alg_name, "hmac(sha256)") == 0) {
-		key_aalg = &xs->aalg->alg_key[0];
-		hmac_setkey("sha256-generic", key_aalg,
-			    xs->aalg->alg_key_len / 8,
-			    &istate.state, &ostate.state);
-		key_ealg = &xs->ealg->alg_key[0];
-		key_len = xs->ealg->alg_key_len / 8;
-		write_state_le(context->data, (const u32 *)key_ealg, key_len);
-		write_state_be(context->data + SIZE_IN_WORDS(key_len),
-			       (const u32 *)&istate.state, SHA256_DIGEST_SIZE);
-
-		key_len += SHA256_DIGEST_SIZE;
-		write_state_be(context->data + SIZE_IN_WORDS(key_len),
-			       (const u32 *)&ostate.state, SHA256_DIGEST_SIZE);
-
-		key_len += SHA256_DIGEST_SIZE;
-		memcpy(context->data + SIZE_IN_WORDS(key_len),
-		       &xs->id.spi, 4);
-
-		if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
-			/* rx path */
-			context->control0 = CTRL_WORD0_IN_SHA256;
-			context->control1 = CTRL_WORD1_IN_SHA256;
-			context->data[50] = 0x07041010;
-			context->data[52] = 0xdd070010;
-			context->data[53] = 0xe4561820;
-		} else {
-			/* tx path */
-			context->control0 = CTRL_WORD0_OUT_SHA256;
-			context->control1 = CTRL_WORD1_OUT_SHA256;
-			context->data[50] = 0x01021010;
-			context->data[53] = 0xe1560817;
-			context->data[55] = 0x0000004d;
-		}
-	}
-
-	/**
-	 * Set CDRT for inline IPSec
-	 * Follow FE_CSR_MEM config flow.
-	 **/
-
-	/* Command descriptor W0-W3 */
-	for (i = MTK_GLO_MEM_DATA0; i <= MTK_GLO_MEM_DATA9; i = i + 4)
-		mtk_w32(eth, 0, i);
-
-	mtk_w32(eth, TYPE(3), MTK_GLO_MEM_DATA0);
-	mtk_w32(eth, TOKEN_LEN(48), MTK_GLO_MEM_DATA1);
-	mtk_w32(eth, __psp_pa(context) | 2, MTK_GLO_MEM_DATA2);
-	mtk_w32(eth, CTRL_CMD(1) | CTRL_INDEX(3) | CTRL_ADDR(cdrt_idx * 3),
-		MTK_GLO_MEM_CTRL);
-
-	/* Command descriptor W4-W7 */
-	for (i = MTK_GLO_MEM_DATA0; i <= MTK_GLO_MEM_DATA9; i = i + 4)
-		mtk_w32(eth, 0, i);
-
-	mtk_w32(eth, HW_SER(2) | ALLOW_PAD | STRIP_PAD, MTK_GLO_MEM_DATA0);
-	mtk_w32(eth, CTRL_CMD(1) | CTRL_INDEX(3) | CTRL_ADDR(cdrt_idx * 3 + 1),
-		MTK_GLO_MEM_CTRL);
-
-	/* Command descriptor W8-W11 */
-	for (i = MTK_GLO_MEM_DATA0; i <= MTK_GLO_MEM_DATA9; i = i + 4)
-		mtk_w32(eth, 0, i);
-
-	mtk_w32(eth, CTRL_CMD(1) | CTRL_INDEX(3) | CTRL_ADDR(cdrt_idx * 3 + 2),
-		MTK_GLO_MEM_CTRL);
-
-	xs->xso.offload_handle = (unsigned long)context;
-
-	return 0;
-}
-
-static void mtk_ipsec_free_state(struct xfrm_state *xs)
-{
-	struct context_record *context;
-
-	if (!xs->xso.offload_handle)
-		return;
-
-	context = (struct context_record *)xs->xso.offload_handle;
-	kfree(context);
-}
-
-static bool mtk_ipsec_offload_ok(struct sk_buff *skb,
-				 struct xfrm_state *xs)
-{
-	struct xfrm_offload *xo = NULL;
-
-	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
-		/* rx path */
-		if (xfrm_offload(skb) != NULL)
-			xo = xfrm_offload(skb);
-
-	} else {
-		/* tx path */
-		if (xfrm_offload(skb) != NULL)
-			xo = xfrm_offload(skb);
-	}
-
-	if (xs->props.family == AF_INET) {
-		/* Offload with IPv4 options is not supported yet */
-		if (ip_hdr(skb)->ihl != 5)
-			return false;
-	}
-
-	return true;
-}
-
-static const struct xfrmdev_ops mtk_xfrmdev_ops = {
-	.xdo_dev_state_add = mtk_ipsec_add_sa,
-	.xdo_dev_state_free = mtk_ipsec_free_state,
-	.xdo_dev_offload_ok = mtk_ipsec_offload_ok,
-};
-
-void mtk_ipsec_offload_init(struct mtk_eth *eth)
-{
-	int i;
-
-	for (i = 0; i < MTK_MAC_COUNT; i++)
-		eth->netdev[i]->xfrmdev_ops = &mtk_xfrmdev_ops;
-}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_ipsec.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_ipsec.h
deleted file mode 100644
index a662dc3..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_ipsec.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2022 MediaTek Inc. */
-
-#ifndef MTK_IPSEC_H
-#define MTK_IPSEC_H
-
-#define CTRL_WORD0_OUT		0x196b1006
-#define CTRL_WORD1_OUT		0x51400001
-#define CTRL_WORD0_IN		0x096ba20f
-#define CTRL_WORD1_IN		0x00010001
-#define CTRL_WORD0_OUT_SHA256	0x19eb1606
-#define CTRL_WORD1_OUT_SHA256	0x57400001
-#define CTRL_WORD0_IN_SHA256	0x09eba20f
-#define CTRL_WORD1_IN_SHA256	0x00010001
-#define SIZE_IN_WORDS(x)	((x) >> 2)
-
-/* Global memory */
-#define MTK_GLO_MEM_CFG		0x600
-#define MTK_GLO_MEM_CTRL	0x604
-#define MTK_GLO_MEM_DATA0	0x608
-#define MTK_GLO_MEM_DATA1	0x60c
-#define MTK_GLO_MEM_DATA2	0x610
-#define MTK_GLO_MEM_DATA3	0x614
-#define MTK_GLO_MEM_DATA4	0x618
-#define MTK_GLO_MEM_DATA5	0x61c
-#define MTK_GLO_MEM_DATA6	0x620
-#define MTK_GLO_MEM_DATA7	0x624
-#define MTK_GLO_MEM_DATA8	0x628
-#define MTK_GLO_MEM_DATA9	0x62c
-
-/* GLO MEM CTRL */
-#define CTRL_CMD(x)		((x) << 30)
-#define CTRL_CMD_SFT		30
-#define CTRL_CMD_MASK		GENMASK(31, 30)
-#define CTRL_INDEX(x)		((x) << 20)
-#define CTRL_INDEX_SFT		20
-#define CTRL_INDEX_MASK		GENMASK(29, 20)
-#define CTRL_ADDR(x)		((x) << 0)
-#define CTRL_ADDR_SFT		0
-#define CTRL_ADDR_MASK		GENMASK(19, 0)
-
-/* CDR Word0 */
-#define TYPE(x)			((x) << 30)
-#define TYPE_SFT		30
-#define TYPE_MASK		GENMASK(31, 30)
-#define ENCLASTDEST		BIT(25)
-#define ENCLASTDEST_MASK	BIT(25)
-
-/* CDR Word1 */
-#define TOKEN_LEN(x)		((x) << 16)
-#define TOKEN_LEN_SFT		16
-#define TOKEN_LEN_MASK		GENMASK(23, 16)
-#define APP_ID(x)		((x) << 9)
-#define APP_ID_SFT		9
-#define APP_ID_MASK		GENMASK(15, 9)
-#define ADD_LEN(x)		((x) << 0)
-#define ADD_LEN_SFT		0
-#define ADD_LEN_MASK		GENMASK(7, 0)
-
-/* CDR Word4 */
-#define FLOW_LOOKUP		BIT(31)
-#define FLOW_LOOKUP_MASK	BIT(31)
-#define HW_SER(x)		((x) << 24)
-#define HW_SER_SFT		24
-#define HW_SER_MASK		GENMASK(29, 24)
-#define ALLOW_PAD		BIT(23)
-#define ALLOW_PAD_MASK		BIT(23)
-#define STRIP_PAD		BIT(22)
-#define STRIP_PAD_MASK		BIT(22)
-#define USER_DEF(x)		((x) << 0)
-#define USER_DEF_SFT		0
-#define USER_DEF_MASK		GENMASK(15, 0)
-
-/* CDR Word5 */
-#define KEEP_OUTER		BIT(28)
-#define KEEP_OUTER_MASK		BIT(28)
-#define PARSE_ETH		BIT(27)
-#define PARSE_ETH_MASK		BIT(27)
-#define L4CHECKSUM		BIT(26)
-#define L4CHECKSUM_MASK		BIT(26)
-#define IPV4CHECKSUM		BIT(25)
-#define IPV4CHECKSUM_MASK	BIT(25)
-#define FL			BIT(24)
-#define FL_MASK			BIT(24)
-#define NEXT_HEADER(x)		((x) << 16)
-#define NEXT_HEADER_SFT		16
-#define NEXT_HEADER_MASK	GENMASK(23, 16)
-
-#define HASH_CACHE_SIZE		SHA512_BLOCK_SIZE
-
-struct ahash_export_state {
-	u64 len;
-	u64 processed;
-
-	u32 digest;
-
-	u32 state[SHA512_DIGEST_SIZE / sizeof(u32)];
-	u8 cache[HASH_CACHE_SIZE];
-};
-
-/* Context Control */
-struct context_record {
-	__le32 control0;
-	__le32 control1;
-
-	__le32 data[62];
-};
-
-void mtk_ipsec_offload_init(struct mtk_eth *eth);
-#endif /* MTK_IPSEC_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2728-net-phy-aquantia-add-mib-read.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2728-net-phy-aquantia-add-mib-read.patch
new file mode 100644
index 0000000..9da1224
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2728-net-phy-aquantia-add-mib-read.patch
@@ -0,0 +1,281 @@
+From f65c0f12471c39c5833b045a429d25ad504dc320 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Thu, 3 Aug 2023 17:05:20 +0800
+Subject: [PATCH] 999-2728-net-phy-aquantia-add-mib-read.patch
+
+---
+ drivers/net/phy/Kconfig         |   6 ++
+ drivers/net/phy/Makefile        |   3 +
+ drivers/net/phy/aquantia.h      |  22 +++++
+ drivers/net/phy/aquantia_main.c |   4 +
+ drivers/net/phy/aquantia_mib.c  | 167 ++++++++++++++++++++++++++++++++
+ 5 files changed, 202 insertions(+)
+ create mode 100644 drivers/net/phy/aquantia_mib.c
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index d467834..d6e2f37 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -405,6 +405,12 @@ config AQUANTIA_PHY_FW_FILE
+ 	---help---
+ 	  Currently supports the Aquantia AQR113c
+ 
++config AQUANTIA_PHY_MIB
++	tristate "MIB Read Enable"
++	depends on AQUANTIA_PHY
++	---help---
++	  Currently supports the Aquantia AQR113C
++
+ config AX88796B_PHY
+ 	tristate "Asix PHYs"
+ 	help
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index e9653de..7aff0be 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -71,6 +71,9 @@ endif
+ ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
+ aquantia-objs			+= aquantia_firmware.o
+ endif
++ifdef CONFIG_AQUANTIA_PHY_MIB
++aquantia-objs			+= aquantia_mib.o
++endif
+ obj-$(CONFIG_AIROHA_EN8801SC_PHY)	+= en8801sc.o
+ obj-$(CONFIG_AIROHA_EN8811H_PHY)	+= air_en8811h.o
+ obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
+diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
+index ab1c241..68845b5 100644
+--- a/drivers/net/phy/aquantia.h
++++ b/drivers/net/phy/aquantia.h
+@@ -47,6 +47,21 @@ static const struct aqr107_hw_stat aqr107_hw_stats[] = {
+ };
+ #define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
+ 
++#ifdef CONFIG_AQUANTIA_PHY_MIB
++struct aqr107_mib_stat {
++	u64 crc8_error_packets;
++	u64 ldpc_error_packets;
++	u64 ls_tx_good_packets;
++	u64 ls_tx_bad_packets;
++	u64 ls_rx_good_packets;
++	u64 ls_rx_bad_packets;
++	u64 ss_tx_good_packets;
++	u64 ss_tx_bad_packets;
++	u64 ss_rx_good_packets;
++	u64 ss_rx_bad_packets;
++};
++#endif
++
+ struct aqr107_priv {
+ 	u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
+ #ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
+@@ -57,6 +72,10 @@ struct aqr107_priv {
+ 	int fw_dl_mode;
+ 	u16 heartbeat;
+ #endif
++#ifdef CONFIG_AQUANTIA_PHY_MIB
++	struct aqr107_mib_stat mib;
++	struct task_struct *mib_thread;
++#endif
+ };
+ 
+ int aqr107_set_downshift(struct phy_device *phydev, u8 cnt);
+@@ -78,3 +97,6 @@ enum {
+ int aqr_firmware_heartbeat_thread(void *data);
+ int aqr_firmware_download(struct phy_device *phydev);
+ #endif
++#ifdef CONFIG_AQUANTIA_PHY_MIB
++int aqr107_config_mib(struct phy_device *phydev);
++#endif
+\ No newline at end of file
+diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
+index 874cd26..5c05ea8 100644
+--- a/drivers/net/phy/aquantia_main.c
++++ b/drivers/net/phy/aquantia_main.c
+@@ -605,6 +605,10 @@ static int aqr107_probe(struct phy_device *phydev)
+ 	if (!phydev->priv)
+ 		return -ENOMEM;
+ 
++#ifdef CONFIG_AQUANTIA_PHY_MIB
++	aqr107_config_mib(phydev);
++#endif
++
+ 	return aqr_hwmon_probe(phydev);
+ }
+ 
+diff --git a/drivers/net/phy/aquantia_mib.c b/drivers/net/phy/aquantia_mib.c
+new file mode 100644
+index 0000000..07223fa
+--- /dev/null
++++ b/drivers/net/phy/aquantia_mib.c
+@@ -0,0 +1,167 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Packet counter driver for Aquantia PHY
++ */
++
++#include <linux/phy.h>
++#include <linux/kernel.h>
++#include <linux/debugfs.h>
++#include <linux/kthread.h>
++
++#include "aquantia.h"
++
++#define MDIO_PCS_LS_TX_GOOD_COUNTER		0xc820
++#define MDIO_PCS_LS_TX_BAD_COUNTER		0xc822
++#define MDIO_PCS_SS_TX_GOOD_COUNTER		0xc860
++#define MDIO_PCS_SS_TX_BAD_COUNTER		0xc862
++#define MDIO_PCS_CRC8_ERROR_COUNTER		0xe810
++#define MDIO_PCS_LS_RX_GOOD_COUNTER		0xe812
++#define MDIO_PCS_LS_RX_BAD_COUNTER		0xe814
++#define MDIO_PCS_LDPC_ERROR_COUNTER		0xe820
++#define MDIO_PCS_SS_RX_GOOD_COUNTER		0xe860
++#define MDIO_PCS_SS_RX_BAD_COUNTER		0xe862
++
++static int aqr107_mib_read_word(struct phy_device *phydev, u32 reg, u16 *lsw, u16 *msw)
++{
++	int val;
++
++	val = phy_read_mmd(phydev, MDIO_MMD_PCS, reg + 1);
++	if (val < 0)
++		return val;
++
++	*msw = val;
++
++	val = phy_read_mmd(phydev, MDIO_MMD_PCS, reg);
++	if (val < 0)
++		return val;
++
++	*lsw = val;
++
++	return 0;
++}
++
++static void aqr107_mib_read(struct phy_device *phydev)
++{
++	struct aqr107_priv *priv = phydev->priv;
++	u16 lsw, msw;
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_CRC8_ERROR_COUNTER, &lsw, &msw))
++		priv->mib.crc8_error_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_LDPC_ERROR_COUNTER, &lsw, &msw))
++		priv->mib.ldpc_error_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_LS_TX_GOOD_COUNTER, &lsw, &msw))
++		priv->mib.ls_tx_good_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_LS_TX_BAD_COUNTER, &lsw, &msw))
++		priv->mib.ls_tx_bad_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_LS_RX_GOOD_COUNTER, &lsw, &msw))
++		priv->mib.ls_rx_good_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_LS_RX_BAD_COUNTER, &lsw, &msw))
++		priv->mib.ls_rx_bad_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_SS_TX_GOOD_COUNTER, &lsw, &msw))
++		priv->mib.ss_tx_good_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_SS_TX_BAD_COUNTER, &lsw, &msw))
++		priv->mib.ss_tx_bad_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_SS_RX_GOOD_COUNTER, &lsw, &msw))
++		priv->mib.ss_rx_good_packets += ((msw << 16) | lsw);
++
++	if (!aqr107_mib_read_word(phydev, MDIO_PCS_SS_RX_BAD_COUNTER, &lsw, &msw))
++		priv->mib.ss_rx_bad_packets += ((msw << 16) | lsw);
++}
++
++static int aqr107_mib_thread(void *data)
++{
++	struct phy_device *phydev = data;
++
++	for (;;) {
++		if (kthread_should_stop())
++			break;
++
++		aqr107_mib_read(phydev);
++
++		set_current_state(TASK_INTERRUPTIBLE);
++		schedule_timeout(HZ);
++	}
++
++	return 0;
++}
++
++static int aqr107_mib_show(struct seq_file *m, void *private)
++{
++	struct phy_device *phydev = m->private;
++	struct aqr107_priv *priv = phydev->priv;
++
++	aqr107_mib_read(phydev);
++
++	seq_printf(m, "+---------------------------------+\n");
++	seq_printf(m, "|         <<AQUANTIA MIB>>        |\n");
++	seq_printf(m, "| CRC8 Error Packets=%012lld |\n", priv->mib.crc8_error_packets);
++	seq_printf(m, "| LDPC Error Packets=%012lld |\n", priv->mib.ldpc_error_packets);
++	seq_printf(m, "|           [Line Side]\n");
++	seq_printf(m, "| TX   Good  Packets=%012lld |\n", priv->mib.ls_tx_good_packets);
++	seq_printf(m, "| TX   Bad   Packets=%012lld |\n", priv->mib.ls_tx_bad_packets);
++	seq_printf(m, "| RX   Good  Packets=%012lld |\n", priv->mib.ls_rx_good_packets);
++	seq_printf(m, "| RX   Bad   Packets=%012lld |\n", priv->mib.ls_rx_bad_packets);
++	seq_printf(m, "|          [System Side]\n");
++	seq_printf(m, "| TX   Good  Packets=%012lld |\n", priv->mib.ss_tx_good_packets);
++	seq_printf(m, "| TX   Bad   Packets=%012lld |\n", priv->mib.ss_tx_bad_packets);
++	seq_printf(m, "| RX   Good  Packets=%012lld |\n", priv->mib.ss_rx_good_packets);
++	seq_printf(m, "| RX   Bad   Packets=%012lld |\n", priv->mib.ss_rx_bad_packets);
++	seq_printf(m, "+---------------------------------+\n");
++
++	memset(&priv->mib, 0, sizeof(priv->mib));
++
++	return 0;
++}
++
++static int aqr107_mib_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, aqr107_mib_show, inode->i_private);
++}
++
++int aqr107_config_mib(struct phy_device *phydev)
++{
++	static const struct file_operations fops_mib = {
++		.open = aqr107_mib_open,
++		.read = seq_read,
++		.llseek = seq_lseek,
++		.release = single_release
++	};
++
++	struct aqr107_priv *priv = phydev->priv;
++	struct dentry *root;
++	char dirname[5];
++
++	snprintf(dirname, sizeof(dirname), "phy%d", phydev->mdio.addr);
++
++	root = debugfs_lookup("aquantia", NULL);
++	if (!root) {
++		root = debugfs_create_dir("aquantia", NULL);
++		if (!root)
++			return -ENOMEM;
++	}
++
++	debugfs_create_file(dirname, S_IRUGO, root, phydev, &fops_mib);
++
++	if (!priv->mib_thread) {
++		/* create a thread for recording packet counts */
++		priv->mib_thread = kthread_create(aqr107_mib_thread,
++						  phydev,
++						  "aqr107_mib_thread");
++		if (IS_ERR(priv->mib_thread)) {
++			phydev_err(phydev,
++				   "failed to create aqr107_mib_thread(%ld)\n",
++				   PTR_ERR(priv->mib_thread));
++			return PTR_ERR(priv->mib_thread);
++		}
++		wake_up_process(priv->mib_thread);
++	}
++
++	return 0;
++}
+-- 
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index 2b9ec88..3fce397 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -147,6 +147,7 @@
     file://999-2724-dt-bindings-phy-Add-DT-bindings-for-Xilinx-ZynqMP-PS.patch \
     file://999-2725-iwconfig-wireless-rate-fix.patch;apply=no \
     file://999-2727-net-phy-sfp-add-debug-info.patch.patch \
+    file://999-2728-net-phy-aquantia-add-mib-read.patch \
     file://999-2800-misc-add-mtk-platform.patch \
     file://999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch \
     file://999-2901-dts-mt7622-remove-cooling-device.patch \