openwrt-cghmn-mt300n/target/linux/qualcommbe/patches-6.6/103-33-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch
Christian Marangi 93173aee96
qualcommbe: ipq95xx: Add initial support for new target
Add initial support for new target with the initial patch for ethernet
support using pending upstream patches for PCS UNIPHY, PPE and EDMA.

Only initramfs currently working as support for new SPI/NAND
implementation, USB, CPUFreq and other devices is still unfinished and
needs to be evaluated.

Link: https://github.com/openwrt/openwrt/pull/17725
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
2025-01-25 21:24:06 +01:00

683 lines
23 KiB
Diff

From 3e8cb061bff0bf74503cd2f206ed5c599a1e7ff7 Mon Sep 17 00:00:00 2001
From: Lei Wei <quic_leiwei@quicinc.com>
Date: Thu, 29 Feb 2024 20:16:14 +0800
Subject: [PATCH 33/50] net: ethernet: qualcomm: Add PPE port MAC MIB
statistics functions
Add PPE port MAC MIB statistics functions which are used by netdev
ops and ethtool. For GMAC, a polling task is scheduled to read the
MIB counters periodically to avoid 32bit register counter overflow.
Change-Id: Ic20e240061278f77d703f652e1f7d959db8fac37
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
---
drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 465 +++++++++++++++++++
drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 13 +
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 91 ++++
3 files changed, 569 insertions(+)
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
index dcc13889089e..284ee14b8d03 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
@@ -23,6 +23,122 @@
/* PPE BM port start for PPE MAC ports */
#define PPE_BM_PORT_MAC_START 7
+/* Poll interval time to poll GMAC MIBs for overflow protection,
+ * the time should ensure that the 32bit GMAC packet counter
+ * register would not overflow within this time at line rate
+ * speed for 64B packet size.
+ */
+#define PPE_GMIB_POLL_INTERVAL_MS 120000
+
+#define PPE_MAC_MIB_DESC(_s, _o, _n) \
+ { \
+ .size = (_s), \
+ .offset = (_o), \
+ .name = (_n), \
+ }
+
+/* PPE MAC MIB description */
+struct ppe_mac_mib_info {
+ u32 size;
+ u32 offset;
+ const char *name;
+};
+
+/* PPE GMAC MIB statistics type */
+enum ppe_gmib_stats_type {
+ gmib_rx_broadcast,
+ gmib_rx_pause,
+ gmib_rx_multicast,
+ gmib_rx_fcserr,
+ gmib_rx_alignerr,
+ gmib_rx_runt,
+ gmib_rx_frag,
+ gmib_rx_jumbofcserr,
+ gmib_rx_jumboalignerr,
+ gmib_rx_pkt64,
+ gmib_rx_pkt65to127,
+ gmib_rx_pkt128to255,
+ gmib_rx_pkt256to511,
+ gmib_rx_pkt512to1023,
+ gmib_rx_pkt1024to1518,
+ gmib_rx_pkt1519tomax,
+ gmib_rx_toolong,
+ gmib_rx_bytes_g,
+ gmib_rx_bytes_b,
+ gmib_rx_unicast,
+ gmib_tx_broadcast,
+ gmib_tx_pause,
+ gmib_tx_multicast,
+ gmib_tx_underrun,
+ gmib_tx_pkt64,
+ gmib_tx_pkt65to127,
+ gmib_tx_pkt128to255,
+ gmib_tx_pkt256to511,
+ gmib_tx_pkt512to1023,
+ gmib_tx_pkt1024to1518,
+ gmib_tx_pkt1519tomax,
+ gmib_tx_bytes,
+ gmib_tx_collisions,
+ gmib_tx_abortcol,
+ gmib_tx_multicol,
+ gmib_tx_singlecol,
+ gmib_tx_excdeffer,
+ gmib_tx_deffer,
+ gmib_tx_latecol,
+ gmib_tx_unicast,
+};
+
+/* PPE XGMAC MIB statistics type */
+enum ppe_xgmib_stats_type {
+ xgmib_tx_bytes,
+ xgmib_tx_frames,
+ xgmib_tx_broadcast_g,
+ xgmib_tx_multicast_g,
+ xgmib_tx_pkt64,
+ xgmib_tx_pkt65to127,
+ xgmib_tx_pkt128to255,
+ xgmib_tx_pkt256to511,
+ xgmib_tx_pkt512to1023,
+ xgmib_tx_pkt1024tomax,
+ xgmib_tx_unicast,
+ xgmib_tx_multicast,
+ xgmib_tx_broadcast,
+ xgmib_tx_underflow_err,
+ xgmib_tx_bytes_g,
+ xgmib_tx_frames_g,
+ xgmib_tx_pause,
+ xgmib_tx_vlan_g,
+ xgmib_tx_lpi_usec,
+ xgmib_tx_lpi_tran,
+ xgmib_rx_frames,
+ xgmib_rx_bytes,
+ xgmib_rx_bytes_g,
+ xgmib_rx_broadcast_g,
+ xgmib_rx_multicast_g,
+ xgmib_rx_crc_err,
+ xgmib_rx_runt_err,
+ xgmib_rx_jabber_err,
+ xgmib_rx_undersize_g,
+ xgmib_rx_oversize_g,
+ xgmib_rx_pkt64,
+ xgmib_rx_pkt65to127,
+ xgmib_rx_pkt128to255,
+ xgmib_rx_pkt256to511,
+ xgmib_rx_pkt512to1023,
+ xgmib_rx_pkt1024tomax,
+ xgmib_rx_unicast_g,
+ xgmib_rx_len_err,
+ xgmib_rx_outofrange_err,
+ xgmib_rx_pause,
+ xgmib_rx_fifo_overflow,
+ xgmib_rx_vlan,
+ xgmib_rx_wdog_err,
+ xgmib_rx_lpi_usec,
+ xgmib_rx_lpi_tran,
+ xgmib_rx_drop_frames,
+ xgmib_rx_drop_bytes,
+};
+
/* PPE port clock and reset name */
static const char * const ppe_port_clk_rst_name[] = {
[PPE_PORT_CLK_RST_MAC] = "port_mac",
@@ -30,6 +146,322 @@ static const char * const ppe_port_clk_rst_name[] = {
[PPE_PORT_CLK_RST_TX] = "port_tx",
};
+/* PPE GMAC MIB statistics description information */
+static const struct ppe_mac_mib_info gmib_info[] = {
+ PPE_MAC_MIB_DESC(4, GMAC_RXBROAD_ADDR, "rx_broadcast"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPAUSE_ADDR, "rx_pause"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXMULTI_ADDR, "rx_multicast"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXFCSERR_ADDR, "rx_fcserr"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXALIGNERR_ADDR, "rx_alignerr"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXRUNT_ADDR, "rx_runt"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXFRAG_ADDR, "rx_frag"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXJUMBOFCSERR_ADDR, "rx_jumbofcserr"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXJUMBOALIGNERR_ADDR, "rx_jumboalignerr"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT64_ADDR, "rx_pkt64"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT65TO127_ADDR, "rx_pkt65to127"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT128TO255_ADDR, "rx_pkt128to255"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT256TO511_ADDR, "rx_pkt256to511"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT512TO1023_ADDR, "rx_pkt512to1023"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT1024TO1518_ADDR, "rx_pkt1024to1518"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT1519TOX_ADDR, "rx_pkt1519tomax"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXTOOLONG_ADDR, "rx_toolong"),
+ PPE_MAC_MIB_DESC(8, GMAC_RXBYTE_G_ADDR, "rx_bytes_g"),
+ PPE_MAC_MIB_DESC(8, GMAC_RXBYTE_B_ADDR, "rx_bytes_b"),
+ PPE_MAC_MIB_DESC(4, GMAC_RXUNI_ADDR, "rx_unicast"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXBROAD_ADDR, "tx_broadcast"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPAUSE_ADDR, "tx_pause"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXMULTI_ADDR, "tx_multicast"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXUNDERRUN_ADDR, "tx_underrun"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT64_ADDR, "tx_pkt64"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT65TO127_ADDR, "tx_pkt65to127"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT128TO255_ADDR, "tx_pkt128to255"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT256TO511_ADDR, "tx_pkt256to511"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT512TO1023_ADDR, "tx_pkt512to1023"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT1024TO1518_ADDR, "tx_pkt1024to1518"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT1519TOX_ADDR, "tx_pkt1519tomax"),
+ PPE_MAC_MIB_DESC(8, GMAC_TXBYTE_ADDR, "tx_bytes"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXCOLLISIONS_ADDR, "tx_collisions"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXABORTCOL_ADDR, "tx_abortcol"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXMULTICOL_ADDR, "tx_multicol"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXSINGLECOL_ADDR, "tx_singlecol"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXEXCESSIVEDEFER_ADDR, "tx_excdeffer"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXDEFER_ADDR, "tx_deffer"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXLATECOL_ADDR, "tx_latecol"),
+ PPE_MAC_MIB_DESC(4, GMAC_TXUNI_ADDR, "tx_unicast"),
+};
+
+/* PPE XGMAC MIB statistics description information */
+static const struct ppe_mac_mib_info xgmib_info[] = {
+ PPE_MAC_MIB_DESC(8, XGMAC_TXBYTE_GB_ADDR, "tx_bytes"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT_GB_ADDR, "tx_frames"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXBROAD_G_ADDR, "tx_broadcast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXMULTI_G_ADDR, "tx_multicast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT64_GB_ADDR, "tx_pkt64"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT65TO127_GB_ADDR, "tx_pkt65to127"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT128TO255_GB_ADDR, "tx_pkt128to255"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT256TO511_GB_ADDR, "tx_pkt256to511"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT512TO1023_GB_ADDR, "tx_pkt512to1023"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT1024TOMAX_GB_ADDR, "tx_pkt1024tomax"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXUNI_GB_ADDR, "tx_unicast"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXMULTI_GB_ADDR, "tx_multicast"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXBROAD_GB_ADDR, "tx_broadcast"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXUNDERFLOW_ERR_ADDR, "tx_underflow_err"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXBYTE_G_ADDR, "tx_bytes_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT_G_ADDR, "tx_frames_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXPAUSE_ADDR, "tx_pause"),
+ PPE_MAC_MIB_DESC(8, XGMAC_TXVLAN_G_ADDR, "tx_vlan_g"),
+ PPE_MAC_MIB_DESC(4, XGMAC_TXLPI_USEC_ADDR, "tx_lpi_usec"),
+ PPE_MAC_MIB_DESC(4, XGMAC_TXLPI_TRAN_ADDR, "tx_lpi_tran"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT_GB_ADDR, "rx_frames"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXBYTE_GB_ADDR, "rx_bytes"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXBYTE_G_ADDR, "rx_bytes_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXBROAD_G_ADDR, "rx_broadcast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXMULTI_G_ADDR, "rx_multicast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXCRC_ERR_ADDR, "rx_crc_err"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXRUNT_ERR_ADDR, "rx_runt_err"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXJABBER_ERR_ADDR, "rx_jabber_err"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXUNDERSIZE_G_ADDR, "rx_undersize_g"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXOVERSIZE_G_ADDR, "rx_oversize_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT64_GB_ADDR, "rx_pkt64"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT65TO127_GB_ADDR, "rx_pkt65to127"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT128TO255_GB_ADDR, "rx_pkt128to255"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT256TO511_GB_ADDR, "rx_pkt256to511"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT512TO1023_GB_ADDR, "rx_pkt512to1023"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT1024TOMAX_GB_ADDR, "rx_pkt1024tomax"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXUNI_G_ADDR, "rx_unicast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXLEN_ERR_ADDR, "rx_len_err"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXOUTOFRANGE_ADDR, "rx_outofrange_err"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXPAUSE_ADDR, "rx_pause"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXFIFOOVERFLOW_ADDR, "rx_fifo_overflow"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXVLAN_GB_ADDR, "rx_vlan"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXWATCHDOG_ERR_ADDR, "rx_wdog_err"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXLPI_USEC_ADDR, "rx_lpi_usec"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXLPI_TRAN_ADDR, "rx_lpi_tran"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXDISCARD_GB_ADDR, "rx_drop_frames"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXDISCARDBYTE_GB_ADDR, "rx_drop_bytes"),
+};
+
+/* Get GMAC MIBs from registers and accumulate to PPE port GMIB stats array */
+static void ppe_port_gmib_update(struct ppe_port *ppe_port)
+{
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+ const struct ppe_mac_mib_info *mib;
+ int port = ppe_port->port_id;
+ u32 reg, val;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) {
+ mib = &gmib_info[i];
+ reg = PPE_PORT_GMAC_ADDR(port) + mib->offset;
+
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret) {
+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret);
+ continue;
+ }
+
+ ppe_port->gmib_stats[i] += val;
+ if (mib->size == 8) {
+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val);
+ if (ret) {
+ dev_warn(ppe_dev->dev, "%s: %d\n",
+ __func__, ret);
+ continue;
+ }
+
+ ppe_port->gmib_stats[i] += (u64)val << 32;
+ }
+ }
+}
+
+/* Polling task to read GMIB statistics to avoid GMIB 32bit register overflow */
+static void ppe_port_gmib_stats_poll(struct work_struct *work)
+{
+ struct ppe_port *ppe_port = container_of(work, struct ppe_port,
+ gmib_read.work);
+ spin_lock(&ppe_port->gmib_stats_lock);
+ ppe_port_gmib_update(ppe_port);
+ spin_unlock(&ppe_port->gmib_stats_lock);
+
+ schedule_delayed_work(&ppe_port->gmib_read,
+ msecs_to_jiffies(PPE_GMIB_POLL_INTERVAL_MS));
+}
+
+/* Get the XGMAC MIB counter based on the specific MIB stats type */
+static u64 ppe_port_xgmib_get(struct ppe_port *ppe_port,
+ enum ppe_xgmib_stats_type xgmib_type)
+{
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+ const struct ppe_mac_mib_info *mib;
+ int port = ppe_port->port_id;
+ u32 reg, val;
+ u64 data = 0;
+ int ret;
+
+ mib = &xgmib_info[xgmib_type];
+ reg = PPE_PORT_XGMAC_ADDR(port) + mib->offset;
+
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret) {
+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret);
+ goto data_return;
+ }
+
+ data = val;
+ if (mib->size == 8) {
+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val);
+ if (ret) {
+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret);
+ goto data_return;
+ }
+
+ data |= (u64)val << 32;
+ }
+
+data_return:
+ return data;
+}
+
+/**
+ * ppe_port_get_sset_count() - Get PPE port statistics string count
+ * @ppe_port: PPE port
+ * @sset: string set ID
+ *
+ * Description: Get the MAC statistics string count for the PPE port
+ * specified by @ppe_port.
+ *
+ * Return: The count of the statistics string.
+ */
+int ppe_port_get_sset_count(struct ppe_port *ppe_port, int sset)
+{
+ if (sset != ETH_SS_STATS)
+ return 0;
+
+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC)
+ return ARRAY_SIZE(gmib_info);
+ else
+ return ARRAY_SIZE(xgmib_info);
+}
+
+/**
+ * ppe_port_get_strings() - Get PPE port statistics strings
+ * @ppe_port: PPE port
+ * @stringset: string set ID
+ * @data: pointer to statistics strings
+ *
+ * Description: Get the MAC statistics stings for the PPE port
+ * specified by @ppe_port. The strings are stored in the buffer
+ * indicated by @data which used in the ethtool ops.
+ */
+void ppe_port_get_strings(struct ppe_port *ppe_port, u32 stringset, u8 *data)
+{
+ int i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++)
+ strscpy(data + i * ETH_GSTRING_LEN, gmib_info[i].name,
+ ETH_GSTRING_LEN);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++)
+ strscpy(data + i * ETH_GSTRING_LEN, xgmib_info[i].name,
+ ETH_GSTRING_LEN);
+ }
+}
+
+/**
+ * ppe_port_get_ethtool_stats() - Get PPE port ethtool statistics
+ * @ppe_port: PPE port
+ * @data: pointer to statistics data
+ *
+ * Description: Get the MAC statistics for the PPE port specified
+ * by @ppe_port. The statistics are stored in the buffer indicated
+ * by @data which used in the ethtool ops.
+ */
+void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data)
+{
+ int i;
+
+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
+ spin_lock(&ppe_port->gmib_stats_lock);
+
+ ppe_port_gmib_update(ppe_port);
+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++)
+ data[i] = ppe_port->gmib_stats[i];
+
+ spin_unlock(&ppe_port->gmib_stats_lock);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++)
+ data[i] = ppe_port_xgmib_get(ppe_port, i);
+ }
+}
+
+/**
+ * ppe_port_get_stats64() - Get PPE port statistics
+ * @ppe_port: PPE port
+ * @s: statistics pointer
+ *
+ * Description: Get the MAC statistics for the PPE port specified
+ * by @ppe_port.
+ */
+void ppe_port_get_stats64(struct ppe_port *ppe_port,
+ struct rtnl_link_stats64 *s)
+{
+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
+ u64 *src = ppe_port->gmib_stats;
+
+ spin_lock(&ppe_port->gmib_stats_lock);
+
+ ppe_port_gmib_update(ppe_port);
+
+ s->rx_packets = src[gmib_rx_unicast] +
+ src[gmib_rx_broadcast] + src[gmib_rx_multicast];
+
+ s->tx_packets = src[gmib_tx_unicast] +
+ src[gmib_tx_broadcast] + src[gmib_tx_multicast];
+
+ s->rx_bytes = src[gmib_rx_bytes_g];
+ s->tx_bytes = src[gmib_tx_bytes];
+ s->multicast = src[gmib_rx_multicast];
+
+ s->rx_crc_errors = src[gmib_rx_fcserr] + src[gmib_rx_frag];
+ s->rx_frame_errors = src[gmib_rx_alignerr];
+ s->rx_errors = s->rx_crc_errors + s->rx_frame_errors;
+ s->rx_dropped = src[gmib_rx_toolong] + s->rx_errors;
+
+ s->tx_fifo_errors = src[gmib_tx_underrun];
+ s->tx_aborted_errors = src[gmib_tx_abortcol];
+ s->tx_errors = s->tx_fifo_errors + s->tx_aborted_errors;
+ s->collisions = src[gmib_tx_collisions];
+
+ spin_unlock(&ppe_port->gmib_stats_lock);
+ } else {
+ s->multicast = ppe_port_xgmib_get(ppe_port, xgmib_rx_multicast_g);
+
+ s->rx_packets = s->multicast;
+ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_unicast_g);
+ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_broadcast_g);
+
+ s->tx_packets = ppe_port_xgmib_get(ppe_port, xgmib_tx_frames);
+ s->rx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_rx_bytes);
+ s->tx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_tx_bytes);
+
+ s->rx_crc_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_crc_err);
+ s->rx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_fifo_overflow);
+
+ s->rx_length_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_len_err);
+ s->rx_errors = s->rx_crc_errors +
+ s->rx_fifo_errors + s->rx_length_errors;
+ s->rx_dropped = s->rx_errors;
+
+ s->tx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_tx_underflow_err);
+ s->tx_errors = s->tx_packets -
+ ppe_port_xgmib_get(ppe_port, xgmib_tx_frames_g);
+ }
+}
+
/* PPE port and MAC reset */
static int ppe_port_mac_reset(struct ppe_port *ppe_port)
{
@@ -261,6 +693,9 @@ static void ppe_port_mac_link_up(struct phylink_config *config,
int ret, port = ppe_port->port_id;
u32 reg, val;
+ /* Start GMIB statistics polling */
+ schedule_delayed_work(&ppe_port->gmib_read, 0);
+
if (mac_type == PPE_MAC_TYPE_GMAC)
ret = ppe_port_gmac_link_up(ppe_port,
speed, duplex, tx_pause, rx_pause);
@@ -306,6 +741,9 @@ static void ppe_port_mac_link_down(struct phylink_config *config,
int ret, port = ppe_port->port_id;
u32 reg;
+ /* Stop GMIB statistics polling */
+ cancel_delayed_work_sync(&ppe_port->gmib_read);
+
/* Disable PPE port TX */
reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port;
ret = regmap_update_bits(ppe_dev->regmap, reg,
@@ -627,6 +1065,27 @@ static int ppe_port_mac_hw_init(struct ppe_port *ppe_port)
return ret;
}
+/* PPE port MAC MIB work task initialization */
+static int ppe_port_mac_mib_work_init(struct ppe_port *ppe_port)
+{
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+ u64 *gstats;
+
+ gstats = devm_kzalloc(ppe_dev->dev,
+ sizeof(*gstats) * ARRAY_SIZE(gmib_info),
+ GFP_KERNEL);
+ if (!gstats)
+ return -ENOMEM;
+
+ ppe_port->gmib_stats = gstats;
+
+ spin_lock_init(&ppe_port->gmib_stats_lock);
+ INIT_DELAYED_WORK(&ppe_port->gmib_read,
+ ppe_port_gmib_stats_poll);
+
+ return 0;
+}
+
/**
* ppe_port_mac_init() - Initialization of PPE ports for the PPE device
* @ppe_dev: PPE device
@@ -693,6 +1152,12 @@ int ppe_port_mac_init(struct ppe_device *ppe_dev)
goto err_port_node;
}
+ ret = ppe_port_mac_mib_work_init(&ppe_ports->port[i]);
+ if (ret) {
+ dev_err(ppe_dev->dev, "Failed to initialize MAC MIB work\n");
+ goto err_port_node;
+ }
+
i++;
}
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h
index 194f65815011..a524d90e1446 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h
@@ -8,6 +8,8 @@
#include <linux/phylink.h>
+struct rtnl_link_stats64;
+
/**
* enum ppe_port_clk_rst_type - PPE port clock and reset ID type
* @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC
@@ -44,6 +46,9 @@ enum ppe_mac_type {
* @port_id: Port ID
* @clks: Port clocks
* @rstcs: Port resets
+ * @gmib_read: Delay work task for GMAC MIB statistics polling function
+ * @gmib_stats: GMAC MIB statistics array
+ * @gmib_stats_lock: Lock to protect GMAC MIB statistics
*/
struct ppe_port {
struct phylink *phylink;
@@ -56,6 +61,9 @@ struct ppe_port {
int port_id;
struct clk *clks[PPE_PORT_CLK_RST_MAX];
struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX];
+ struct delayed_work gmib_read;
+ u64 *gmib_stats;
+ spinlock_t gmib_stats_lock; /* Protects GMIB stats */
};
/**
@@ -73,4 +81,9 @@ void ppe_port_mac_deinit(struct ppe_device *ppe_dev);
int ppe_port_phylink_setup(struct ppe_port *ppe_port,
struct net_device *netdev);
void ppe_port_phylink_destroy(struct ppe_port *ppe_port);
+int ppe_port_get_sset_count(struct ppe_port *ppe_port, int sset);
+void ppe_port_get_strings(struct ppe_port *ppe_port, u32 stringset, u8 *data);
+void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data);
+void ppe_port_get_stats64(struct ppe_port *ppe_port,
+ struct rtnl_link_stats64 *s);
#endif
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
index 34b659ac0c37..2cd5bd9fa446 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
@@ -606,6 +606,48 @@
#define GMAC_MIB_CTRL_MASK \
(GMAC_MIB_RD_CLR | GMAC_MIB_RST | GMAC_MIB_EN)
+/* GMAC MIB counter registers */
+#define GMAC_RXBROAD_ADDR 0x40
+#define GMAC_RXPAUSE_ADDR 0x44
+#define GMAC_RXMULTI_ADDR 0x48
+#define GMAC_RXFCSERR_ADDR 0x4C
+#define GMAC_RXALIGNERR_ADDR 0x50
+#define GMAC_RXRUNT_ADDR 0x54
+#define GMAC_RXFRAG_ADDR 0x58
+#define GMAC_RXJUMBOFCSERR_ADDR 0x5C
+#define GMAC_RXJUMBOALIGNERR_ADDR 0x60
+#define GMAC_RXPKT64_ADDR 0x64
+#define GMAC_RXPKT65TO127_ADDR 0x68
+#define GMAC_RXPKT128TO255_ADDR 0x6C
+#define GMAC_RXPKT256TO511_ADDR 0x70
+#define GMAC_RXPKT512TO1023_ADDR 0x74
+#define GMAC_RXPKT1024TO1518_ADDR 0x78
+#define GMAC_RXPKT1519TOX_ADDR 0x7C
+#define GMAC_RXTOOLONG_ADDR 0x80
+#define GMAC_RXBYTE_G_ADDR 0x84
+#define GMAC_RXBYTE_B_ADDR 0x8C
+#define GMAC_RXUNI_ADDR 0x94
+#define GMAC_TXBROAD_ADDR 0xA0
+#define GMAC_TXPAUSE_ADDR 0xA4
+#define GMAC_TXMULTI_ADDR 0xA8
+#define GMAC_TXUNDERRUN_ADDR 0xAC
+#define GMAC_TXPKT64_ADDR 0xB0
+#define GMAC_TXPKT65TO127_ADDR 0xB4
+#define GMAC_TXPKT128TO255_ADDR 0xB8
+#define GMAC_TXPKT256TO511_ADDR 0xBC
+#define GMAC_TXPKT512TO1023_ADDR 0xC0
+#define GMAC_TXPKT1024TO1518_ADDR 0xC4
+#define GMAC_TXPKT1519TOX_ADDR 0xC8
+#define GMAC_TXBYTE_ADDR 0xCC
+#define GMAC_TXCOLLISIONS_ADDR 0xD4
+#define GMAC_TXABORTCOL_ADDR 0xD8
+#define GMAC_TXMULTICOL_ADDR 0xDC
+#define GMAC_TXSINGLECOL_ADDR 0xE0
+#define GMAC_TXEXCESSIVEDEFER_ADDR 0xE4
+#define GMAC_TXDEFER_ADDR 0xE8
+#define GMAC_TXLATECOL_ADDR 0xEC
+#define GMAC_TXUNI_ADDR 0xF0
+
/* XGMAC TX configuration register */
#define XGMAC_TX_CONFIG_ADDR 0x0
#define XGMAC_SPEED_M GENMASK(31, 29)
@@ -668,4 +710,53 @@
#define XGMAC_MCF BIT(3)
#define XGMAC_CNTRST BIT(0)
+/* XGMAC MIB counter registers */
+#define XGMAC_TXBYTE_GB_ADDR 0x814
+#define XGMAC_TXPKT_GB_ADDR 0x81C
+#define XGMAC_TXBROAD_G_ADDR 0x824
+#define XGMAC_TXMULTI_G_ADDR 0x82C
+#define XGMAC_TXPKT64_GB_ADDR 0x834
+#define XGMAC_TXPKT65TO127_GB_ADDR 0x83C
+#define XGMAC_TXPKT128TO255_GB_ADDR 0x844
+#define XGMAC_TXPKT256TO511_GB_ADDR 0x84C
+#define XGMAC_TXPKT512TO1023_GB_ADDR 0x854
+#define XGMAC_TXPKT1024TOMAX_GB_ADDR 0x85C
+#define XGMAC_TXUNI_GB_ADDR 0x864
+#define XGMAC_TXMULTI_GB_ADDR 0x86C
+#define XGMAC_TXBROAD_GB_ADDR 0x874
+#define XGMAC_TXUNDERFLOW_ERR_ADDR 0x87C
+#define XGMAC_TXBYTE_G_ADDR 0x884
+#define XGMAC_TXPKT_G_ADDR 0x88C
+#define XGMAC_TXPAUSE_ADDR 0x894
+#define XGMAC_TXVLAN_G_ADDR 0x89C
+#define XGMAC_TXLPI_USEC_ADDR 0x8A4
+#define XGMAC_TXLPI_TRAN_ADDR 0x8A8
+#define XGMAC_RXPKT_GB_ADDR 0x900
+#define XGMAC_RXBYTE_GB_ADDR 0x908
+#define XGMAC_RXBYTE_G_ADDR 0x910
+#define XGMAC_RXBROAD_G_ADDR 0x918
+#define XGMAC_RXMULTI_G_ADDR 0x920
+#define XGMAC_RXCRC_ERR_ADDR 0x928
+#define XGMAC_RXRUNT_ERR_ADDR 0x930
+#define XGMAC_RXJABBER_ERR_ADDR 0x934
+#define XGMAC_RXUNDERSIZE_G_ADDR 0x938
+#define XGMAC_RXOVERSIZE_G_ADDR 0x93C
+#define XGMAC_RXPKT64_GB_ADDR 0x940
+#define XGMAC_RXPKT65TO127_GB_ADDR 0x948
+#define XGMAC_RXPKT128TO255_GB_ADDR 0x950
+#define XGMAC_RXPKT256TO511_GB_ADDR 0x958
+#define XGMAC_RXPKT512TO1023_GB_ADDR 0x960
+#define XGMAC_RXPKT1024TOMAX_GB_ADDR 0x968
+#define XGMAC_RXUNI_G_ADDR 0x970
+#define XGMAC_RXLEN_ERR_ADDR 0x978
+#define XGMAC_RXOUTOFRANGE_ADDR 0x980
+#define XGMAC_RXPAUSE_ADDR 0x988
+#define XGMAC_RXFIFOOVERFLOW_ADDR 0x990
+#define XGMAC_RXVLAN_GB_ADDR 0x998
+#define XGMAC_RXWATCHDOG_ERR_ADDR 0x9A0
+#define XGMAC_RXLPI_USEC_ADDR 0x9A4
+#define XGMAC_RXLPI_TRAN_ADDR 0x9A8
+#define XGMAC_RXDISCARD_GB_ADDR 0x9AC
+#define XGMAC_RXDISCARDBYTE_GB_ADDR 0x9B4
+
#endif
--
2.45.2