mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
net: ti: icssg-prueth: Add support for PA Stats
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 maintains consistency between miig_stats and pa_stats by - renaming the array icssg_all_stats to icssg_all_miig_stats - renaming the structure icssg_stats to icssg_miig_stats - renaming ICSSG_STATS() to ICSSG_MIIG_STATS() - changing order of stats related data structures and arrays so that data structures of a certain stats type is clubbed together. Signed-off-by: MD Danish Anwar <danishanwar@ti.com> Link: https://patch.msgid.link/20240822122652.1071801-3-danishanwar@ti.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
be91edc81b
commit
550ee90ac6
5 changed files with 140 additions and 83 deletions
|
@ -83,13 +83,11 @@ static void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
|
||||||
|
|
||||||
switch (stringset) {
|
switch (stringset) {
|
||||||
case ETH_SS_STATS:
|
case ETH_SS_STATS:
|
||||||
for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) {
|
for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++)
|
||||||
if (!icssg_all_stats[i].standard_stats) {
|
if (!icssg_all_miig_stats[i].standard_stats)
|
||||||
memcpy(p, icssg_all_stats[i].name,
|
ethtool_puts(&p, icssg_all_miig_stats[i].name);
|
||||||
ETH_GSTRING_LEN);
|
for (i = 0; i < ARRAY_SIZE(icssg_all_pa_stats); i++)
|
||||||
p += ETH_GSTRING_LEN;
|
ethtool_puts(&p, icssg_all_pa_stats[i].name);
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -104,9 +102,12 @@ static void emac_get_ethtool_stats(struct net_device *ndev,
|
||||||
|
|
||||||
emac_update_hardware_stats(emac);
|
emac_update_hardware_stats(emac);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++)
|
for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++)
|
||||||
if (!icssg_all_stats[i].standard_stats)
|
if (!icssg_all_miig_stats[i].standard_stats)
|
||||||
*(data++) = emac->stats[i];
|
*(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,
|
static int emac_get_ts_info(struct net_device *ndev,
|
||||||
|
|
|
@ -1182,6 +1182,12 @@ static int prueth_probe(struct platform_device *pdev)
|
||||||
return -ENODEV;
|
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) {
|
if (eth0_node) {
|
||||||
ret = prueth_get_cores(prueth, ICSS_SLICE0, false);
|
ret = prueth_get_cores(prueth, ICSS_SLICE0, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -50,8 +50,10 @@
|
||||||
|
|
||||||
#define ICSSG_MAX_RFLOWS 8 /* per slice */
|
#define ICSSG_MAX_RFLOWS 8 /* per slice */
|
||||||
|
|
||||||
|
#define ICSSG_NUM_PA_STATS 4
|
||||||
|
#define ICSSG_NUM_MIIG_STATS 60
|
||||||
/* Number of ICSSG related stats */
|
/* Number of ICSSG related stats */
|
||||||
#define ICSSG_NUM_STATS 60
|
#define ICSSG_NUM_STATS (ICSSG_NUM_MIIG_STATS + ICSSG_NUM_PA_STATS)
|
||||||
#define ICSSG_NUM_STANDARD_STATS 31
|
#define ICSSG_NUM_STANDARD_STATS 31
|
||||||
#define ICSSG_NUM_ETHTOOL_STATS (ICSSG_NUM_STATS - ICSSG_NUM_STANDARD_STATS)
|
#define ICSSG_NUM_ETHTOOL_STATS (ICSSG_NUM_STATS - ICSSG_NUM_STANDARD_STATS)
|
||||||
|
|
||||||
|
@ -190,7 +192,8 @@ struct prueth_emac {
|
||||||
int port_vlan;
|
int port_vlan;
|
||||||
|
|
||||||
struct delayed_work stats_work;
|
struct delayed_work stats_work;
|
||||||
u64 stats[ICSSG_NUM_STATS];
|
u64 stats[ICSSG_NUM_MIIG_STATS];
|
||||||
|
u64 pa_stats[ICSSG_NUM_PA_STATS];
|
||||||
|
|
||||||
/* RX IRQ Coalescing Related */
|
/* RX IRQ Coalescing Related */
|
||||||
struct hrtimer rx_hrtimer;
|
struct hrtimer rx_hrtimer;
|
||||||
|
@ -230,6 +233,7 @@ struct icssg_firmwares {
|
||||||
* @registered_netdevs: list of registered netdevs
|
* @registered_netdevs: list of registered netdevs
|
||||||
* @miig_rt: regmap to mii_g_rt block
|
* @miig_rt: regmap to mii_g_rt block
|
||||||
* @mii_rt: regmap to mii_rt block
|
* @mii_rt: regmap to mii_rt block
|
||||||
|
* @pa_stats: regmap to pa_stats block
|
||||||
* @pru_id: ID for each of the PRUs
|
* @pru_id: ID for each of the PRUs
|
||||||
* @pdev: pointer to ICSSG platform device
|
* @pdev: pointer to ICSSG platform device
|
||||||
* @pdata: pointer to platform data for ICSSG driver
|
* @pdata: pointer to platform data for ICSSG driver
|
||||||
|
@ -263,6 +267,7 @@ struct prueth {
|
||||||
struct net_device *registered_netdevs[PRUETH_NUM_MACS];
|
struct net_device *registered_netdevs[PRUETH_NUM_MACS];
|
||||||
struct regmap *miig_rt;
|
struct regmap *miig_rt;
|
||||||
struct regmap *mii_rt;
|
struct regmap *mii_rt;
|
||||||
|
struct regmap *pa_stats;
|
||||||
|
|
||||||
enum pruss_pru_id pru_id[PRUSS_NUM_PRUS];
|
enum pruss_pru_id pru_id[PRUSS_NUM_PRUS];
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#define ICSSG_TX_PACKET_OFFSET 0xA0
|
#define ICSSG_TX_PACKET_OFFSET 0xA0
|
||||||
#define ICSSG_TX_BYTE_OFFSET 0xEC
|
#define ICSSG_TX_BYTE_OFFSET 0xEC
|
||||||
|
#define ICSSG_FW_STATS_BASE 0x0248
|
||||||
|
|
||||||
static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */
|
static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */
|
||||||
0xb18, /* Slice 1 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);
|
int slice = prueth_emac_slice(emac);
|
||||||
u32 base = stats_base[slice];
|
u32 base = stats_base[slice];
|
||||||
u32 tx_pkt_cnt = 0;
|
u32 tx_pkt_cnt = 0;
|
||||||
u32 val;
|
u32 val, reg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) {
|
for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++) {
|
||||||
regmap_read(prueth->miig_rt,
|
regmap_read(prueth->miig_rt,
|
||||||
base + icssg_all_stats[i].offset,
|
base + icssg_all_miig_stats[i].offset,
|
||||||
&val);
|
&val);
|
||||||
regmap_write(prueth->miig_rt,
|
regmap_write(prueth->miig_rt,
|
||||||
base + icssg_all_stats[i].offset,
|
base + icssg_all_miig_stats[i].offset,
|
||||||
val);
|
val);
|
||||||
|
|
||||||
if (icssg_all_stats[i].offset == ICSSG_TX_PACKET_OFFSET)
|
if (icssg_all_miig_stats[i].offset == ICSSG_TX_PACKET_OFFSET)
|
||||||
tx_pkt_cnt = val;
|
tx_pkt_cnt = val;
|
||||||
|
|
||||||
emac->stats[i] += val;
|
emac->stats[i] += val;
|
||||||
if (icssg_all_stats[i].offset == ICSSG_TX_BYTE_OFFSET)
|
if (icssg_all_miig_stats[i].offset == ICSSG_TX_BYTE_OFFSET)
|
||||||
emac->stats[i] -= tx_pkt_cnt * 8;
|
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)
|
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;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) {
|
for (i = 0; i < ARRAY_SIZE(icssg_all_miig_stats); i++) {
|
||||||
if (!strcmp(icssg_all_stats[i].name, stat_name))
|
if (!strcmp(icssg_all_miig_stats[i].name, stat_name))
|
||||||
return emac->stats[icssg_all_stats[i].offset / sizeof(u32)];
|
return emac->stats[icssg_all_miig_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);
|
netdev_err(emac->ndev, "Invalid stats %s\n", stat_name);
|
||||||
|
|
|
@ -77,82 +77,114 @@ struct miig_stats_regs {
|
||||||
u32 tx_bytes;
|
u32 tx_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ICSSG_STATS(field, stats_type) \
|
#define ICSSG_MIIG_STATS(field, stats_type) \
|
||||||
{ \
|
{ \
|
||||||
#field, \
|
#field, \
|
||||||
offsetof(struct miig_stats_regs, field), \
|
offsetof(struct miig_stats_regs, field), \
|
||||||
stats_type \
|
stats_type \
|
||||||
}
|
}
|
||||||
|
|
||||||
struct icssg_stats {
|
struct icssg_miig_stats {
|
||||||
char name[ETH_GSTRING_LEN];
|
char name[ETH_GSTRING_LEN];
|
||||||
u32 offset;
|
u32 offset;
|
||||||
bool standard_stats;
|
bool standard_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct icssg_stats icssg_all_stats[] = {
|
static const struct icssg_miig_stats icssg_all_miig_stats[] = {
|
||||||
/* Rx */
|
/* Rx */
|
||||||
ICSSG_STATS(rx_packets, true),
|
ICSSG_MIIG_STATS(rx_packets, true),
|
||||||
ICSSG_STATS(rx_broadcast_frames, false),
|
ICSSG_MIIG_STATS(rx_broadcast_frames, false),
|
||||||
ICSSG_STATS(rx_multicast_frames, true),
|
ICSSG_MIIG_STATS(rx_multicast_frames, true),
|
||||||
ICSSG_STATS(rx_crc_errors, true),
|
ICSSG_MIIG_STATS(rx_crc_errors, true),
|
||||||
ICSSG_STATS(rx_mii_error_frames, false),
|
ICSSG_MIIG_STATS(rx_mii_error_frames, false),
|
||||||
ICSSG_STATS(rx_odd_nibble_frames, false),
|
ICSSG_MIIG_STATS(rx_odd_nibble_frames, false),
|
||||||
ICSSG_STATS(rx_frame_max_size, true),
|
ICSSG_MIIG_STATS(rx_frame_max_size, true),
|
||||||
ICSSG_STATS(rx_max_size_error_frames, false),
|
ICSSG_MIIG_STATS(rx_max_size_error_frames, false),
|
||||||
ICSSG_STATS(rx_frame_min_size, true),
|
ICSSG_MIIG_STATS(rx_frame_min_size, true),
|
||||||
ICSSG_STATS(rx_min_size_error_frames, false),
|
ICSSG_MIIG_STATS(rx_min_size_error_frames, false),
|
||||||
ICSSG_STATS(rx_over_errors, true),
|
ICSSG_MIIG_STATS(rx_over_errors, true),
|
||||||
ICSSG_STATS(rx_class0_hits, false),
|
ICSSG_MIIG_STATS(rx_class0_hits, false),
|
||||||
ICSSG_STATS(rx_class1_hits, false),
|
ICSSG_MIIG_STATS(rx_class1_hits, false),
|
||||||
ICSSG_STATS(rx_class2_hits, false),
|
ICSSG_MIIG_STATS(rx_class2_hits, false),
|
||||||
ICSSG_STATS(rx_class3_hits, false),
|
ICSSG_MIIG_STATS(rx_class3_hits, false),
|
||||||
ICSSG_STATS(rx_class4_hits, false),
|
ICSSG_MIIG_STATS(rx_class4_hits, false),
|
||||||
ICSSG_STATS(rx_class5_hits, false),
|
ICSSG_MIIG_STATS(rx_class5_hits, false),
|
||||||
ICSSG_STATS(rx_class6_hits, false),
|
ICSSG_MIIG_STATS(rx_class6_hits, false),
|
||||||
ICSSG_STATS(rx_class7_hits, false),
|
ICSSG_MIIG_STATS(rx_class7_hits, false),
|
||||||
ICSSG_STATS(rx_class8_hits, false),
|
ICSSG_MIIG_STATS(rx_class8_hits, false),
|
||||||
ICSSG_STATS(rx_class9_hits, false),
|
ICSSG_MIIG_STATS(rx_class9_hits, false),
|
||||||
ICSSG_STATS(rx_class10_hits, false),
|
ICSSG_MIIG_STATS(rx_class10_hits, false),
|
||||||
ICSSG_STATS(rx_class11_hits, false),
|
ICSSG_MIIG_STATS(rx_class11_hits, false),
|
||||||
ICSSG_STATS(rx_class12_hits, false),
|
ICSSG_MIIG_STATS(rx_class12_hits, false),
|
||||||
ICSSG_STATS(rx_class13_hits, false),
|
ICSSG_MIIG_STATS(rx_class13_hits, false),
|
||||||
ICSSG_STATS(rx_class14_hits, false),
|
ICSSG_MIIG_STATS(rx_class14_hits, false),
|
||||||
ICSSG_STATS(rx_class15_hits, false),
|
ICSSG_MIIG_STATS(rx_class15_hits, false),
|
||||||
ICSSG_STATS(rx_smd_frags, false),
|
ICSSG_MIIG_STATS(rx_smd_frags, false),
|
||||||
ICSSG_STATS(rx_bucket1_size, true),
|
ICSSG_MIIG_STATS(rx_bucket1_size, true),
|
||||||
ICSSG_STATS(rx_bucket2_size, true),
|
ICSSG_MIIG_STATS(rx_bucket2_size, true),
|
||||||
ICSSG_STATS(rx_bucket3_size, true),
|
ICSSG_MIIG_STATS(rx_bucket3_size, true),
|
||||||
ICSSG_STATS(rx_bucket4_size, true),
|
ICSSG_MIIG_STATS(rx_bucket4_size, true),
|
||||||
ICSSG_STATS(rx_64B_frames, true),
|
ICSSG_MIIG_STATS(rx_64B_frames, true),
|
||||||
ICSSG_STATS(rx_bucket1_frames, true),
|
ICSSG_MIIG_STATS(rx_bucket1_frames, true),
|
||||||
ICSSG_STATS(rx_bucket2_frames, true),
|
ICSSG_MIIG_STATS(rx_bucket2_frames, true),
|
||||||
ICSSG_STATS(rx_bucket3_frames, true),
|
ICSSG_MIIG_STATS(rx_bucket3_frames, true),
|
||||||
ICSSG_STATS(rx_bucket4_frames, true),
|
ICSSG_MIIG_STATS(rx_bucket4_frames, true),
|
||||||
ICSSG_STATS(rx_bucket5_frames, true),
|
ICSSG_MIIG_STATS(rx_bucket5_frames, true),
|
||||||
ICSSG_STATS(rx_bytes, true),
|
ICSSG_MIIG_STATS(rx_bytes, true),
|
||||||
ICSSG_STATS(rx_tx_total_bytes, false),
|
ICSSG_MIIG_STATS(rx_tx_total_bytes, false),
|
||||||
/* Tx */
|
/* Tx */
|
||||||
ICSSG_STATS(tx_packets, true),
|
ICSSG_MIIG_STATS(tx_packets, true),
|
||||||
ICSSG_STATS(tx_broadcast_frames, false),
|
ICSSG_MIIG_STATS(tx_broadcast_frames, false),
|
||||||
ICSSG_STATS(tx_multicast_frames, false),
|
ICSSG_MIIG_STATS(tx_multicast_frames, false),
|
||||||
ICSSG_STATS(tx_odd_nibble_frames, false),
|
ICSSG_MIIG_STATS(tx_odd_nibble_frames, false),
|
||||||
ICSSG_STATS(tx_underflow_errors, false),
|
ICSSG_MIIG_STATS(tx_underflow_errors, false),
|
||||||
ICSSG_STATS(tx_frame_max_size, true),
|
ICSSG_MIIG_STATS(tx_frame_max_size, true),
|
||||||
ICSSG_STATS(tx_max_size_error_frames, false),
|
ICSSG_MIIG_STATS(tx_max_size_error_frames, false),
|
||||||
ICSSG_STATS(tx_frame_min_size, true),
|
ICSSG_MIIG_STATS(tx_frame_min_size, true),
|
||||||
ICSSG_STATS(tx_min_size_error_frames, false),
|
ICSSG_MIIG_STATS(tx_min_size_error_frames, false),
|
||||||
ICSSG_STATS(tx_bucket1_size, true),
|
ICSSG_MIIG_STATS(tx_bucket1_size, true),
|
||||||
ICSSG_STATS(tx_bucket2_size, true),
|
ICSSG_MIIG_STATS(tx_bucket2_size, true),
|
||||||
ICSSG_STATS(tx_bucket3_size, true),
|
ICSSG_MIIG_STATS(tx_bucket3_size, true),
|
||||||
ICSSG_STATS(tx_bucket4_size, true),
|
ICSSG_MIIG_STATS(tx_bucket4_size, true),
|
||||||
ICSSG_STATS(tx_64B_frames, true),
|
ICSSG_MIIG_STATS(tx_64B_frames, true),
|
||||||
ICSSG_STATS(tx_bucket1_frames, true),
|
ICSSG_MIIG_STATS(tx_bucket1_frames, true),
|
||||||
ICSSG_STATS(tx_bucket2_frames, true),
|
ICSSG_MIIG_STATS(tx_bucket2_frames, true),
|
||||||
ICSSG_STATS(tx_bucket3_frames, true),
|
ICSSG_MIIG_STATS(tx_bucket3_frames, true),
|
||||||
ICSSG_STATS(tx_bucket4_frames, true),
|
ICSSG_MIIG_STATS(tx_bucket4_frames, true),
|
||||||
ICSSG_STATS(tx_bucket5_frames, true),
|
ICSSG_MIIG_STATS(tx_bucket5_frames, true),
|
||||||
ICSSG_STATS(tx_bytes, true),
|
ICSSG_MIIG_STATS(tx_bytes, true),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_PA_STATS(field) \
|
||||||
|
{ \
|
||||||
|
#field, \
|
||||||
|
offsetof(struct pa_stats_regs, field), \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct icssg_pa_stats {
|
||||||
|
char name[ETH_GSTRING_LEN];
|
||||||
|
u32 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
#endif /* __NET_TI_ICSSG_STATS_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue