/* $NetBSD: igc_evcnt.h,v 1.1 2023/10/04 07:35:27 rin Exp $ */
/*-
* Copyright (c) 2023 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Rin Okuyama <
[email protected]>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IGC_EVCNT_H_
#include <sys/param.h>
#include <sys/types.h>
#include <sys/atomic.h>
#include <sys/evcnt.h>
#include <dev/pci/igc/if_igc.h>
#ifndef IGC_EVENT_COUNTERS
#define IGC_GLOBAL_EVENT(sc, event, delta) ((void)(sc))
#define IGC_DRIVER_EVENT(q, event, delta) ((void)(q))
#define IGC_QUEUE_EVENT(q, event, delta) ((void)(q))
#else
struct igc_counter {
int type;
const char *name;
};
/*
* Global counters:
*
* Events outside queue context.
*/
enum igc_global_event {
igcge_watchdog,
igcge_link,
igcge_count,
};
static const struct igc_counter igc_global_counters[] = {
[igcge_watchdog] = { EVCNT_TYPE_MISC, "Watchdog Timeout" },
[igcge_link] = { EVCNT_TYPE_INTR, "Link Event" },
};
#define IGC_GLOBAL_COUNTERS __arraycount(igc_global_counters)
CTASSERT(IGC_GLOBAL_COUNTERS == igcge_count);
/*
* Driver counters:
*
* Events in queue context, but summed up over queues.
*/
enum igc_driver_event {
igcde_txdma_efbig,
igcde_txdma_defrag,
igcde_txdma_enomem,
igcde_txdma_einval,
igcde_txdma_eagain,
igcde_txdma_other,
igcde_rx_ipcs,
igcde_rx_tcpcs,
igcde_rx_udpcs,
igcde_rx_ipcs_bad,
igcde_rx_l4cs_bad,
igcde_count,
};
static const struct igc_counter igc_driver_counters[] = {
[igcde_txdma_efbig] = { EVCNT_TYPE_MISC, "Tx DMA Soft Fail EFBIG" },
#ifdef notyet
[igcde_txdma_efbig2] = { EVCNT_TYPE_MISC, "Tx DMA Hard Fail EFBIG" },
#endif
[igcde_txdma_defrag] = { EVCNT_TYPE_MISC, "Tx DMA Fail Defrag" },
[igcde_txdma_enomem] = { EVCNT_TYPE_MISC, "Tx DMA Fail ENOMEM" },
[igcde_txdma_einval] = { EVCNT_TYPE_MISC, "Tx DMA Fail EINVAL" },
[igcde_txdma_eagain] = { EVCNT_TYPE_MISC, "Tx DMA Fail EAGAIN" },
[igcde_txdma_other] = { EVCNT_TYPE_MISC, "Tx DMA Fail Other" },
[igcde_rx_ipcs] = { EVCNT_TYPE_MISC, "Rx Csum Offload IPv4" },
[igcde_rx_tcpcs] = { EVCNT_TYPE_MISC, "Rx Csum Offload TCP" },
[igcde_rx_udpcs] = { EVCNT_TYPE_MISC, "Rx Csum Offload UDP" },
[igcde_rx_ipcs_bad] = { EVCNT_TYPE_MISC, "Rx Csum Offload IPv4 Bad" },
[igcde_rx_l4cs_bad] = { EVCNT_TYPE_MISC, "Rx Csum Offload L4 Bad" },
};
#define IGC_DRIVER_COUNTERS __arraycount(igc_driver_counters)
CTASSERT(IGC_DRIVER_COUNTERS == igcde_count);
/*
* Queue counters:
*
* Per queue events.
*/
enum igc_queue_event {
igcqe_irqs,
igcqe_handleq,
igcqe_req,
igcqe_tx_bytes,
igcqe_tx_packets,
igcqe_tx_pcq_drop,
igcqe_tx_no_desc,
igcqe_tx_ctx,
igcqe_rx_bytes,
igcqe_rx_packets,
igcqe_rx_no_mbuf,
igcqe_rx_discard,
igcqe_count,
};
static const struct igc_counter igc_queue_counters[] = {
[igcqe_irqs] = { EVCNT_TYPE_INTR, "Interrupts" },
[igcqe_handleq] = { EVCNT_TYPE_MISC, "Handled in softint" },
[igcqe_req] = { EVCNT_TYPE_MISC, "Requeued in softint" },
[igcqe_tx_bytes] = { EVCNT_TYPE_MISC, "Tx Bytes" },
[igcqe_tx_packets] = { EVCNT_TYPE_MISC, "Tx Packets" },
[igcqe_tx_pcq_drop] = { EVCNT_TYPE_MISC, "Tx pcq Dropped" },
[igcqe_tx_no_desc] = { EVCNT_TYPE_MISC, "Tx No Descriptor Available" },
[igcqe_tx_ctx] = { EVCNT_TYPE_MISC, "Tx Advanced CTX Used" },
[igcqe_rx_bytes] = { EVCNT_TYPE_MISC, "Rx Bytes" },
[igcqe_rx_packets] = { EVCNT_TYPE_MISC, "Rx Packets" },
[igcqe_rx_no_mbuf] = { EVCNT_TYPE_MISC, "Rx No mbuf Available" },
[igcqe_rx_discard] = { EVCNT_TYPE_MISC, "Rx Discarded" },
#ifdef notyet
[igcqe_rx_copy] = { EVCNT_TYPE_MISC, "Rx Copied Frames" },
#endif
};
#define IGC_QUEUE_COUNTERS __arraycount(igc_queue_counters)
CTASSERT(IGC_QUEUE_COUNTERS == igcqe_count);
/*
* MAC counters:
*
* Events obtained from MAC Statistics registers.
*/
static const struct igc_mac_counter {
bus_size_t reg;
bool is64;
const char *name;
} igc_mac_counters[] = {
/* Interrupts */
{ IGC_IAC, false, "Interrupt Assertion" },
/* TX errors */
{ IGC_COLC, false, "Collision" },
{ IGC_SCC, false, "Single Collision" },
{ IGC_MCC, false, "Multiple Collision" },
{ IGC_ECOL, false, "Excessive Collision" },
{ IGC_LATECOL, false, "Late Collision" },
{ IGC_TNCRS, false, "Tx-No CRS" },
/* RX errors */
{ IGC_CRCERRS, false, "CRC Error" },
{ IGC_MPC, false, "Missed Packet" },
{ IGC_RLEC, false, "Receive Length Error" },
{ IGC_LENERRS, false, "Length Errors" },
{ IGC_ALGNERRC, false, "Alignment Error" },
{ IGC_RERC, false, "Receive Error" },
/* flow control events */
{ IGC_XOFFTXC, false, "XOFF Tx" },
{ IGC_XONTXC, false, "XON Tx" },
{ IGC_XOFFRXC, false, "XOFF Rx" },
{ IGC_XONRXC, false, "XON Rx" },
{ IGC_FCRUC, false, "Flow Control Rx Unsupported" },
/* TX statistics */
{ IGC_TOTL, true, "Total Octets Tx" },
{ IGC_GOTCL, true, "Good Octets Tx" },
{ IGC_HGOTCL, true, "Host Good Octets Transmit" },
{ IGC_TPT, false, "Total Packets Tx" },
{ IGC_GPTC, false, "Good Packets Tx" },
{ IGC_MPTC, false, "Multicast Packets Tx" },
{ IGC_BPTC, false, "Broadcast Packets Tx" },
{ IGC_MGTPTC, false, "Management Packets Tx" },
{ IGC_HTDPMC, false, "Host Transmit Discarded by MAC" },
{ IGC_DC, false, "Defer" },
{ IGC_TSCTC, false, "TCP Segmentation Context Tx" },
{ IGC_PTC64, false, "Packets Tx (64 bytes)" },
{ IGC_PTC127, false, "Packets Tx (65-127 bytes)" },
{ IGC_PTC255, false, "Packets Tx (128-255 bytes)" },
{ IGC_PTC511, false, "Packets Tx (256-511 bytes)" },
{ IGC_PTC1023, false, "Packets Tx (512-1023 bytes)" },
{ IGC_PTC1522, false, "Packets Tx (1024-1522 bytes)" },
/* RX statistics */
{ IGC_TORL, true, "Total Octets Rx" },
{ IGC_GORCL, true, "Good Octets Rx" },
{ IGC_HGORCL, true, "Host Good Octets Received" },
{ IGC_TPR, false, "Total Packets Rx" },
{ IGC_GPRC, false, "Good Packets Rx" },
{ IGC_BPRC, false, "Broadcast Packets Rx" },
{ IGC_MPRC, false, "Multicast Packets Rx" },
{ IGC_MGTPRC, false, "Management Packets Rx" },
{ IGC_MGTPDC, false, "Management Packets Dropped" },
{ IGC_RNBC, false, "Rx No Buffers" },
{ IGC_RUC, false, "Rx Undersize" },
{ IGC_RFC, false, "Rx Fragment" },
{ IGC_ROC, false, "Rx Oversize" },
{ IGC_RJC, false, "Rx Jabber" },
{ IGC_RXDMTC, false, "Rx Descriptor Minimum Threshold" },
{ IGC_PRC64, false, "Packets Rx (64 bytes)" },
{ IGC_PRC127, false, "Packets Rx (65-127 bytes)" },
{ IGC_PRC255, false, "Packets Rx (128-255 bytes)" },
{ IGC_PRC511, false, "Packets Rx (256-511 bytes)" },
{ IGC_PRC1023, false, "Packets Rx (512-1023 bytes)" },
{ IGC_PRC1522, false, "Packets Rx (1024-1522 bytes)" },
/* EEE */
{ IGC_TLPIC, false, "EEE Tx LPI" },
{ IGC_RLPIC, false, "EEE Rx LPI" },
};
#define IGC_MAC_COUNTERS __arraycount(igc_mac_counters)
#define IGC_ATOMIC_ADD(p, delta) \
atomic_store_relaxed(p, atomic_load_relaxed(p) + (delta))
#define IGC_ATOMIC_STORE(p, val) \
atomic_store_relaxed(p, val)
#define IGC_ATOMIC_LOAD(p) \
atomic_load_relaxed(p)
#define IGC_GLOBAL_COUNTER(sc, cnt) \
((sc)->sc_global_evcnts[cnt].ev_count)
#define IGC_GLOBAL_COUNTER_ADD(sc, cnt, delta) \
IGC_ATOMIC_ADD(&IGC_GLOBAL_COUNTER(sc, cnt), delta)
#define IGC_GLOBAL_COUNTER_STORE(sc, cnt, val) \
IGC_ATOMIC_STORE(&IGC_GLOBAL_COUNTER(sc, cnt), val)
#define IGC_DRIVER_COUNTER(sc, cnt) \
((sc)->sc_driver_evcnts[cnt].ev_count)
#define IGC_DRIVER_COUNTER_ADD(sc, cnt, delta) \
IGC_ATOMIC_ADD(&IGC_DRIVER_COUNTER(sc, cnt), delta)
#define IGC_DRIVER_COUNTER_STORE(sc, cnt, val) \
IGC_ATOMIC_STORE(&IGC_DRIVER_COUNTER(sc, cnt), val)
#define IGC_QUEUE_DRIVER_COUNTER(q, cnt) \
((q)->igcq_driver_counters[cnt])
#define IGC_QUEUE_DRIVER_COUNTER_VAL(q, cnt) \
IGC_ATOMIC_LOAD(&IGC_QUEUE_DRIVER_COUNTER(q, cnt))
#define IGC_QUEUE_DRIVER_COUNTER_ADD(q, cnt, delta) \
IGC_ATOMIC_ADD(&IGC_QUEUE_DRIVER_COUNTER(q, cnt), delta)
#define IGC_QUEUE_DRIVER_COUNTER_STORE(q, cnt, val) \
IGC_ATOMIC_STORE(&IGC_QUEUE_DRIVER_COUNTER(q, cnt), val)
#define IGC_QUEUE_COUNTER(q, cnt) \
((q)->igcq_queue_evcnts[cnt].ev_count)
#define IGC_QUEUE_COUNTER_ADD(q, cnt, delta) \
IGC_ATOMIC_ADD(&IGC_QUEUE_COUNTER(q, cnt), delta)
#define IGC_QUEUE_COUNTER_STORE(q, cnt, val) \
IGC_ATOMIC_STORE(&IGC_QUEUE_COUNTER(q, cnt), val)
#define IGC_MAC_COUNTER(sc, cnt) \
((sc)->sc_mac_evcnts[cnt].ev_count)
#define IGC_MAC_COUNTER_ADD(sc, cnt, delta) \
IGC_ATOMIC_ADD(&IGC_MAC_COUNTER(sc, cnt), delta)
#define IGC_MAC_COUNTER_STORE(sc, cnt, val) \
IGC_ATOMIC_STORE(&IGC_MAC_COUNTER(sc, cnt), val)
#define IGC_GLOBAL_EVENT(sc, event, delta) \
IGC_GLOBAL_COUNTER_ADD(sc, igcge_ ## event, delta)
#define IGC_DRIVER_EVENT(q, event, delta) \
IGC_QUEUE_DRIVER_COUNTER_ADD(q, igcde_ ## event, delta)
#define IGC_QUEUE_EVENT(q, event, delta) \
IGC_QUEUE_COUNTER_ADD(q, igcqe_ ## event, delta)
#endif /* IGC_EVENT_COUNTERS */
#endif /* _IGC_EVCNT_ */