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