diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c index d18a7e5383d..4aeefb2f8c0 100644 --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c @@ -2071,7 +2071,8 @@ static void qca_ppe_get_strings(struct dsa_switch *ds, int port, if (stringset != ETH_SS_STATS) return; - for (i = 0; i < ARRAY_SIZE(qca_ppe_mib); i++) + /* The CPU port has no MAC; only its queues count. */ + for (i = 0; port && i < ARRAY_SIZE(qca_ppe_mib); i++) ethtool_puts(&data, qca_ppe_mib[i].name); ppe_port_qstats(ds_to_priv(ds), port, &data, NULL); @@ -2083,7 +2084,7 @@ static int qca_ppe_get_sset_count(struct dsa_switch *ds, int port, if (sset != ETH_SS_STATS) return 0; - return ARRAY_SIZE(qca_ppe_mib) + + return (port ? ARRAY_SIZE(qca_ppe_mib) : 0) + ppe_port_qstats(ds_to_priv(ds), port, NULL, NULL); } @@ -2091,25 +2092,22 @@ static void qca_ppe_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) { struct qca_ppe_priv *priv = ds_to_priv(ds); + int off = port ? ARRAY_SIZE(qca_ppe_mib) : 0; struct qca_ppe_mib_stats *stats, *qstats; int i, n; - if (port < 1) { - memset(data, 0, sizeof(u64) * ARRAY_SIZE(qca_ppe_mib)); - return; - } - - stats = ppe_port_mib(priv, port); qstats = priv->port_qstats + port * PPE_QSTATS_MAX; spin_lock_bh(&priv->mib_lock); - ppe_mib_fold(priv, port); + if (port) { + stats = ppe_port_mib(priv, port); + ppe_mib_fold(priv, port); + for (i = 0; i < ARRAY_SIZE(qca_ppe_mib); i++) + data[i] = stats[i].total; + } n = ppe_port_qstats(priv, port, NULL, qstats); - - for (i = 0; i < ARRAY_SIZE(qca_ppe_mib); i++) - data[i] = stats[i].total; for (i = 0; i < n; i++) - data[ARRAY_SIZE(qca_ppe_mib) + i] = qstats[i].total; + data[off + i] = qstats[i].total; spin_unlock_bh(&priv->mib_lock); } diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_scheduler.c b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_scheduler.c index 59941c3ef0d..a8a78aa304d 100644 --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_scheduler.c +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_scheduler.c @@ -1303,17 +1303,22 @@ u32 ppe_port_queue_drops(struct qca_ppe_priv *priv, int port) return tx; } -/* A user port's queue-side counters for ethtool -S: what each of its queues - * sent and dropped by colour, what the buffer manager turned away on ingress, - * and the colours its meter painted. With @names it lists them, with @st it - * folds them; it returns how many there are either way. +/* A port's queue-side counters for ethtool -S: what each of its queues sent + * and dropped by colour and, for a user port, what the buffer manager turned + * away on ingress and the colours its meter painted. With @names it lists + * them, with @st it folds them; it returns how many there are either way. */ int ppe_port_qstats(struct qca_ppe_priv *priv, int port, u8 **names, struct qca_ppe_mib_stats *st) { + static const struct port_l0_params cpu = { + .ucast_count = PPE_CPU_UCAST_QUEUES, + .mcast_base = 256, + .mcast_count = PPE_MUL_QUEUES_PORT, + }; static const char * const colour[] = { "green", "yellow", "red" }; struct ppe_qstats q = { .priv = priv, .names = names, .st = st }; - const struct port_l0_params *p = NULL; + const struct port_l0_params *p = port ? NULL : &cpu; int bm = PPE_BM_PHY_START + port - 1; int i, c; @@ -1351,6 +1356,9 @@ int ppe_port_qstats(struct qca_ppe_priv *priv, int port, u8 **names, "tx_mcast_queue_%d_drop_%s", i, colour[c]); } + if (!port) + return q.n; + if (bm <= priv->data->bm_phy_end) { ppe_qstat(&q, PPE_BM_DROP_STAT(bm), false, "rx_bm_drop"); ppe_qstat(&q, PPE_BM_DROP_STAT(bm + PPE_BM_PORTS), false,