Commit 76abb5d6 authored by Sean Anderson's avatar Sean Anderson Committed by Jakub Kicinski

net: xilinx: axienet: Add statistics support

Add support for reading the statistics counters, if they are enabled.
The counters may be 64-bit, but we can't detect this statically as
there's no ability bit for it and the counters are read-only. Therefore,
we assume the counters are 32-bits by default. To ensure we don't miss
an overflow, we read all counters at 13-second intervals. This should be
often enough to ensure the bytes counters don't wrap at 2.5 Gbit/s.

Another complication is that the counters may be reset when the device
is reset (depending on configuration). To ensure the counters persist
across link up/down (including suspend/resume), we maintain our own
versions along with the last counter value we saw. Because we might wait
up to 100 ms for the reset to complete, we use a mutex to protect
writing hw_stats. We can't sleep in ndo_get_stats64, so we use a seqlock
to protect readers.

We don't bother disabling the refresh work when we detect 64-bit
counters. This is because the reset issue requires us to read
hw_stat_base and reset_in_progress anyway, which would still require the
seqcount. And I don't think skipping the task is worth the extra
bookkeeping.

We can't use the byte counters for either get_stats64 or
get_eth_mac_stats. This is because the byte counters include everything
in the frame (destination address to FCS, inclusive). But
rtnl_link_stats64 wants bytes excluding the FCS, and
ethtool_eth_mac_stats wants to exclude the L2 overhead (addresses and
length/type). It might be possible to calculate the byte values Linux
expects based on the frame counters, but I think it is simpler to use
the existing software counters.

get_ethtool_stats is implemented for nonstandard statistics. This
includes the aforementioned byte counters, VLAN and PFC frame
counters, and user-defined (e.g. with custom RTL) counters.
Signed-off-by: default avatarSean Anderson <sean.anderson@linux.dev>
Link: https://patch.msgid.link/20240820175343.760389-3-sean.anderson@linux.devSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d70e3788
......@@ -156,6 +156,7 @@
#define XAE_TPID0_OFFSET 0x00000028 /* VLAN TPID0 register */
#define XAE_TPID1_OFFSET 0x0000002C /* VLAN TPID1 register */
#define XAE_PPST_OFFSET 0x00000030 /* PCS PMA Soft Temac Status Reg */
#define XAE_STATS_OFFSET 0x00000200 /* Statistics counters */
#define XAE_RCW0_OFFSET 0x00000400 /* Rx Configuration Word 0 */
#define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */
#define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */
......@@ -163,6 +164,7 @@
#define XAE_EMMC_OFFSET 0x00000410 /* MAC speed configuration */
#define XAE_PHYC_OFFSET 0x00000414 /* RX Max Frame Configuration */
#define XAE_ID_OFFSET 0x000004F8 /* Identification register */
#define XAE_ABILITY_OFFSET 0x000004FC /* Ability Register offset */
#define XAE_MDIO_MC_OFFSET 0x00000500 /* MDIO Setup */
#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MDIO Control */
#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MDIO Write Data */
......@@ -283,6 +285,16 @@
#define XAE_PHYC_SGLINKSPD_100 0x40000000 /* SGMII link 100 Mbit */
#define XAE_PHYC_SGLINKSPD_1000 0x80000000 /* SGMII link 1000 Mbit */
/* Bit masks for Axi Ethernet ability register */
#define XAE_ABILITY_PFC BIT(16)
#define XAE_ABILITY_FRAME_FILTER BIT(10)
#define XAE_ABILITY_HALF_DUPLEX BIT(9)
#define XAE_ABILITY_STATS BIT(8)
#define XAE_ABILITY_2_5G BIT(3)
#define XAE_ABILITY_1G BIT(2)
#define XAE_ABILITY_100M BIT(1)
#define XAE_ABILITY_10M BIT(0)
/* Bit masks for Axi Ethernet MDIO interface MC register */
#define XAE_MDIO_MC_MDIOEN_MASK 0x00000040 /* MII management enable */
#define XAE_MDIO_MC_CLOCK_DIVIDE_MAX 0x3F /* Maximum MDIO divisor */
......@@ -331,6 +343,7 @@
#define XAE_FEATURE_FULL_RX_CSUM BIT(2)
#define XAE_FEATURE_FULL_TX_CSUM BIT(3)
#define XAE_FEATURE_DMA_64BIT BIT(4)
#define XAE_FEATURE_STATS BIT(5)
#define XAE_NO_CSUM_OFFLOAD 0
......@@ -344,6 +357,61 @@
#define XLNX_MII_STD_SELECT_REG 0x11
#define XLNX_MII_STD_SELECT_SGMII BIT(0)
/* enum temac_stat - TEMAC statistics counters
*
* Index of statistics counters within the TEMAC. This must match the
* order/offset of hardware registers exactly.
*/
enum temac_stat {
STAT_RX_BYTES = 0,
STAT_TX_BYTES,
STAT_UNDERSIZE_FRAMES,
STAT_FRAGMENT_FRAMES,
STAT_RX_64_BYTE_FRAMES,
STAT_RX_65_127_BYTE_FRAMES,
STAT_RX_128_255_BYTE_FRAMES,
STAT_RX_256_511_BYTE_FRAMES,
STAT_RX_512_1023_BYTE_FRAMES,
STAT_RX_1024_MAX_BYTE_FRAMES,
STAT_RX_OVERSIZE_FRAMES,
STAT_TX_64_BYTE_FRAMES,
STAT_TX_65_127_BYTE_FRAMES,
STAT_TX_128_255_BYTE_FRAMES,
STAT_TX_256_511_BYTE_FRAMES,
STAT_TX_512_1023_BYTE_FRAMES,
STAT_TX_1024_MAX_BYTE_FRAMES,
STAT_TX_OVERSIZE_FRAMES,
STAT_RX_GOOD_FRAMES,
STAT_RX_FCS_ERRORS,
STAT_RX_BROADCAST_FRAMES,
STAT_RX_MULTICAST_FRAMES,
STAT_RX_CONTROL_FRAMES,
STAT_RX_LENGTH_ERRORS,
STAT_RX_VLAN_FRAMES,
STAT_RX_PAUSE_FRAMES,
STAT_RX_CONTROL_OPCODE_ERRORS,
STAT_TX_GOOD_FRAMES,
STAT_TX_BROADCAST_FRAMES,
STAT_TX_MULTICAST_FRAMES,
STAT_TX_UNDERRUN_ERRORS,
STAT_TX_CONTROL_FRAMES,
STAT_TX_VLAN_FRAMES,
STAT_TX_PAUSE_FRAMES,
STAT_TX_SINGLE_COLLISION_FRAMES,
STAT_TX_MULTIPLE_COLLISION_FRAMES,
STAT_TX_DEFERRED_FRAMES,
STAT_TX_LATE_COLLISIONS,
STAT_TX_EXCESS_COLLISIONS,
STAT_TX_EXCESS_DEFERRAL,
STAT_RX_ALIGNMENT_ERRORS,
STAT_TX_PFC_FRAMES,
STAT_RX_PFC_FRAMES,
STAT_USER_DEFINED0,
STAT_USER_DEFINED1,
STAT_USER_DEFINED2,
STAT_COUNT,
};
/**
* struct axidma_bd - Axi Dma buffer descriptor layout
* @next: MM2S/S2MM Next Descriptor Pointer
......@@ -434,6 +502,16 @@ struct skbuf_dma_descriptor {
* @tx_packets: TX packet count for statistics
* @tx_bytes: TX byte count for statistics
* @tx_stat_sync: Synchronization object for TX stats
* @hw_stat_base: Base offset for statistics counters. This may be nonzero if
* the statistics counteres were reset or wrapped around.
* @hw_last_counter: Last-seen value of each statistic counter
* @reset_in_progress: Set while we are performing a reset and statistics
* counters may be invalid
* @hw_stats_seqcount: Sequence counter for @hw_stat_base, @hw_last_counter,
* and @reset_in_progress.
* @stats_lock: Lock for @hw_stats_seqcount
* @stats_work: Work for reading the hardware statistics counters often enough
* to catch overflows.
* @dma_err_task: Work structure to process Axi DMA errors
* @tx_irq: Axidma TX IRQ number
* @rx_irq: Axidma RX IRQ number
......@@ -505,6 +583,13 @@ struct axienet_local {
u64_stats_t tx_bytes;
struct u64_stats_sync tx_stat_sync;
u64 hw_stat_base[STAT_COUNT];
u32 hw_last_counter[STAT_COUNT];
seqcount_mutex_t hw_stats_seqcount;
struct mutex stats_lock;
struct delayed_work stats_work;
bool reset_in_progress;
struct work_struct dma_err_task;
int tx_irq;
......
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