diff options
author | MD Danish Anwar <danishanwar@ti.com> | 2023-08-01 14:44:25 +0530 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-08-02 10:38:11 +0100 |
commit | c1e10d5dc7a1be8d4eba8560540e20bd03c2be01 (patch) | |
tree | 9d5ee5132610c50b60c7e0c66d77a9a83e82d503 /drivers/net/ethernet/ti/icssg/icssg_stats.c | |
parent | 128d5874c0822105ae9556d5435fb8562aff2e3b (diff) |
net: ti: icssg-prueth: Add ICSSG Stats
Add icssg_stats.c to help dump, icssg related driver statistics.
ICSSG has hardware registers for providing statistics like total rx bytes,
total tx bytes, etc. These registers are of 32 bits and hence in case of 1G
link, they overflows in around 32 seconds. The behaviour of these registers
is such that they don't roll back to 0 after overflow but rather stay at
UINT_MAX.
These registers support a feature where the value written to them is
subtracted from the register. This feature can be utilized to fix the
overflowing of stats.
This solution uses a Workqueues based solution where a function gets
called before the registers overflow (every 25 seconds in 1G link, 25000
seconds in 100M link), this function saves the register
values in local variables and writes the last read value to the
register. So any update during the read will be taken care of.
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ti/icssg/icssg_stats.c')
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_stats.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c new file mode 100644 index 000000000000..25deb368a3f0 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2018-2021 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include "icssg_prueth.h" +#include "icssg_stats.h" +#include <linux/regmap.h> + +static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */ + 0xb18, /* Slice 1 stats start */ +}; + +void emac_update_hardware_stats(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + u32 base = stats_base[slice]; + u32 val; + int i; + + for (i = 0; i < ARRAY_SIZE(icssg_all_stats); i++) { + regmap_read(prueth->miig_rt, + base + icssg_all_stats[i].offset, + &val); + regmap_write(prueth->miig_rt, + base + icssg_all_stats[i].offset, + val); + + emac->stats[i] += val; + } +} + +void emac_stats_work_handler(struct work_struct *work) +{ + struct prueth_emac *emac = container_of(work, struct prueth_emac, + stats_work.work); + emac_update_hardware_stats(emac); + + queue_delayed_work(system_long_wq, &emac->stats_work, + msecs_to_jiffies((STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed)); +} |