Commit 0de45db8 authored by Jakub Kicinski's avatar Jakub Kicinski
parents f85cd6ae 550ee90a
...@@ -278,6 +278,26 @@ patternProperties: ...@@ -278,6 +278,26 @@ patternProperties:
additionalProperties: false additionalProperties: false
^pa-stats@[a-f0-9]+$:
description: |
PA-STATS sub-module represented as a SysCon. PA_STATS is a set of
registers where different statistics related to ICSSG, are dumped by
ICSSG firmware. This syscon sub-module will help the device to
access/read/write those statistics.
type: object
additionalProperties: false
properties:
compatible:
items:
- const: ti,pruss-pa-st
- const: syscon
reg:
maxItems: 1
interrupt-controller@[a-f0-9]+$: interrupt-controller@[a-f0-9]+$:
description: | description: |
PRUSS INTC Node. Each PRUSS has a single interrupt controller instance PRUSS INTC Node. Each PRUSS has a single interrupt controller instance
......
...@@ -83,13 +83,11 @@ static void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data) ...@@ -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, ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment