Thread (6 messages) flat view 6 messages, 2 authors, 2025-07-09
STALE421d

[PATCH net-next 1/3] net: phy: qcom: Add PHY counter support

From: Luo Jie <hidden>
Date: 2025-07-08 16:08:57
Also in: linux-arm-msm, lkml
Subsystem: arm/qualcomm mailing list, ethernet phy library, networking drivers, the rest · Maintainers: Andrew Lunn, Heiner Kallweit, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Add PHY counter functionality to the shared library. The implementation
is identical for the current QCA807X and QCA808X PHYs.

Signed-off-by: Luo Jie <redacted>
---
 drivers/net/phy/qcom/qcom-phy-lib.c | 82 +++++++++++++++++++++++++++++++++++++
 drivers/net/phy/qcom/qcom.h         | 16 ++++++++
 2 files changed, 98 insertions(+)
diff --git a/drivers/net/phy/qcom/qcom-phy-lib.c b/drivers/net/phy/qcom/qcom-phy-lib.c
index d28815ef56bb..6447e590539b 100644
--- a/drivers/net/phy/qcom/qcom-phy-lib.c
+++ b/drivers/net/phy/qcom/qcom-phy-lib.c
@@ -14,6 +14,40 @@ MODULE_AUTHOR("Matus Ujhelyi");
 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
 MODULE_LICENSE("GPL");
 
+struct qcom_phy_hw_stat {
+	const char *string;
+	int devad;
+	u16 cnt_31_16_reg;
+	u16 cnt_15_0_reg;
+};
+
+static const struct qcom_phy_hw_stat qcom_phy_hw_stats[] = {
+	{
+		.string		= "phy_rx_good_frame",
+		.devad		= MDIO_MMD_AN,
+		.cnt_31_16_reg	= QCA808X_MMD7_CNT_RX_GOOD_CRC_31_16,
+		.cnt_15_0_reg	= QCA808X_MMD7_CNT_RX_GOOD_CRC_15_0,
+	},
+	{
+		.string		= "phy_rx_bad_frame",
+		.devad		= MDIO_MMD_AN,
+		.cnt_31_16_reg	= 0xffff,
+		.cnt_15_0_reg	= QCA808X_MMD7_CNT_RX_BAD_CRC,
+	},
+	{
+		.string		= "phy_tx_good_frame",
+		.devad		= MDIO_MMD_AN,
+		.cnt_31_16_reg	= QCA808X_MMD7_CNT_TX_GOOD_CRC_31_16,
+		.cnt_15_0_reg	= QCA808X_MMD7_CNT_TX_GOOD_CRC_15_0,
+	},
+	{
+		.string		= "phy_tx_bad_frame",
+		.devad		= MDIO_MMD_AN,
+		.cnt_31_16_reg	= 0xffff,
+		.cnt_15_0_reg	= QCA808X_MMD7_CNT_TX_BAD_CRC,
+	},
+};
+
 int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
 {
 	int ret;
@@ -674,3 +708,51 @@ int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(qca808x_led_reg_blink_set);
+
+/* Enable CRC checking for both received and transmitted frames to support
+ * accurate counter recording.
+ */
+int qcom_phy_counter_crc_check_en(struct phy_device *phydev)
+{
+	return phy_set_bits_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_CTRL,
+				QCA808X_MMD7_CNT_CTRL_CRC_CHECK_EN);
+}
+EXPORT_SYMBOL_GPL(qcom_phy_counter_crc_check_en);
+
+int qcom_phy_get_sset_count(struct phy_device *phydev)
+{
+	return ARRAY_SIZE(qcom_phy_hw_stats);
+}
+EXPORT_SYMBOL_GPL(qcom_phy_get_sset_count);
+
+void qcom_phy_get_strings(struct phy_device *phydev, u8 *data)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(qcom_phy_hw_stats); i++)
+		ethtool_puts(&data, qcom_phy_hw_stats[i].string);
+}
+EXPORT_SYMBOL_GPL(qcom_phy_get_strings);
+
+void qcom_phy_get_stats(struct phy_device *phydev, struct ethtool_stats *stats,
+			u64 *data)
+{
+	struct qcom_phy_hw_stat stat;
+	unsigned int i;
+	int ret, cnt;
+
+	for (i = 0; i < ARRAY_SIZE(qcom_phy_hw_stats); i++) {
+		stat = qcom_phy_hw_stats[i];
+		data[i] = U64_MAX;
+
+		ret = phy_read_mmd(phydev, stat.devad, stat.cnt_15_0_reg);
+		if (ret >= 0) {
+			cnt = ret;
+
+			ret = phy_read_mmd(phydev, stat.devad, stat.cnt_31_16_reg);
+			if (ret >= 0)
+				data[i] = cnt | ret << 16;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(qcom_phy_get_stats);
diff --git a/drivers/net/phy/qcom/qcom.h b/drivers/net/phy/qcom/qcom.h
index 4bb541728846..ee2eb11d8d7e 100644
--- a/drivers/net/phy/qcom/qcom.h
+++ b/drivers/net/phy/qcom/qcom.h
@@ -192,6 +192,17 @@
 #define AT803X_MIN_DOWNSHIFT			2
 #define AT803X_MAX_DOWNSHIFT			9
 
+#define QCA808X_MMD7_CNT_CTRL			0x8029
+#define QCA808X_MMD7_CNT_CTRL_READ_CLEAR_EN	BIT(1)
+#define QCA808X_MMD7_CNT_CTRL_CRC_CHECK_EN	BIT(0)
+
+#define QCA808X_MMD7_CNT_RX_GOOD_CRC_31_16	0x802a
+#define QCA808X_MMD7_CNT_RX_GOOD_CRC_15_0	0x802b
+#define QCA808X_MMD7_CNT_RX_BAD_CRC		0x802c
+#define QCA808X_MMD7_CNT_TX_GOOD_CRC_31_16	0x802d
+#define QCA808X_MMD7_CNT_TX_GOOD_CRC_15_0	0x802e
+#define QCA808X_MMD7_CNT_TX_BAD_CRC		0x802f
+
 enum stat_access_type {
 	PHY,
 	MMD
@@ -241,3 +252,8 @@ int qca808x_led_reg_brightness_set(struct phy_device *phydev,
 int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg,
 			      unsigned long *delay_on,
 			      unsigned long *delay_off);
+int qcom_phy_counter_crc_check_en(struct phy_device *phydev);
+int qcom_phy_get_sset_count(struct phy_device *phydev);
+void qcom_phy_get_strings(struct phy_device *phydev, u8 *data);
+void qcom_phy_get_stats(struct phy_device *phydev, struct ethtool_stats *stats,
+			u64 *data);
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help