On 20/08/2024 12:16, MD Danish Anwar wrote: > Add support for dumping PA stats registers via ethtool. > Firmware maintained stats are stored at PA Stats registers. > Also modify emac_get_strings() API to use ethtool_puts(). > > This commit also renames the array icssg_all_stats to icssg_mii_g_rt_stats > and creates a new array named icssg_all_pa_stats for PA Stats. > > Signed-off-by: MD Danish Anwar <danishanwar@xxxxxx> > --- > drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 19 ++++++----- > drivers/net/ethernet/ti/icssg/icssg_prueth.c | 6 ++++ > drivers/net/ethernet/ti/icssg/icssg_prueth.h | 9 +++-- > drivers/net/ethernet/ti/icssg/icssg_stats.c | 31 ++++++++++++----- > drivers/net/ethernet/ti/icssg/icssg_stats.h | 34 ++++++++++++++++++- > 5 files changed, 78 insertions(+), 21 deletions(-) > > diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c > index 5688f054cec5..25832dcbada2 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c > +++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c > @@ -83,13 +83,11 @@ static void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data) > > switch (stringset) { > case ETH_SS_STATS: > - for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { > - if (!icssg_all_stats[i].standard_stats) { > - memcpy(p, icssg_all_stats[i].name, > - ETH_GSTRING_LEN); > - p += ETH_GSTRING_LEN; > - } > - } > + for (i = 0; i < ARRAY_SIZE(icssg_mii_g_rt_stats); i++) > + if (!icssg_mii_g_rt_stats[i].standard_stats) > + ethtool_puts(&p, icssg_mii_g_rt_stats[i].name); > + for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) > + ethtool_puts(&p, icssg_all_pa_stats[i].name); > break; > default: > break; > @@ -104,9 +102,12 @@ static void emac_get_ethtool_stats(struct net_device *ndev, > > emac_update_hardware_stats(emac); > > - for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) > - if (!icssg_all_stats[i].standard_stats) > + for (i = 0; i < ARRAY_SIZE(icssg_mii_g_rt_stats); i++) > + if (!icssg_mii_g_rt_stats[i].standard_stats) > *(data++) = emac->stats[i]; > + > + for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) > + *(data++) = emac->pa_stats[i]; > } > > static int emac_get_ts_info(struct net_device *ndev, > diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c > index 53a3e44b99a2..f623a0f603fc 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c > +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c > @@ -1182,6 +1182,12 @@ static int prueth_probe(struct platform_device *pdev) > return -ENODEV; > } > > + prueth->pa_stats = syscon_regmap_lookup_by_phandle(np, "ti,pa-stats"); > + if (IS_ERR(prueth->pa_stats)) { > + dev_err(dev, "couldn't get ti,pa-stats syscon regmap\n"); > + return -ENODEV; > + } > + > if (eth0_node) { > ret = prueth_get_cores(prueth, ICSS_SLICE0, false); > if (ret) > diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h > index f678d656a3ed..996f6f8a194c 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h > +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h > @@ -50,8 +50,10 @@ > > #define ICSSG_MAX_RFLOWS 8 /* per slice */ > > +#define ICSSG_NUM_PA_STATS 4 > +#define ICSSG_NUM_MII_G_RT_STATS 60 > /* Number of ICSSG related stats */ > -#define ICSSG_NUM_STATS 60 > +#define ICSSG_NUM_STATS (ICSSG_NUM_MII_G_RT_STATS + ICSSG_NUM_PA_STATS) > #define ICSSG_NUM_STANDARD_STATS 31 > #define ICSSG_NUM_ETHTOOL_STATS (ICSSG_NUM_STATS - ICSSG_NUM_STANDARD_STATS) > > @@ -190,7 +192,8 @@ struct prueth_emac { > int port_vlan; > > struct delayed_work stats_work; > - u64 stats[ICSSG_NUM_STATS]; > + u64 stats[ICSSG_NUM_MII_G_RT_STATS]; > + u64 pa_stats[ICSSG_NUM_PA_STATS]; > > /* RX IRQ Coalescing Related */ > struct hrtimer rx_hrtimer; > @@ -230,6 +233,7 @@ struct icssg_firmwares { > * @registered_netdevs: list of registered netdevs > * @miig_rt: regmap to mii_g_rt block > * @mii_rt: regmap to mii_rt block > + * @pa_stats: regmap to pa_stats block > * @pru_id: ID for each of the PRUs > * @pdev: pointer to ICSSG platform device > * @pdata: pointer to platform data for ICSSG driver > @@ -263,6 +267,7 @@ struct prueth { > struct net_device *registered_netdevs[PRUETH_NUM_MACS]; > struct regmap *miig_rt; > struct regmap *mii_rt; > + struct regmap *pa_stats; > > enum pruss_pru_id pru_id[PRUSS_NUM_PRUS]; > struct platform_device *pdev; > diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c > index 2fb150c13078..857bb956e935 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_stats.c > +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c > @@ -11,6 +11,7 @@ > > #define ICSSG_TX_PACKET_OFFSET 0xA0 > #define ICSSG_TX_BYTE_OFFSET 0xEC > +#define ICSSG_FW_STATS_BASE 0x0248 > > static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */ > 0xb18, /* Slice 1 stats start */ > @@ -22,24 +23,31 @@ void emac_update_hardware_stats(struct prueth_emac *emac) > int slice = prueth_emac_slice(emac); > u32 base = stats_base[slice]; > u32 tx_pkt_cnt = 0; > - u32 val; > + u32 val, reg; > int i; > > - for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { > + for (i = 0; i < ARRAY_SIZE(icssg_mii_g_rt_stats); i++) { > regmap_read(prueth->miig_rt, > - base + icssg_all_stats[i].offset, > + base + icssg_mii_g_rt_stats[i].offset, > &val); > regmap_write(prueth->miig_rt, > - base + icssg_all_stats[i].offset, > + base + icssg_mii_g_rt_stats[i].offset, > val); > > - if (icssg_all_stats[i].offset == ICSSG_TX_PACKET_OFFSET) > + if (icssg_mii_g_rt_stats[i].offset == ICSSG_TX_PACKET_OFFSET) > tx_pkt_cnt = val; > > emac->stats[i] += val; > - if (icssg_all_stats[i].offset == ICSSG_TX_BYTE_OFFSET) > + if (icssg_mii_g_rt_stats[i].offset == ICSSG_TX_BYTE_OFFSET) > emac->stats[i] -= tx_pkt_cnt * 8; > } > + > + for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) { > + reg = ICSSG_FW_STATS_BASE + icssg_all_pa_stats[i].offset * > + PRUETH_NUM_MACS + slice * sizeof(u32); > + regmap_read(prueth->pa_stats, reg, &val); > + emac->pa_stats[i] += val; > + } > } > > void icssg_stats_work_handler(struct work_struct *work) > @@ -57,9 +65,14 @@ int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name) > { > int i; > > - for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { > - if (!strcmp(icssg_all_stats[i].name, stat_name)) > - return emac->stats[icssg_all_stats[i].offset / sizeof(u32)]; > + for (i = 0; i < ARRAY_SIZE(icssg_mii_g_rt_stats); i++) { > + if (!strcmp(icssg_mii_g_rt_stats[i].name, stat_name)) > + return emac->stats[icssg_mii_g_rt_stats[i].offset / sizeof(u32)]; > + } > + > + for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++) { > + if (!strcmp(icssg_all_pa_stats[i].name, stat_name)) > + return emac->pa_stats[icssg_all_pa_stats[i].offset / sizeof(u32)]; > } > > netdev_err(emac->ndev, "Invalid stats %s\n", stat_name); > diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/net/ethernet/ti/icssg/icssg_stats.h > index 999a4a91276c..2a1edbc55214 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_stats.h > +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h > @@ -77,6 +77,20 @@ struct miig_stats_regs { > u32 tx_bytes; > }; > > +/** > + * struct pa_stats_regs - ICSSG Firmware maintained PA Stats register > + * @fw_rx_cnt: Number of valid packets sent by Rx PRU to Host on PSI > + * @fw_tx_cnt: Number of valid packets copied by RTU0 to Tx queues > + * @fw_tx_pre_overflow: Host Egress Q (Pre-emptible) Overflow Counter > + * @fw_tx_exp_overflow: Host Egress Q (Express) Overflow Counter > + */ > +struct pa_stats_regs { > + u32 fw_rx_cnt; > + u32 fw_tx_cnt; > + u32 fw_tx_pre_overflow; > + u32 fw_tx_exp_overflow; > +}; > + > #define ICSSG_STATS(field, stats_type) \ > { \ > #field, \ > @@ -84,13 +98,24 @@ struct miig_stats_regs { > stats_type \ > } > > +#define ICSSG_PA_STATS(field) \ > +{ \ > + #field, \ > + offsetof(struct pa_stats_regs, field), \ > +} > + > struct icssg_stats { icssg_mii_stats? > char name[ETH_GSTRING_LEN]; > u32 offset; > bool standard_stats; > }; > > -static const struct icssg_stats icssg_all_stats[] = { > +struct icssg_pa_stats { > + char name[ETH_GSTRING_LEN]; > + u32 offset; > +}; > + > +static const struct icssg_stats icssg_mii_g_rt_stats[] = { icssg_all_mii_stats? to be consistend with the newly added icssg_pa_stats and icssg_all_pa_stats. Could you please group all mii_stats data strucutres and arrays together followed by pa_stats data structures and arrays? > /* Rx */ > ICSSG_STATS(rx_packets, true), > ICSSG_STATS(rx_broadcast_frames, false), > @@ -155,4 +180,11 @@ static const struct icssg_stats icssg_all_stats[] = { > ICSSG_STATS(tx_bytes, true),t > }; > > +static const struct icssg_pa_stats icssg_all_pa_stats[] = > + ICSSG_PA_STATS(fw_rx_cnt), > + ICSSG_PA_STATS(fw_tx_cnt), > + ICSSG_PA_STATS(fw_tx_pre_overflow), > + ICSSG_PA_STATS(fw_tx_exp_overflow), > +}; > + > #endif /* __NET_TI_ICSSG_STATS_H */ -- cheers, -roger