196fd2bd6SIgor Romanov /* SPDX-License-Identifier: BSD-3-Clause
296fd2bd6SIgor Romanov *
396fd2bd6SIgor Romanov * Copyright(c) 2019-2021 Xilinx, Inc.
496fd2bd6SIgor Romanov * Copyright(c) 2019 Solarflare Communications Inc.
596fd2bd6SIgor Romanov *
696fd2bd6SIgor Romanov * This software was jointly developed between OKTET Labs (under contract
796fd2bd6SIgor Romanov * for Solarflare) and Solarflare Communications, Inc.
896fd2bd6SIgor Romanov */
996fd2bd6SIgor Romanov
1096fd2bd6SIgor Romanov #ifndef _SFC_STATS_H
1196fd2bd6SIgor Romanov #define _SFC_STATS_H
1296fd2bd6SIgor Romanov
1396fd2bd6SIgor Romanov #include <stdint.h>
1496fd2bd6SIgor Romanov
1596fd2bd6SIgor Romanov #include <rte_atomic.h>
1696fd2bd6SIgor Romanov
1796fd2bd6SIgor Romanov #include "sfc_tweak.h"
1896fd2bd6SIgor Romanov
1996fd2bd6SIgor Romanov #ifdef __cplusplus
2096fd2bd6SIgor Romanov extern "C" {
2196fd2bd6SIgor Romanov #endif
2296fd2bd6SIgor Romanov
2396fd2bd6SIgor Romanov /**
2496fd2bd6SIgor Romanov * 64-bit packets and bytes counters covered by 128-bit integer
2596fd2bd6SIgor Romanov * in order to do atomic updates to guarantee consistency if
2696fd2bd6SIgor Romanov * required.
2796fd2bd6SIgor Romanov */
2896fd2bd6SIgor Romanov union sfc_pkts_bytes {
2996fd2bd6SIgor Romanov struct {
3096fd2bd6SIgor Romanov uint64_t pkts;
3196fd2bd6SIgor Romanov uint64_t bytes;
3296fd2bd6SIgor Romanov };
3396fd2bd6SIgor Romanov rte_int128_t pkts_bytes;
3496fd2bd6SIgor Romanov };
3596fd2bd6SIgor Romanov
3696fd2bd6SIgor Romanov /**
3796fd2bd6SIgor Romanov * Update packets and bytes counters atomically in assumption that
3896fd2bd6SIgor Romanov * the counter is written on one core only.
3996fd2bd6SIgor Romanov */
4096fd2bd6SIgor Romanov static inline void
sfc_pkts_bytes_add(union sfc_pkts_bytes * st,uint64_t pkts,uint64_t bytes)4196fd2bd6SIgor Romanov sfc_pkts_bytes_add(union sfc_pkts_bytes *st, uint64_t pkts, uint64_t bytes)
4296fd2bd6SIgor Romanov {
4396fd2bd6SIgor Romanov #if SFC_SW_STATS_ATOMIC
4496fd2bd6SIgor Romanov union sfc_pkts_bytes result;
4596fd2bd6SIgor Romanov
4696fd2bd6SIgor Romanov /* Stats are written on single core only, so just load values */
4796fd2bd6SIgor Romanov result.pkts = st->pkts + pkts;
4896fd2bd6SIgor Romanov result.bytes = st->bytes + bytes;
4996fd2bd6SIgor Romanov
5096fd2bd6SIgor Romanov /*
5196fd2bd6SIgor Romanov * Store the result atomically to guarantee that the reader
5296fd2bd6SIgor Romanov * core sees both counter updates together.
5396fd2bd6SIgor Romanov */
5496fd2bd6SIgor Romanov __atomic_store_n(&st->pkts_bytes.int128, result.pkts_bytes.int128,
55*34f92e82SAndrew Rybchenko __ATOMIC_RELAXED);
5696fd2bd6SIgor Romanov #else
5796fd2bd6SIgor Romanov st->pkts += pkts;
5896fd2bd6SIgor Romanov st->bytes += bytes;
5996fd2bd6SIgor Romanov #endif
6096fd2bd6SIgor Romanov }
6196fd2bd6SIgor Romanov
6296fd2bd6SIgor Romanov /**
6396fd2bd6SIgor Romanov * Get an atomic copy of a packets and bytes counters.
6496fd2bd6SIgor Romanov */
6596fd2bd6SIgor Romanov static inline void
sfc_pkts_bytes_get(const union sfc_pkts_bytes * st,union sfc_pkts_bytes * result)6696fd2bd6SIgor Romanov sfc_pkts_bytes_get(const union sfc_pkts_bytes *st, union sfc_pkts_bytes *result)
6796fd2bd6SIgor Romanov {
6896fd2bd6SIgor Romanov #if SFC_SW_STATS_ATOMIC
6996fd2bd6SIgor Romanov result->pkts_bytes.int128 = __atomic_load_n(&st->pkts_bytes.int128,
70*34f92e82SAndrew Rybchenko __ATOMIC_RELAXED);
7196fd2bd6SIgor Romanov #else
7296fd2bd6SIgor Romanov *result = *st;
7396fd2bd6SIgor Romanov #endif
7496fd2bd6SIgor Romanov }
7596fd2bd6SIgor Romanov
7696fd2bd6SIgor Romanov #ifdef __cplusplus
7796fd2bd6SIgor Romanov }
7896fd2bd6SIgor Romanov #endif
7996fd2bd6SIgor Romanov #endif /* _SFC_STATS_H */
80