if_rge: initial import of if_rge driver from OpenBSD.

This is an initial import of the if_rge driver from OpenBSD
and adapted to FreeBSD.

Differential Revision:	https://reviews.freebsd.org/D54101
This commit is contained in:
Adrian Chadd
2025-12-05 21:26:30 -08:00
parent edd982b953
commit 4bf8ce037d
17 changed files with 19407 additions and 0 deletions
+1
View File
@@ -501,6 +501,7 @@ MAN= aac.4 \
random.4 \
rctl.4 \
re.4 \
rge.4 \
rgephy.4 \
rights.4 \
rl.4 \
+165
View File
@@ -0,0 +1,165 @@
.\"
.\" Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
.\"
.\" SPDX-License-Identifier: BSD-2-Clause
.\"
.Dd December 12, 2025
.Dt RGE 4
.Os
.Sh NAME
.Nm rge
.Nd RealTek RTL8125/RTL8126/RTL8127/Killer E3000 PCIe Ethernet adapter driver
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device rge"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_rge_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for various NICs based on the RealTek RTL8125,
RTL8126 and RTL8127 PCIe Ethernet controllers.
.Pp
All of the NICs supported by this driver support 10, 100 and 1000Mbit
over CAT5 cable.
NICs based on the RTL8125 additionally support 2.5Gbit over CAT6 cable.
NICs based on the RTL8126 additionally support 2.5Gbit and 5Gbit over CAT6
cable.
NICs based on the RTL8127 additionally support 2.5Gbit, 5Gbit and 10Gbit
over CAT6 cable.
.Pp
All NICs supported by the
.Nm
driver have TCP/IP checksum offload and hardware VLAN tagging/insertion
features, and use a descriptor-based DMA mechanism.
They are also
capable of TCP large send (TCP segmentation offload).
.Pp
The RTL8125, RTL8126 and RTL8127 devices are single-chip solutions combining
both a MAC and PHY.
Standalone cards are available in 1x PCIe models.
.Pp
The RTL8125, RTL8126 and RTL8127 also support jumbo frames, which can be
configured via the interface MTU setting.
The MTU is limited to 9126.
Selecting an MTU larger than 1500 bytes with the
.Xr ifconfig 8
utility configures the adapter to receive and transmit jumbo frames.
.Pp
The
.Nm
driver supports the following media types:
.Bl -tag -width "10baseT/UTP"
.It Cm autoselect
Enable autoselection of the media type and options.
The user can manually override
the autoselected mode by adding media options to
.Xr rc.conf 5 .
.It Cm 10baseT/UTP
Set 10Mbps operation.
The
.Xr ifconfig 8
.Cm mediaopt
option can also be used to select either
.Cm full-duplex
or
.Cm half-duplex
modes.
.It Cm 100baseTX
Set 100Mbps (Fast Ethernet) operation.
The
.Xr ifconfig 8
.Cm mediaopt
option can also be used to select either
.Cm full-duplex
or
.Cm half-duplex
modes.
.It Cm 1000baseTX
Set 1000baseTX operation over twisted pair.
The RealTek gigE chips support 1000Mbps in
.Cm full-duplex
mode only.
.It Cm 2500baseTX
Set 2500baseTX operation over twisted pair.
The RealTek devices support 2.5Gbit in
.Cm full-duplex
mode only.
.It Cm 5000baseTX
Set 5000baseTX operation over twisted pair.
The RealTek devices support 5Gbit in
.Cm full-duplex
mode only.
.It Cm 10000baseTX
Set 10000baseTX operation over twisted pair.
The RealTek devices support 10Gbit in
.Cm full-duplex
mode only.
.El
.Pp
The
.Nm
driver supports the following media options:
.Bl -tag -width "full-duplex"
.It Cm full-duplex
Force full duplex operation.
.It Cm half-duplex
Force half duplex operation.
.El
.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
.Sh HARDWARE
The
.Nm
driver supports RealTek RTL8125, RTL8126, RTL8125 and Killer E3000 based
PCIe 1GB to 1GB Ethernet devices.
.Sh SYSCTL VARIABLES
The following variables are available as both
.Xr sysctl 8
variables and
.Xr loader 8
tunables:
.Bl -tag -width "xxxxxx"
.It Va dev.rge.%d.debug
Configure runtime debug output. This is a 32 bit bitmask.
.El
.Sh DIAGNOSTICS
.Bl -diag
.It "rge%d: watchdog timeout"
The device has stopped responding to the network, or there is a problem with
the network connection (cable).
.El
.Sh SEE ALSO
.Xr altq 4 ,
.Xr arp 4 ,
.Xr miibus 4 ,
.Xr netintro 4 ,
.Xr ng_ether 4 ,
.Xr polling 4 ,
.Xr vlan 4 ,
.Xr ifconfig 8
.Rs
.%U https://www.realtek.com/
.Re
.Sh HISTORY
The
.Nm
device driver first appeared in
.Fx 16.0 .
.Sh AUTHORS
The
.Nm
driver was written by
.An Kevin Lo Aq Mt kevlo@openbsd.org
and ported to FreeBSD by
.An Adrian Chadd Aq Mt adrian@freebsd.org .
+4
View File
@@ -2866,6 +2866,10 @@ dev/regulator/regnode_if.m optional regulator
dev/regulator/regulator.c optional regulator
dev/regulator/regulator_bus.c optional regulator fdt
dev/regulator/regulator_fixed.c optional regulator
dev/rge/if_rge.c optional rge
dev/rge/if_rge_hw.c optional rge
dev/rge/if_rge_stats.c optional rge
dev/rge/if_rge_sysctl.c optional rge
dev/rl/if_rl.c optional rl pci
dev/rndtest/rndtest.c optional rndtest
#
+2683
View File
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_RGE_DEBUG_H__
#define __IF_RGE_DEBUG_H__
#define RGE_DEBUG_XMIT 0x00000001
#define RGE_DEBUG_RECV 0x00000002
#define RGE_DEBUG_INTR 0x00000004
#define RGE_DEBUG_SETUP 0x00000008
#define RGE_DEBUG_INIT 0x00000010
#define RGE_DEBUG_XMIT_DESC 0x00000020
#define RGE_DEBUG_RECV_DESC 0x00000040
#define RGE_DPRINTF(sc, dbg, ...) \
do { \
if (((sc)->sc_debug & (dbg)) != 0) \
device_printf((sc)->sc_dev, __VA_ARGS__); \
} while (0)
#define RGE_DLOG(sc, dbg, ...) \
do { \
if (((sc)->sc_debug & (dbg)) != 0) \
device_log((sc)->sc_dev, LOG_DEBUG, \
__VA_ARGS__); \
} while (0)
#define RGE_PRINT_ERROR(sc, ...) \
do { \
device_printf((sc)->sc_dev, "[ERR] " __VA_ARGS__); \
} while (0)
#define RGE_PRINT_INFO(sc, ...) \
do { \
device_printf((sc)->sc_dev, "[INFO] " __VA_ARGS__); \
} while (0)
#define RGE_PRINT_TODO(sc, ...) \
do { \
device_printf((sc)->sc_dev, "[TODO] " __VA_ARGS__); \
} while (0)
#define RGE_PRINT_WARN(sc, ...) \
do { \
device_printf((sc)->sc_dev, "[WARN] " __VA_ARGS__); \
} while (0)
#endif /* __IF_RGE_DEBUG_H__ */
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_RGE_HW_H__
#define __IF_RGE_HW_H__
struct rge_softc;
extern int rge_chipinit(struct rge_softc *);
extern void rge_mac_config_mcu(struct rge_softc *, enum rge_mac_type);
extern void rge_write_mac_ocp(struct rge_softc *, uint16_t, uint16_t);
extern uint16_t rge_read_mac_ocp(struct rge_softc *, uint16_t);
extern void rge_ephy_config(struct rge_softc *);
extern int rge_phy_config(struct rge_softc *);
extern void rge_set_macaddr(struct rge_softc *, const uint8_t *);
extern void rge_get_macaddr(struct rge_softc *, uint8_t *);
extern void rge_hw_reset(struct rge_softc *);
extern void rge_config_imtype(struct rge_softc *, int);
extern void rge_disable_aspm_clkreq(struct rge_softc *);
extern void rge_setup_intr(struct rge_softc *, int);
extern void rge_write_csi(struct rge_softc *, uint32_t, uint32_t);
extern uint32_t rge_read_csi(struct rge_softc *, uint32_t);
extern void rge_write_phy(struct rge_softc *, uint16_t, uint16_t, uint16_t);
extern uint16_t rge_read_phy(struct rge_softc *, uint16_t, uint16_t);
extern void rge_write_phy_ocp(struct rge_softc *, uint16_t, uint16_t);
extern uint16_t rge_read_phy_ocp(struct rge_softc *sc, uint16_t reg);
extern int rge_get_link_status(struct rge_softc *);
#endif /* __IF_RGE_HW_H__ */
File diff suppressed because it is too large Load Diff
+133
View File
@@ -0,0 +1,133 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019, 2020, 2023-2025 Kevin Lo <kevlo@openbsd.org>
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: if_rge.c,v 1.38 2025/09/19 00:41:14 kevlo Exp $ */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/endian.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <net/if_vlan_var.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <dev/mii/mii.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include "if_rge_vendor.h"
#include "if_rgereg.h"
#include "if_rgevar.h"
#include "if_rge_debug.h"
#include "if_rge_stats.h"
/**
* @brief Fetch the MAC statistics from the hardware
*
* I don't know if this can be done asynchronously (eg via
* an interrupt notification path for completion) as I
* currently don't have datasheets. OpenBSD and the
* older if_re driver both implement this using polling.
*
* Must be called with the driver lock held.
*/
int
rge_hw_mac_stats_fetch(struct rge_softc *sc, struct rge_hw_mac_stats *hws)
{
struct rge_mac_stats *ss = &sc->sc_mac_stats;
uint32_t reg;
uint8_t command;
int i;
RGE_ASSERT_LOCKED(sc);
command = RGE_READ_1(sc, RGE_CMD);
if (command == 0xff || (command & RGE_CMD_RXENB) == 0)
return (ENETDOWN);
bus_dmamap_sync(sc->sc_dmat_stats_buf, ss->map, BUS_DMASYNC_PREREAD);
#if 0
if (extend_stats)
re_set_mac_ocp_bit(sc, 0xEA84, (BIT_1 | BIT_0));
#endif
/* Program in the memory page to write data into */
RGE_WRITE_4(sc, RGE_DTCCR_HI, RGE_ADDR_HI(ss->paddr));
RGE_WRITE_BARRIER_4(sc, RGE_DTCCR_HI);
(void) RGE_READ_1(sc, RGE_CMD);
RGE_WRITE_4(sc, RGE_DTCCR_LO, RGE_ADDR_LO(ss->paddr));
RGE_WRITE_BARRIER_4(sc, RGE_DTCCR_LO);
/* Inform the hardware to begin stats writing */
RGE_WRITE_4(sc, RGE_DTCCR_LO, RGE_ADDR_LO(ss->paddr) | RGE_DTCCR_CMD);
RGE_WRITE_BARRIER_4(sc, RGE_DTCCR_LO);
for (i = 0; i < 1000; i++) {
RGE_READ_BARRIER_4(sc, RGE_DTCCR_LO);
reg = RGE_READ_4(sc, RGE_DTCCR_LO);
if ((reg & RGE_DTCCR_CMD) == 0)
break;
DELAY(10);
}
#if 0
if (extend_stats)
re_clear_mac_ocp_bit(sc, 0xEA84, (BIT_1 | BIT_0));
#endif
if ((reg & RGE_DTCCR_CMD) != 0)
return (ETIMEDOUT);
bus_dmamap_sync(sc->sc_dmat_stats_buf, ss->map, BUS_DMASYNC_POSTREAD);
/* Copy them out - assume host == NIC order for now for bring-up */
if (hws != NULL)
*hws = *ss->stats;
return (0);
}
+26
View File
@@ -0,0 +1,26 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_RGE_STATS_H__
#define __IF_RGE_STATS_H__
struct rge_softc;
extern int rge_hw_mac_stats_fetch(struct rge_softc *,
struct rge_hw_mac_stats *);
#endif /* __IF_RGE_STATS_H__ */
+238
View File
@@ -0,0 +1,238 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/endian.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <net/if_vlan_var.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <dev/mii/mii.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include "if_rge_vendor.h"
#include "if_rgereg.h"
#include "if_rgevar.h"
#include "if_rge_debug.h"
#include "if_rge_sysctl.h"
static void
rge_sysctl_drv_stats_attach(struct rge_softc *sc)
{
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
/* Create stats node */
tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "drv_stats",
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "driver statistics");
child = SYSCTL_CHILDREN(tree);
/* Driver stats */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_call_cnt", CTLFLAG_RD,
&sc->sc_drv_stats.transmit_call_cnt, "Calls to rge_transmit");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_stopped_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.transmit_stopped_cnt,
"rge_transmit calls to a stopped interface");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_full_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.transmit_full_cnt,
"rge_transmit calls to a full tx queue");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_queued_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.transmit_queued_cnt,
"rge_transmit calls which queued a frame");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "intr_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.intr_cnt,
"incoming interrupts");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "intr_system_errcnt",
CTLFLAG_RD, &sc->sc_drv_stats.intr_system_err_cnt,
"INTR_SYSTEM_ERR interrupt leading to a hardware reset");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rxeof_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.rxeof_cnt,
"calls to rxeof() to process RX frames");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "txeof_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.txeof_cnt,
"calls to rxeof() to process TX frame completions");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "link_state_change_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.link_state_change_cnt,
"link state changes");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_task_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.tx_task_cnt,
"calls to tx_task task to send queued frames");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "recv_input_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.recv_input_cnt,
"calls to if_input to process frames");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_desc_err_multidesc",
CTLFLAG_RD, &sc->sc_drv_stats.rx_desc_err_multidesc,
"multi-descriptor RX frames (unsupported, so dropped)");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_watchdog_timeout_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.tx_watchdog_timeout_cnt,
"TX watchdog timeouts");
/* TX encap counters */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_encap_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.tx_encap_cnt, "calls to rge_encap()");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_encap_refrag_cnt",
CTLFLAG_RD, &sc->sc_drv_stats.tx_encap_refrag_cnt,
"How often rge_encap() has re-linearised TX mbufs");
/* TX checksum counters */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_encap_err_toofrag",
CTLFLAG_RD, &sc->sc_drv_stats.tx_encap_err_toofrag,
"How often rge_encap() failed to defrag a TX mbuf");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_ip_csum_set",
CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_ip_csum_set,
"Number of frames with TX'ed with IPv4 checksum offload set");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_tcp_csum_set",
CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_tcp_csum_set,
"Number of frames TX'ed with TCP checksum offload set");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_udp_csum_set",
CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_udp_csum_set,
"Number of frames TX'ed with UDP checksum offload set");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_vlan_tag_set",
CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_vlan_tag_set,
"Number of frames TX'ed with VLAN offload tag set");
/* RX counters */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_ether_csum_err",
CTLFLAG_RD, &sc->sc_drv_stats.rx_ether_csum_err,
"Number of frames RX'ed with invalid ethernet CRC");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_vlan_tag",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_vlan_tag,
"Number of frames RX'ed with offload VLAN tag");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_jumbo_frag",
CTLFLAG_RD, &sc->sc_drv_stats.rx_desc_jumbo_frag,
"Number of descriptors RX'ed as part of a multi-descriptor frame");
/* RX checksum offload counters */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_ipv4_exists",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_ipv4_exists,
"Number of frames RX'ed with IPv4 checksum offload set");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_ipv4_valid",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_ipv4_valid,
"Number of frames RX'ed with IPv4 checksum offload valid");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_tcp_exists",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_tcp_exists,
"Number of frames RX'ed with TCP checksum offload set");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_tcp_valid",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_tcp_valid,
"Number of frames RX'ed with TCP checksum offload valid");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_udp_exists",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_udp_exists,
"Number of frames RX'ed with UDP checksum offload set");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_udp_valid",
CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_udp_valid,
"Number of frames RX'ed with UDP checksum offload valid");
}
static void
rge_sysctl_mac_stats_attach(struct rge_softc *sc)
{
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
struct rge_mac_stats *ss = &sc->sc_mac_stats;
/* Create stats node */
tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "mac statistics");
child = SYSCTL_CHILDREN(tree);
/* MAC statistics */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_tx_ok", CTLFLAG_RD,
&ss->lcl_stats.rge_tx_ok, "");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_rx_ok", CTLFLAG_RD,
&ss->lcl_stats.rge_rx_ok, "");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_tx_er", CTLFLAG_RD,
&ss->lcl_stats.rge_tx_er, "");
/* uint32_t rge_rx_er */
/* uint16_t rge_miss_pkt */
/* uint16_t rge_fae */
/* uint32_t rge_tx_1col */
/* uint32_t rge_tx_mcol */
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_rx_ok_phy", CTLFLAG_RD,
&ss->lcl_stats.rge_rx_ok_phy, "");
SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_rx_ok_brd", CTLFLAG_RD,
&ss->lcl_stats.rge_rx_ok_brd, "");
/* uint32_t rge_rx_ok_mul */
/* uint16_t rge_tx_abt */
/* uint16_t rge_tx_undrn */
}
void
rge_sysctl_attach(struct rge_softc *sc)
{
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"debug", CTLFLAG_RW, &sc->sc_debug, 0,
"control debugging printfs");
/* Stats */
rge_sysctl_drv_stats_attach(sc);
rge_sysctl_mac_stats_attach(sc);
}
+25
View File
@@ -0,0 +1,25 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_RGE_SYSCTL_H__
#define __IF_RGE_SYSCTL_H__
struct rge_softc;
extern void rge_sysctl_attach(struct rge_softc *);
#endif /* __IF_RGE_SYSCTL_H__ */
+28
View File
@@ -0,0 +1,28 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_RGE_VENDOR_H__
#define __IF_RGE_VENDOR_H__
#define PCI_VENDOR_REALTEK 0x10ec
#define PCI_PRODUCT_REALTEK_E3000 0x3000
#define PCI_PRODUCT_REALTEK_RTL8125 0x8125
#define PCI_PRODUCT_REALTEK_RTL8126 0x8126
#define PCI_PRODUCT_REALTEK_RTL8127 0x8127
#endif /* __IF_RGE_VENDOR_H__ */
+387
View File
@@ -0,0 +1,387 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019, 2020, 2025 Kevin Lo <kevlo@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: if_rgereg.h,v 1.15 2025/09/19 00:41:14 kevlo Exp $ */
#ifndef __IF_RGEREG_H__
#define __IF_RGEREG_H__
#define RGE_PCI_BAR0 PCI_MAPREG_START
#define RGE_PCI_BAR1 (PCI_MAPREG_START + 4)
#define RGE_PCI_BAR2 (PCI_MAPREG_START + 8)
/* For now, a single MSI message, no multi-RX/TX ring support */
#define RGE_MSI_MESSAGES 1
#define RGE_MAC0 0x0000
#define RGE_MAC4 0x0004
#define RGE_MAR0 0x0008
#define RGE_MAR4 0x000c
#define RGE_DTCCR_LO 0x0010
#define RGE_DTCCR_CMD (1U << 3)
#define RGE_DTCCR_HI 0x0014
#define RGE_TXDESC_ADDR_LO 0x0020
#define RGE_TXDESC_ADDR_HI 0x0024
#define RGE_INT_CFG0 0x0034
#define RGE_CMD 0x0037
#define RGE_IMR 0x0038
#define RGE_ISR 0x003c
#define RGE_TXCFG 0x0040
#define RGE_RXCFG 0x0044
#define RGE_TIMERCNT 0x0048
#define RGE_EECMD 0x0050
#define RGE_CFG0 0x0051
#define RGE_CFG1 0x0052
#define RGE_CFG2 0x0053
#define RGE_CFG3 0x0054
#define RGE_CFG4 0x0055
#define RGE_CFG5 0x0056
#define RGE_TDFNR 0x0057
#define RGE_TIMERINT0 0x0058
#define RGE_TIMERINT1 0x005c
#define RGE_CSIDR 0x0064
#define RGE_CSIAR 0x0068
#define RGE_PHYSTAT 0x006c
#define RGE_PMCH 0x006f
#define RGE_INT_CFG1 0x007a
#define RGE_EPHYAR 0x0080
#define RGE_TIMERINT2 0x008c
#define RGE_TXSTART 0x0090
#define RGE_MACOCP 0x00b0
#define RGE_PHYOCP 0x00b8
#define RGE_DLLPR 0x00d0
#define RGE_TWICMD 0x00d2
#define RGE_MCUCMD 0x00d3
#define RGE_RXMAXSIZE 0x00da
#define RGE_CPLUSCMD 0x00e0
#define RGE_IM 0x00e2
#define RGE_RXDESC_ADDR_LO 0x00e4
#define RGE_RXDESC_ADDR_HI 0x00e8
#define RGE_PPSW 0x00f2
#define RGE_TIMERINT3 0x00f4
#define RGE_RADMFIFO_PROTECT 0x0402
#define RGE_INTMITI(i) (0x0a00 + (i) * 4)
#define RGE_PHYBASE 0x0a40
#define RGE_EPHYAR_EXT_ADDR 0x0ffe
#define RGE_ADDR0 0x19e0
#define RGE_ADDR1 0x19e4
#define RGE_RSS_CTRL 0x4500
#define RGE_RXQUEUE_CTRL 0x4800
#define RGE_EEE_TXIDLE_TIMER 0x6048
/* Flags for register RGE_INT_CFG0 */
#define RGE_INT_CFG0_EN 0x01
#define RGE_INT_CFG0_TIMEOUT_BYPASS 0x02
#define RGE_INT_CFG0_MITIGATION_BYPASS 0x04
#define RGE_INT_CFG0_RDU_BYPASS_8126 0x10
#define RGE_INT_CFG0_AVOID_MISS_INTR 0x40
/* Flags for register RGE_CMD */
#define RGE_CMD_RXBUF_EMPTY 0x01
#define RGE_CMD_TXENB 0x04
#define RGE_CMD_RXENB 0x08
#define RGE_CMD_RESET 0x10
#define RGE_CMD_STOPREQ 0x80
/* Flags for register RGE_ISR */
#define RGE_ISR_RX_OK 0x00000001
#define RGE_ISR_RX_ERR 0x00000002
#define RGE_ISR_TX_OK 0x00000004
#define RGE_ISR_TX_ERR 0x00000008
#define RGE_ISR_RX_DESC_UNAVAIL 0x00000010
#define RGE_ISR_LINKCHG 0x00000020
#define RGE_ISR_RX_FIFO_OFLOW 0x00000040
#define RGE_ISR_TX_DESC_UNAVAIL 0x00000080
#define RGE_ISR_SWI 0x00000100
#define RGE_ISR_PCS_TIMEOUT 0x00004000
#define RGE_ISR_SYSTEM_ERR 0x00008000
#define RGE_INTRS \
(RGE_ISR_RX_OK | RGE_ISR_RX_ERR | RGE_ISR_TX_OK | \
RGE_ISR_TX_ERR | RGE_ISR_LINKCHG | RGE_ISR_TX_DESC_UNAVAIL | \
RGE_ISR_PCS_TIMEOUT | RGE_ISR_SYSTEM_ERR)
#define RGE_INTRS_TIMER \
(RGE_ISR_RX_ERR | RGE_ISR_TX_ERR | RGE_ISR_PCS_TIMEOUT | \
RGE_ISR_SYSTEM_ERR)
/* Flags for register RGE_TXCFG */
#define RGE_TXCFG_HWREV 0x7cf00000
/* Flags for register RGE_RXCFG */
#define RGE_RXCFG_ALLPHYS 0x00000001
#define RGE_RXCFG_INDIV 0x00000002
#define RGE_RXCFG_MULTI 0x00000004
#define RGE_RXCFG_BROAD 0x00000008
#define RGE_RXCFG_RUNT 0x00000010
#define RGE_RXCFG_ERRPKT 0x00000020
#define RGE_RXCFG_VLANSTRIP 0x00c00000
/* Flags for register RGE_EECMD */
#define RGE_EECMD_WRITECFG 0xc0
/* Flags for register RGE_CFG1 */
#define RGE_CFG1_PM_EN 0x01
#define RGE_CFG1_SPEED_DOWN 0x10
/* Flags for register RGE_CFG2 */
#define RGE_CFG2_PMSTS_EN 0x20
#define RGE_CFG2_CLKREQ_EN 0x80
/* Flags for register RGE_CFG3 */
#define RGE_CFG3_RDY_TO_L23 0x02
#define RGE_CFG3_WOL_LINK 0x10
#define RGE_CFG3_WOL_MAGIC 0x20
/* Flags for register RGE_CFG5 */
#define RGE_CFG5_PME_STS 0x01
#define RGE_CFG5_WOL_LANWAKE 0x02
#define RGE_CFG5_WOL_UCAST 0x10
#define RGE_CFG5_WOL_MCAST 0x20
#define RGE_CFG5_WOL_BCAST 0x40
/* Flags for register RGE_CSIAR */
#define RGE_CSIAR_BYTE_EN 0x0000000f
#define RGE_CSIAR_BYTE_EN_SHIFT 12
#define RGE_CSIAR_ADDR_MASK 0x00000fff
#define RGE_CSIAR_BUSY 0x80000000
/* Flags for register RGE_PHYSTAT */
#define RGE_PHYSTAT_FDX 0x0001
#define RGE_PHYSTAT_LINK 0x0002
#define RGE_PHYSTAT_10MBPS 0x0004
#define RGE_PHYSTAT_100MBPS 0x0008
#define RGE_PHYSTAT_1000MBPS 0x0010
#define RGE_PHYSTAT_RXFLOW 0x0020
#define RGE_PHYSTAT_TXFLOW 0x0040
#define RGE_PHYSTAT_2500MBPS 0x0400
#define RGE_PHYSTAT_5000MBPS 0x1000
#define RGE_PHYSTAT_10000MBPS 0x4000
/* Flags for register RGE_EPHYAR */
#define RGE_EPHYAR_DATA_MASK 0x0000ffff
#define RGE_EPHYAR_BUSY 0x80000000
#define RGE_EPHYAR_ADDR_MASK 0x0000007f
#define RGE_EPHYAR_ADDR_SHIFT 16
/* Flags for register RGE_TXSTART */
#define RGE_TXSTART_START 0x0001
/* Flags for register RGE_MACOCP */
#define RGE_MACOCP_DATA_MASK 0x0000ffff
#define RGE_MACOCP_BUSY 0x80000000
#define RGE_MACOCP_ADDR_SHIFT 16
/* Flags for register RGE_PHYOCP */
#define RGE_PHYOCP_DATA_MASK 0x0000ffff
#define RGE_PHYOCP_BUSY 0x80000000
#define RGE_PHYOCP_ADDR_SHIFT 16
/* Flags for register RGE_DLLPR. */
#define RGE_DLLPR_PFM_EN 0x40
#define RGE_DLLPR_TX_10M_PS_EN 0x80
/* Flags for register RGE_MCUCMD */
#define RGE_MCUCMD_RXFIFO_EMPTY 0x10
#define RGE_MCUCMD_TXFIFO_EMPTY 0x20
#define RGE_MCUCMD_IS_OOB 0x80
/* Flags for register RGE_CPLUSCMD */
#define RGE_CPLUSCMD_RXCSUM 0x0020
#define RGE_TX_NSEGS 32
#define RGE_TX_LIST_CNT 1024
#define RGE_RX_LIST_CNT 1024
#define RGE_ALIGN 256
#define RGE_TX_LIST_SZ (sizeof(struct rge_tx_desc) * RGE_TX_LIST_CNT)
#define RGE_RX_LIST_SZ (sizeof(struct rge_rx_desc) * RGE_RX_LIST_CNT)
#define RGE_NEXT_TX_DESC(x) (((x) + 1) % RGE_TX_LIST_CNT)
#define RGE_NEXT_RX_DESC(x) (((x) + 1) % RGE_RX_LIST_CNT)
#define RGE_ADDR_LO(y) ((uint64_t) (y) & 0xffffffff)
#define RGE_ADDR_HI(y) ((uint64_t) (y) >> 32)
#define RGE_ADV_2500TFDX 0x0080
#define RGE_ADV_5000TFDX 0x0100
#define RGE_ADV_10000TFDX 0x1000
/* Tx descriptor */
struct rge_tx_desc {
uint32_t rge_cmdsts;
uint32_t rge_extsts;
uint64_t rge_addr;
uint32_t reserved[4];
} __packed __aligned(16);
#define RGE_TDCMDSTS_COLL 0x000f0000
#define RGE_TDCMDSTS_EXCESSCOLL 0x00100000
#define RGE_TDCMDSTS_TXERR 0x00800000
#define RGE_TDCMDSTS_EOF 0x10000000
#define RGE_TDCMDSTS_SOF 0x20000000
#define RGE_TDCMDSTS_EOR 0x40000000
#define RGE_TDCMDSTS_OWN 0x80000000
#define RGE_TDEXTSTS_VTAG 0x00020000
#define RGE_TDEXTSTS_IPCSUM 0x20000000
#define RGE_TDEXTSTS_TCPCSUM 0x40000000
#define RGE_TDEXTSTS_UDPCSUM 0x80000000
/* Rx descriptor */
struct rge_rx_desc {
union {
struct {
uint32_t rsvd0;
uint32_t rsvd1;
} rx_qword0;
} lo_qword0;
union {
struct {
uint32_t rss;
uint16_t length;
uint16_t hdr_info;
} rx_qword1;
struct {
uint32_t rsvd2;
uint32_t rsvd3;
} rx_qword2;
} lo_qword1;
union {
uint64_t rge_addr;
struct {
uint64_t timestamp;
} rx_timestamp;
struct {
uint32_t rsvd4;
uint32_t rsvd5;
} rx_qword3;
} hi_qword0;
union {
struct {
uint32_t rge_extsts;
uint32_t rge_cmdsts;
} rx_qword4;
struct {
uint16_t rsvd6;
uint16_t rsvd7;
uint32_t rsvd8;
} rx_ptp;
} hi_qword1;
} __packed __aligned(16);
#define RGE_RDCMDSTS_RXERRSUM 0x00100000
#define RGE_RDCMDSTS_EOF 0x01000000
#define RGE_RDCMDSTS_SOF 0x02000000
#define RGE_RDCMDSTS_EOR 0x40000000
#define RGE_RDCMDSTS_OWN 0x80000000
#define RGE_RDCMDSTS_FRAGLEN 0x00003fff
#define RGE_RDEXTSTS_VTAG 0x00010000
#define RGE_RDEXTSTS_VLAN_MASK 0x0000ffff
#define RGE_RDEXTSTS_TCPCSUMERR 0x01000000
#define RGE_RDEXTSTS_UDPCSUMERR 0x02000000
#define RGE_RDEXTSTS_IPCSUMERR 0x04000000
#define RGE_RDEXTSTS_TCPPKT 0x10000000
#define RGE_RDEXTSTS_UDPPKT 0x20000000
#define RGE_RDEXTSTS_IPV4 0x40000000
#define RGE_RDEXTSTS_IPV6 0x80000000
/*
* @brief Statistics counter structure
*
* This is the layout of the hardware structure that
* is populated by the hardware when RGE_DTCCR_* is
* appropriately poked.
*/
struct rge_hw_mac_stats {
uint64_t rge_tx_ok;
uint64_t rge_rx_ok;
uint64_t rge_tx_er;
uint32_t rge_rx_er;
uint16_t rge_miss_pkt;
uint16_t rge_fae; /* frame align errors */
uint32_t rge_tx_1col; /* one collision */
uint32_t rge_tx_mcol; /* multple collisions */
uint64_t rge_rx_ok_phy; /* unicast */
uint64_t rge_rx_ok_brd; /* broadcasts */
uint32_t rge_rx_ok_mul; /* multicasts */
uint16_t rge_tx_abt;
uint16_t rge_tx_undrn;
/* extended */
uint64_t re_tx_octets;
uint64_t re_rx_octets;
uint64_t re_rx_multicast64;
uint64_t re_tx_unicast64;
uint64_t re_tx_broadcast64;
uint64_t re_tx_multicast64;
uint32_t re_tx_pause_on;
uint32_t re_tx_pause_off;
uint32_t re_tx_pause_all;
uint32_t re_tx_deferred;
uint32_t re_tx_late_collision;
uint32_t re_tx_all_collision;
uint32_t re_tx_aborted32;
uint32_t re_align_errors32;
uint32_t re_rx_frame_too_long;
uint32_t re_rx_runt;
uint32_t re_rx_pause_on;
uint32_t re_rx_pause_off;
uint32_t re_rx_pause_all;
uint32_t re_rx_unknown_opcode;
uint32_t re_rx_mac_error;
uint32_t re_tx_underrun32;
uint32_t re_rx_mac_missed;
uint32_t re_rx_tcam_dropped;
uint32_t re_tdu;
uint32_t re_rdu;
} __packed __aligned(sizeof(uint64_t));
#define RGE_STATS_BUF_SIZE sizeof(struct rge_hw_mac_stats)
#define RGE_STATS_ALIGNMENT 64
/* Ram version */
#define RGE_MAC_R25D_RCODE_VER 0x0027
#define RGE_MAC_R26_RCODE_VER 0x0033
#define RGE_MAC_R27_RCODE_VER 0x0036
#define RGE_MAC_R25_RCODE_VER 0x0b33
#define RGE_MAC_R25B_RCODE_VER 0x0b99
#define RGE_TIMEOUT 100
#define RGE_JUMBO_FRAMELEN 9216
#define RGE_JUMBO_MTU \
(RGE_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN - \
ETHER_VLAN_ENCAP_LEN)
#define RGE_TXCFG_CONFIG 0x03000700
#define RGE_RXCFG_CONFIG 0x41000700
#define RGE_RXCFG_CONFIG_8125B 0x41000c00
#define RGE_RXCFG_CONFIG_8125D 0x41200c00
#define RGE_RXCFG_CONFIG_8126 0x41200d00
#endif /* __IF_RGEREG_H__ */
+269
View File
@@ -0,0 +1,269 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019, 2020, 2025 Kevin Lo <kevlo@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: if_rgereg.h,v 1.15 2025/09/19 00:41:14 kevlo Exp $ */
#ifndef __IF_RGEVAR_H__
#define __IF_RGEVAR_H__
#define RGE_LOCK(sc) (mtx_lock(&sc->sc_mtx))
#define RGE_UNLOCK(sc) (mtx_unlock(&sc->sc_mtx))
#define RGE_ASSERT_LOCKED(sc) (mtx_assert(&sc->sc_mtx, MA_OWNED))
#define RGE_ASSERT_UNLOCKED(sc) (mtx_assert(&sc->sc_mtx, MA_NOTOWNED))
enum rge_mac_type {
MAC_UNKNOWN = 1,
MAC_R25,
MAC_R25B,
MAC_R25D,
MAC_R26,
MAC_R27
};
struct rge_drv_stats {
/* How many times if_transmit() was called */
uint64_t transmit_call_cnt;
/* Transmitted frame failed because the interface was stopped */
uint64_t transmit_stopped_cnt;
/* Transmitted frame failed because the TX queue is full */
uint64_t transmit_full_cnt;
/* How many transmit frames were queued for transmit */
uint64_t transmit_queued_cnt;
/* How many times the interrupt routine was called */
uint64_t intr_cnt;
/* How many times SYSTEM_ERR was set, requiring a hardware reset */
uint64_t intr_system_err_cnt;
/* How many times rge_rxeof was called */
uint64_t rxeof_cnt;
/* How many times rge_txeof was called */
uint64_t txeof_cnt;
/* How many times the link state changed */
uint64_t link_state_change_cnt;
/* How many times tx_task was run */
uint64_t tx_task_cnt;
/* Count of frames passed up into if_input() */
uint64_t recv_input_cnt;
/*
* For now - driver doesn't support multi descriptor
* RX frames; so count if it happens so it'll be noticed.
*/
uint64_t rx_desc_err_multidesc;
/*
* Number of TX watchdog timeouts.
*/
uint64_t tx_watchdog_timeout_cnt;
uint64_t tx_encap_cnt;
uint64_t tx_encap_refrag_cnt;
uint64_t tx_encap_err_toofrag;
uint64_t tx_offload_ip_csum_set;
uint64_t tx_offload_tcp_csum_set;
uint64_t tx_offload_udp_csum_set;
uint64_t tx_offload_vlan_tag_set;
uint64_t rx_ether_csum_err;
uint64_t rx_desc_jumbo_frag;
uint64_t rx_offload_vlan_tag;
uint64_t rx_offload_csum_ipv4_exists;
uint64_t rx_offload_csum_ipv4_valid;
uint64_t rx_offload_csum_tcp_exists;
uint64_t rx_offload_csum_tcp_valid;
uint64_t rx_offload_csum_udp_exists;
uint64_t rx_offload_csum_udp_valid;
};
struct rge_txq {
struct mbuf *txq_mbuf;
bus_dmamap_t txq_dmamap;
int txq_descidx;
};
struct rge_rxq {
struct mbuf *rxq_mbuf;
bus_dmamap_t rxq_dmamap;
};
struct rge_tx {
struct rge_txq rge_txq[RGE_TX_LIST_CNT];
int rge_txq_prodidx;
int rge_txq_considx;
bus_addr_t rge_tx_list_paddr;
bus_dmamap_t rge_tx_list_map;
struct rge_tx_desc *rge_tx_list;
};
struct rge_rx {
struct rge_rxq rge_rxq[RGE_RX_LIST_CNT];
int rge_rxq_prodidx;
int rge_rxq_considx;
// struct if_rxring rge_rx_ring;
bus_addr_t rge_rx_list_paddr;
bus_dmamap_t rge_rx_list_map;
struct rge_rx_desc *rge_rx_list;
struct mbuf *rge_head;
struct mbuf **rge_tail;
};
struct rge_queues {
struct rge_softc *q_sc;
void *q_ihc;
int q_index;
char q_name[16];
// pci_intr_handle_t q_ih;
struct rge_tx q_tx;
struct rge_rx q_rx;
};
struct rge_mac_stats {
bus_addr_t paddr;
bus_dmamap_t map;
/* NIC dma buffer, NIC order */
struct rge_hw_mac_stats *stats;
/* Local copy for retrieval, host order */
struct rge_hw_mac_stats lcl_stats;
};
struct rge_softc {
device_t sc_dev;
if_t sc_ifp; /* Ethernet common data */
bool sc_ether_attached;
struct mtx sc_mtx;
struct resource *sc_irq[RGE_MSI_MESSAGES];
void *sc_ih[RGE_MSI_MESSAGES];
uint32_t sc_expcap; /* PCe exp cap */
struct resource *sc_bres; /* bus space MMIO/IOPORT resource */
bus_space_handle_t rge_bhandle; /* bus space handle */
bus_space_tag_t rge_btag; /* bus space tag */
bus_size_t rge_bsize;
bus_dma_tag_t sc_dmat;
bus_dma_tag_t sc_dmat_tx_desc;
bus_dma_tag_t sc_dmat_tx_buf;
bus_dma_tag_t sc_dmat_rx_desc;
bus_dma_tag_t sc_dmat_rx_buf;
bus_dma_tag_t sc_dmat_stats_buf;
// pci_chipset_tag_t sc_pc;
// pcitag_t sc_tag;
struct ifmedia sc_media; /* media info */
enum rge_mac_type rge_type;
struct rge_queues *sc_queues;
unsigned int sc_nqueues;
bool sc_detaching;
bool sc_stopped;
bool sc_suspended;
/* Note: these likely should be per-TXQ */
struct mbufq sc_txq;
struct taskqueue * sc_tq;
char sc_tq_name[32];
char sc_tq_thr_name[32];
struct task sc_tx_task;
struct callout sc_timeout; /* 1 second tick */
uint64_t rge_mcodever;
uint16_t rge_rcodever;
uint32_t rge_flags;
#define RGE_FLAG_MSI 0x00000001
#define RGE_FLAG_PCIE 0x00000002
uint32_t rge_intrs;
int rge_timerintr;
#define RGE_IMTYPE_NONE 0
#define RGE_IMTYPE_SIM 1
int sc_watchdog;
uint32_t sc_debug;
struct rge_drv_stats sc_drv_stats;
struct rge_mac_stats sc_mac_stats;
};
/*
* Register space access macros.
*/
#define RGE_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->rge_btag, sc->rge_bhandle, reg, val)
#define RGE_WRITE_2(sc, reg, val) \
bus_space_write_2(sc->rge_btag, sc->rge_bhandle, reg, val)
#define RGE_WRITE_1(sc, reg, val) \
bus_space_write_1(sc->rge_btag, sc->rge_bhandle, reg, val)
#define RGE_WRITE_BARRIER_4(sc, reg) \
bus_space_barrier(sc->rge_btag, sc->rge_bhandle, reg, 4, \
BUS_SPACE_BARRIER_WRITE)
#define RGE_READ_BARRIER_4(sc, reg) \
bus_space_barrier(sc->rge_btag, sc->rge_bhandle, reg, 4, \
BUS_SPACE_BARRIER_READ)
#define RGE_READ_4(sc, reg) \
bus_space_read_4(sc->rge_btag, sc->rge_bhandle, reg)
#define RGE_READ_2(sc, reg) \
bus_space_read_2(sc->rge_btag, sc->rge_bhandle, reg)
#define RGE_READ_1(sc, reg) \
bus_space_read_1(sc->rge_btag, sc->rge_bhandle, reg)
#define RGE_SETBIT_4(sc, reg, val) \
RGE_WRITE_4(sc, reg, RGE_READ_4(sc, reg) | (val))
#define RGE_SETBIT_2(sc, reg, val) \
RGE_WRITE_2(sc, reg, RGE_READ_2(sc, reg) | (val))
#define RGE_SETBIT_1(sc, reg, val) \
RGE_WRITE_1(sc, reg, RGE_READ_1(sc, reg) | (val))
#define RGE_CLRBIT_4(sc, reg, val) \
RGE_WRITE_4(sc, reg, RGE_READ_4(sc, reg) & ~(val))
#define RGE_CLRBIT_2(sc, reg, val) \
RGE_WRITE_2(sc, reg, RGE_READ_2(sc, reg) & ~(val))
#define RGE_CLRBIT_1(sc, reg, val) \
RGE_WRITE_1(sc, reg, RGE_READ_1(sc, reg) & ~(val))
#define RGE_EPHY_SETBIT(sc, reg, val) \
rge_write_ephy(sc, reg, rge_read_ephy(sc, reg) | (val))
#define RGE_EPHY_CLRBIT(sc, reg, val) \
rge_write_ephy(sc, reg, rge_read_ephy(sc, reg) & ~(val))
#define RGE_PHY_SETBIT(sc, reg, val) \
rge_write_phy_ocp(sc, reg, rge_read_phy_ocp(sc, reg) | (val))
#define RGE_PHY_CLRBIT(sc, reg, val) \
rge_write_phy_ocp(sc, reg, rge_read_phy_ocp(sc, reg) & ~(val))
#define RGE_MAC_SETBIT(sc, reg, val) \
rge_write_mac_ocp(sc, reg, rge_read_mac_ocp(sc, reg) | (val))
#define RGE_MAC_CLRBIT(sc, reg, val) \
rge_write_mac_ocp(sc, reg, rge_read_mac_ocp(sc, reg) & ~(val))
#endif /* __IF_RGEVAR_H__ */
+1
View File
@@ -348,6 +348,7 @@ SUBDIR= \
${_rdrand_rng} \
${_rdseed_rng} \
re \
rge \
rl \
${_rockchip} \
rtsx \
+7
View File
@@ -0,0 +1,7 @@
.PATH: ${SRCTOP}/sys/dev/rge
KMOD= if_rge
SRCS= if_rge.c if_rge_hw.c if_rge_stats.c if_rge_sysctl.c
SRCS+= device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>