xref: /freebsd/sys/dev/rge/if_rge_stats.c (revision 4bf8ce037dc8fa699be87350bb6467f1b74cb96d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019, 2020, 2023-2025 Kevin Lo <kevlo@openbsd.org>
5  * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*	$OpenBSD: if_rge.c,v 1.38 2025/09/19 00:41:14 kevlo Exp $	*/
21 
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/sockio.h>
25 #include <sys/mbuf.h>
26 #include <sys/malloc.h>
27 #include <sys/endian.h>
28 #include <sys/socket.h>
29 #include <net/if.h>
30 #include <net/if_media.h>
31 #include <sys/queue.h>
32 #include <sys/taskqueue.h>
33 #include <sys/bus.h>
34 #include <sys/module.h>
35 #include <sys/rman.h>
36 
37 #include <netinet/in.h>
38 #include <netinet/if_ether.h>
39 
40 #include <net/bpf.h>
41 #include <net/ethernet.h>
42 #include <net/if.h>
43 #include <net/if_var.h>
44 #include <net/if_arp.h>
45 #include <net/if_dl.h>
46 #include <net/if_media.h>
47 #include <net/if_types.h>
48 #include <net/if_vlan_var.h>
49 
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 
53 #include <dev/mii/mii.h>
54 
55 #include <dev/pci/pcivar.h>
56 #include <dev/pci/pcireg.h>
57 
58 #include "if_rge_vendor.h"
59 #include "if_rgereg.h"
60 #include "if_rgevar.h"
61 #include "if_rge_debug.h"
62 
63 #include "if_rge_stats.h"
64 
65 
66 /**
67  * @brief Fetch the MAC statistics from the hardware
68  *
69  * I don't know if this can be done asynchronously (eg via
70  * an interrupt notification path for completion) as I
71  * currently don't have datasheets.  OpenBSD and the
72  * older if_re driver both implement this using polling.
73  *
74  * Must be called with the driver lock held.
75  */
76 int
rge_hw_mac_stats_fetch(struct rge_softc * sc,struct rge_hw_mac_stats * hws)77 rge_hw_mac_stats_fetch(struct rge_softc *sc, struct rge_hw_mac_stats *hws)
78 {
79 	struct rge_mac_stats *ss = &sc->sc_mac_stats;
80 	uint32_t reg;
81 	uint8_t command;
82 	int i;
83 
84 	RGE_ASSERT_LOCKED(sc);
85 
86 	command = RGE_READ_1(sc, RGE_CMD);
87 	if (command == 0xff || (command & RGE_CMD_RXENB) == 0)
88 		return (ENETDOWN);
89 
90 	bus_dmamap_sync(sc->sc_dmat_stats_buf, ss->map, BUS_DMASYNC_PREREAD);
91 
92 #if 0
93                 if (extend_stats)
94                         re_set_mac_ocp_bit(sc, 0xEA84, (BIT_1 | BIT_0));
95 #endif
96 
97 	/* Program in the memory page to write data into */
98 	RGE_WRITE_4(sc, RGE_DTCCR_HI, RGE_ADDR_HI(ss->paddr));
99 	RGE_WRITE_BARRIER_4(sc, RGE_DTCCR_HI);
100 
101 	(void) RGE_READ_1(sc, RGE_CMD);
102 
103 	RGE_WRITE_4(sc, RGE_DTCCR_LO, RGE_ADDR_LO(ss->paddr));
104 	RGE_WRITE_BARRIER_4(sc, RGE_DTCCR_LO);
105 
106 	/* Inform the hardware to begin stats writing */
107 	RGE_WRITE_4(sc, RGE_DTCCR_LO, RGE_ADDR_LO(ss->paddr) | RGE_DTCCR_CMD);
108 	RGE_WRITE_BARRIER_4(sc, RGE_DTCCR_LO);
109 
110 	for (i = 0; i < 1000; i++) {
111 		RGE_READ_BARRIER_4(sc, RGE_DTCCR_LO);
112 		reg = RGE_READ_4(sc, RGE_DTCCR_LO);
113 		if ((reg & RGE_DTCCR_CMD) == 0)
114 			break;
115 		DELAY(10);
116 	}
117 
118 #if 0
119                 if (extend_stats)
120                         re_clear_mac_ocp_bit(sc, 0xEA84, (BIT_1 | BIT_0));
121 #endif
122 
123 	if ((reg & RGE_DTCCR_CMD) != 0)
124 		return (ETIMEDOUT);
125 
126 	bus_dmamap_sync(sc->sc_dmat_stats_buf, ss->map, BUS_DMASYNC_POSTREAD);
127 
128 	/* Copy them out - assume host == NIC order for now for bring-up */
129 	if (hws != NULL)
130 		*hws = *ss->stats;
131 
132 	return (0);
133 }
134