EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
manages the traffic in a TDM manner. As a result multiple net_devices can
connect to the same GDM{3,4} port and there is a theoretical "1:n"
relation between GDM ports and net_devices.
┌─────────────────────────────────┐
│ │ ┌──────┐
│ P1 GDM1 ├────►MT7530│
│ │ └──────┘
│ │ ETH0 (DSA conduit)
│ │
│ PSE/FE │
│ │
│ │
│ │ ┌─────┐
│ P0 CDM1 ├────►QDMA0│
│ P4 P9 GDM4 │ └─────┘
└──┬─────────────────────────┬────┘
│ │
┌──▼──┐ ┌────▼────┐
│ PPE │ │ ARB │
└─────┘ └─┬─────┬─┘
│ │
┌──▼──┐┌─▼───┐
│ ETH ││ USB │
└─────┘└─────┘
ETH1 ETH2
This series introduces support for multiple net_devices connected to the
same Frame Engine (FE) GDM port (GDM3 or GDM4) via an external hw
arbiter. Please note GDM1 or GDM2 does not support the connection with
the external arbiter.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://github.com/openwrt/openwrt/pull/23481
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
416 lines
15 KiB
Diff
416 lines
15 KiB
Diff
From 9652322e0b47eacfef497828f6476a2a3169fd13 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <9652322e0b47eacfef497828f6476a2a3169fd13.1779351672.git.lorenzo@kernel.org>
|
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
|
Date: Sat, 17 Jan 2026 14:46:12 +0100
|
|
Subject: [PATCH] net: airoha: Better handle MIB for GDM with multiple port
|
|
attached
|
|
|
|
In the context of a GDM that can have multiple port attached (GDM3/4)
|
|
the HW counter (MIB) are global for the GDM port. This cause duplicated
|
|
stats reported to the kernel for the related interface.
|
|
|
|
The SoC supports a split MIB feature where each counter is tracked based
|
|
on the relevant HW channel (NBQ) to account for this scenario and
|
|
provide a way to select the related counter on accessing the MIB
|
|
registers.
|
|
|
|
Enable this feature for GDM3 and GDM4 and configure the relevant HW
|
|
channel before updating the HW stats to report correct HW counter to the
|
|
kernel for the related interface.
|
|
|
|
Also move the stats struct from port to dev since HW counter are
|
|
now specific to the network interface instead of the GDM port.
|
|
|
|
Co-developed-by: Brown Huang <Brown.huang@airoha.com>
|
|
Signed-off-by: Brown Huang <Brown.huang@airoha.com>
|
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|
---
|
|
drivers/net/ethernet/airoha/airoha_eth.c | 191 +++++++++++++----------
|
|
drivers/net/ethernet/airoha/airoha_eth.h | 7 +-
|
|
2 files changed, 112 insertions(+), 86 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
|
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
|
@@ -611,6 +611,14 @@ static int airoha_fe_init(struct airoha_
|
|
airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX),
|
|
GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK);
|
|
|
|
+ /* Enable split for MIB counters for GDM3 and GDM4 */
|
|
+ airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX),
|
|
+ FE_GDM_TX_MIB_SPLIT_EN_MASK |
|
|
+ FE_GDM_RX_MIB_SPLIT_EN_MASK);
|
|
+ airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM4_IDX),
|
|
+ FE_GDM_TX_MIB_SPLIT_EN_MASK |
|
|
+ FE_GDM_RX_MIB_SPLIT_EN_MASK);
|
|
+
|
|
airoha_fe_crsn_qsel_init(eth);
|
|
|
|
airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK);
|
|
@@ -1758,149 +1766,169 @@ static void airoha_qdma_stop_napi(struct
|
|
}
|
|
}
|
|
|
|
-static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
|
|
+static void airoha_dev_get_hw_stats(struct airoha_gdm_dev *dev)
|
|
{
|
|
struct airoha_gdm_port *port = dev->port;
|
|
struct airoha_eth *eth = dev->eth;
|
|
u32 val, i = 0;
|
|
|
|
- spin_lock(&port->stats.lock);
|
|
- u64_stats_update_begin(&port->stats.syncp);
|
|
+ u64_stats_update_begin(&dev->stats.syncp);
|
|
+
|
|
+ /* Read relevant MIB for GDM with multiple port attached */
|
|
+ if (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)
|
|
+ airoha_fe_rmw(eth, REG_FE_GDM_MIB_CFG(port->id),
|
|
+ FE_TX_MIB_ID_MASK | FE_RX_MIB_ID_MASK,
|
|
+ FIELD_PREP(FE_TX_MIB_ID_MASK, dev->nbq) |
|
|
+ FIELD_PREP(FE_RX_MIB_ID_MASK, dev->nbq));
|
|
|
|
/* TX */
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id));
|
|
- port->stats.tx_ok_pkts += ((u64)val << 32);
|
|
+ dev->stats.tx_ok_pkts += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id));
|
|
- port->stats.tx_ok_pkts += val;
|
|
+ dev->stats.tx_ok_pkts += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id));
|
|
- port->stats.tx_ok_bytes += ((u64)val << 32);
|
|
+ dev->stats.tx_ok_bytes += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id));
|
|
- port->stats.tx_ok_bytes += val;
|
|
+ dev->stats.tx_ok_bytes += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id));
|
|
- port->stats.tx_drops += val;
|
|
+ dev->stats.tx_drops += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id));
|
|
- port->stats.tx_broadcast += val;
|
|
+ dev->stats.tx_broadcast += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id));
|
|
- port->stats.tx_multicast += val;
|
|
+ dev->stats.tx_multicast += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id));
|
|
- port->stats.tx_len[i] += val;
|
|
+ dev->stats.tx_len[i] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id));
|
|
- port->stats.tx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.tx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id));
|
|
- port->stats.tx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.tx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id));
|
|
- port->stats.tx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.tx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id));
|
|
- port->stats.tx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.tx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id));
|
|
- port->stats.tx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.tx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id));
|
|
- port->stats.tx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.tx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id));
|
|
- port->stats.tx_len[i++] += val;
|
|
+ dev->stats.tx_len[i++] += val;
|
|
|
|
/* RX */
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id));
|
|
- port->stats.rx_ok_pkts += ((u64)val << 32);
|
|
+ dev->stats.rx_ok_pkts += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id));
|
|
- port->stats.rx_ok_pkts += val;
|
|
+ dev->stats.rx_ok_pkts += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id));
|
|
- port->stats.rx_ok_bytes += ((u64)val << 32);
|
|
+ dev->stats.rx_ok_bytes += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id));
|
|
- port->stats.rx_ok_bytes += val;
|
|
+ dev->stats.rx_ok_bytes += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id));
|
|
- port->stats.rx_drops += val;
|
|
+ dev->stats.rx_drops += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id));
|
|
- port->stats.rx_broadcast += val;
|
|
+ dev->stats.rx_broadcast += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id));
|
|
- port->stats.rx_multicast += val;
|
|
+ dev->stats.rx_multicast += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id));
|
|
- port->stats.rx_errors += val;
|
|
+ dev->stats.rx_errors += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id));
|
|
- port->stats.rx_crc_error += val;
|
|
+ dev->stats.rx_crc_error += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id));
|
|
- port->stats.rx_over_errors += val;
|
|
+ dev->stats.rx_over_errors += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id));
|
|
- port->stats.rx_fragment += val;
|
|
+ dev->stats.rx_fragment += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id));
|
|
- port->stats.rx_jabber += val;
|
|
+ dev->stats.rx_jabber += val;
|
|
|
|
i = 0;
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id));
|
|
- port->stats.rx_len[i] += val;
|
|
+ dev->stats.rx_len[i] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id));
|
|
- port->stats.rx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.rx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id));
|
|
- port->stats.rx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.rx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id));
|
|
- port->stats.rx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.rx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id));
|
|
- port->stats.rx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.rx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id));
|
|
- port->stats.rx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.rx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id));
|
|
- port->stats.rx_len[i] += ((u64)val << 32);
|
|
+ dev->stats.rx_len[i] += ((u64)val << 32);
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
|
|
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id));
|
|
- port->stats.rx_len[i++] += val;
|
|
+ dev->stats.rx_len[i++] += val;
|
|
+
|
|
+ u64_stats_update_end(&dev->stats.syncp);
|
|
+}
|
|
|
|
- /* reset mib counters */
|
|
- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id),
|
|
+static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
|
|
+{
|
|
+ struct airoha_gdm_port *port = dev->port;
|
|
+ int i;
|
|
+
|
|
+ spin_lock(&port->stats_lock);
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
|
|
+ if (port->devs[i])
|
|
+ airoha_dev_get_hw_stats(port->devs[i]);
|
|
+ }
|
|
+
|
|
+ /* Reset MIB counters */
|
|
+ airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id),
|
|
FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK);
|
|
|
|
- u64_stats_update_end(&port->stats.syncp);
|
|
- spin_unlock(&port->stats.lock);
|
|
+ spin_unlock(&port->stats_lock);
|
|
}
|
|
|
|
void airoha_set_port_mtu(struct airoha_eth *eth, struct airoha_gdm_port *port)
|
|
@@ -2228,23 +2256,22 @@ static void airoha_dev_get_stats64(struc
|
|
struct rtnl_link_stats64 *storage)
|
|
{
|
|
struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
- struct airoha_gdm_port *port = dev->port;
|
|
unsigned int start;
|
|
|
|
airoha_update_hw_stats(dev);
|
|
do {
|
|
- start = u64_stats_fetch_begin(&port->stats.syncp);
|
|
- storage->rx_packets = port->stats.rx_ok_pkts;
|
|
- storage->tx_packets = port->stats.tx_ok_pkts;
|
|
- storage->rx_bytes = port->stats.rx_ok_bytes;
|
|
- storage->tx_bytes = port->stats.tx_ok_bytes;
|
|
- storage->multicast = port->stats.rx_multicast;
|
|
- storage->rx_errors = port->stats.rx_errors;
|
|
- storage->rx_dropped = port->stats.rx_drops;
|
|
- storage->tx_dropped = port->stats.tx_drops;
|
|
- storage->rx_crc_errors = port->stats.rx_crc_error;
|
|
- storage->rx_over_errors = port->stats.rx_over_errors;
|
|
- } while (u64_stats_fetch_retry(&port->stats.syncp, start));
|
|
+ start = u64_stats_fetch_begin(&dev->stats.syncp);
|
|
+ storage->rx_packets = dev->stats.rx_ok_pkts;
|
|
+ storage->tx_packets = dev->stats.tx_ok_pkts;
|
|
+ storage->rx_bytes = dev->stats.rx_ok_bytes;
|
|
+ storage->tx_bytes = dev->stats.tx_ok_bytes;
|
|
+ storage->multicast = dev->stats.rx_multicast;
|
|
+ storage->rx_errors = dev->stats.rx_errors;
|
|
+ storage->rx_dropped = dev->stats.rx_drops;
|
|
+ storage->tx_dropped = dev->stats.tx_drops;
|
|
+ storage->rx_crc_errors = dev->stats.rx_crc_error;
|
|
+ storage->rx_over_errors = dev->stats.rx_over_errors;
|
|
+ } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
|
|
}
|
|
|
|
static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
|
|
@@ -2639,20 +2666,19 @@ static void airoha_ethtool_get_mac_stats
|
|
struct ethtool_eth_mac_stats *stats)
|
|
{
|
|
struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
- struct airoha_gdm_port *port = dev->port;
|
|
unsigned int start;
|
|
|
|
airoha_update_hw_stats(dev);
|
|
do {
|
|
- start = u64_stats_fetch_begin(&port->stats.syncp);
|
|
- stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
|
|
- stats->OctetsTransmittedOK = port->stats.tx_ok_bytes;
|
|
- stats->MulticastFramesXmittedOK = port->stats.tx_multicast;
|
|
- stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast;
|
|
- stats->FramesReceivedOK = port->stats.rx_ok_pkts;
|
|
- stats->OctetsReceivedOK = port->stats.rx_ok_bytes;
|
|
- stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast;
|
|
- } while (u64_stats_fetch_retry(&port->stats.syncp, start));
|
|
+ start = u64_stats_fetch_begin(&dev->stats.syncp);
|
|
+ stats->FramesTransmittedOK = dev->stats.tx_ok_pkts;
|
|
+ stats->OctetsTransmittedOK = dev->stats.tx_ok_bytes;
|
|
+ stats->MulticastFramesXmittedOK = dev->stats.tx_multicast;
|
|
+ stats->BroadcastFramesXmittedOK = dev->stats.tx_broadcast;
|
|
+ stats->FramesReceivedOK = dev->stats.rx_ok_pkts;
|
|
+ stats->OctetsReceivedOK = dev->stats.rx_ok_bytes;
|
|
+ stats->BroadcastFramesReceivedOK = dev->stats.rx_broadcast;
|
|
+ } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
|
|
}
|
|
|
|
static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = {
|
|
@@ -2672,8 +2698,7 @@ airoha_ethtool_get_rmon_stats(struct net
|
|
const struct ethtool_rmon_hist_range **ranges)
|
|
{
|
|
struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
- struct airoha_gdm_port *port = dev->port;
|
|
- struct airoha_hw_stats *hw_stats = &port->stats;
|
|
+ struct airoha_hw_stats *hw_stats = &dev->stats;
|
|
unsigned int start;
|
|
|
|
BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) !=
|
|
@@ -2686,7 +2711,7 @@ airoha_ethtool_get_rmon_stats(struct net
|
|
do {
|
|
int i;
|
|
|
|
- start = u64_stats_fetch_begin(&port->stats.syncp);
|
|
+ start = u64_stats_fetch_begin(&dev->stats.syncp);
|
|
stats->fragments = hw_stats->rx_fragment;
|
|
stats->jabbers = hw_stats->rx_jabber;
|
|
for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1;
|
|
@@ -2694,7 +2719,7 @@ airoha_ethtool_get_rmon_stats(struct net
|
|
stats->hist[i] = hw_stats->rx_len[i];
|
|
stats->hist_tx[i] = hw_stats->tx_len[i];
|
|
}
|
|
- } while (u64_stats_fetch_retry(&port->stats.syncp, start));
|
|
+ } while (u64_stats_fetch_retry(&dev->stats.syncp, start));
|
|
}
|
|
|
|
static int airoha_ethtool_set_priv_flags(struct net_device *netdev, u32 flags)
|
|
@@ -3702,6 +3727,7 @@ static int airoha_alloc_gdm_device(struc
|
|
|
|
netdev->dev.of_node = of_node_get(np);
|
|
dev = netdev_priv(netdev);
|
|
+ u64_stats_init(&dev->stats.syncp);
|
|
dev->dev = netdev;
|
|
dev->port = port;
|
|
dev->eth = eth;
|
|
@@ -3750,9 +3776,8 @@ static int airoha_alloc_gdm_port(struct
|
|
if (!port)
|
|
return -ENOMEM;
|
|
|
|
- u64_stats_init(&port->stats.syncp);
|
|
- spin_lock_init(&port->stats.lock);
|
|
port->id = id;
|
|
+ spin_lock_init(&port->stats_lock);
|
|
eth->ports[p] = port;
|
|
|
|
err = airoha_metadata_dst_alloc(port);
|
|
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
|
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
|
@@ -226,8 +226,6 @@ struct airoha_tx_irq_queue {
|
|
};
|
|
|
|
struct airoha_hw_stats {
|
|
- /* protect concurrent hw_stats accesses */
|
|
- spinlock_t lock;
|
|
struct u64_stats_sync syncp;
|
|
|
|
/* get_stats64 */
|
|
@@ -571,6 +569,8 @@ struct airoha_gdm_dev {
|
|
|
|
u32 flags;
|
|
int nbq;
|
|
+
|
|
+ struct airoha_hw_stats stats;
|
|
};
|
|
|
|
struct airoha_gdm_port {
|
|
@@ -578,7 +578,8 @@ struct airoha_gdm_port {
|
|
int id;
|
|
int users;
|
|
|
|
- struct airoha_hw_stats stats;
|
|
+ /* protect concurrent hw_stats accesses */
|
|
+ spinlock_t stats_lock;
|
|
|
|
struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS];
|
|
};
|