From: stsp Date: Fri, 3 May 2024 13:02:18 +0000 (+0000) Subject: Add support for Rx checksum offloading to dwqe(4). X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a72369d88018601295f2c3f986b88ba3b4415108;p=openbsd Add support for Rx checksum offloading to dwqe(4). Tested by uwe@ and myself on Elkhart Lake, and kettenis@ on RK3566. Joint work with uwe@ ok kettenis@ --- diff --git a/sys/dev/ic/dwqe.c b/sys/dev/ic/dwqe.c index 3e9f6569240..b683535744e 100644 --- a/sys/dev/ic/dwqe.c +++ b/sys/dev/ic/dwqe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dwqe.c,v 1.19 2024/04/25 08:51:37 jmatthew Exp $ */ +/* $OpenBSD: dwqe.c,v 1.20 2024/05/03 13:02:18 stsp Exp $ */ /* * Copyright (c) 2008, 2019 Mark Kettenis * Copyright (c) 2017, 2022 Patrick Wildt @@ -643,6 +643,66 @@ dwqe_tx_proc(struct dwqe_softc *sc) } } +int +dwqe_have_rx_csum_offload(struct dwqe_softc *sc) +{ + return (sc->sc_hw_feature[0] & GMAC_MAC_HW_FEATURE0_RXCOESEL); +} + +void +dwqe_rx_csum(struct dwqe_softc *sc, struct mbuf *m, struct dwqe_desc *rxd) +{ + uint16_t csum_flags = 0; + + /* + * Checksum offload must be supported, the Last-Descriptor bit + * must be set, RDES1 must be valid, and checksumming must not + * have been bypassed (happens for unknown packet types), and + * an IP header must have been detected. + */ + if (!dwqe_have_rx_csum_offload(sc) || + (rxd->sd_tdes3 & RDES3_LD) == 0 || + (rxd->sd_tdes3 & RDES3_RDES1_VALID) == 0 || + (rxd->sd_tdes1 & RDES1_IP_CSUM_BYPASS) || + (rxd->sd_tdes1 & (RDES1_IPV4_HDR | RDES1_IPV6_HDR)) == 0) + return; + + /* If the IP header checksum is invalid then the payload is ignored. */ + if (rxd->sd_tdes1 & RDES1_IP_HDR_ERROR) { + if (rxd->sd_tdes1 & RDES1_IPV4_HDR) + csum_flags |= M_IPV4_CSUM_IN_BAD; + } else { + if (rxd->sd_tdes1 & RDES1_IPV4_HDR) + csum_flags |= M_IPV4_CSUM_IN_OK; + + /* Detect payload type and corresponding checksum errors. */ + switch (rxd->sd_tdes1 & RDES1_IP_PAYLOAD_TYPE) { + case RDES1_IP_PAYLOAD_UDP: + if (rxd->sd_tdes1 & RDES1_IP_PAYLOAD_ERROR) + csum_flags |= M_UDP_CSUM_IN_BAD; + else + csum_flags |= M_UDP_CSUM_IN_OK; + break; + case RDES1_IP_PAYLOAD_TCP: + if (rxd->sd_tdes1 & RDES1_IP_PAYLOAD_ERROR) + csum_flags |= M_TCP_CSUM_IN_BAD; + else + csum_flags |= M_TCP_CSUM_IN_OK; + break; + case RDES1_IP_PAYLOAD_ICMP: + if (rxd->sd_tdes1 & RDES1_IP_PAYLOAD_ERROR) + csum_flags |= M_ICMP_CSUM_IN_BAD; + else + csum_flags |= M_ICMP_CSUM_IN_OK; + break; + default: + break; + } + } + + m->m_pkthdr.csum_flags |= csum_flags; +} + void dwqe_rx_proc(struct dwqe_softc *sc) { @@ -691,6 +751,7 @@ dwqe_rx_proc(struct dwqe_softc *sc) m->m_pkthdr.len = m->m_len = len; + dwqe_rx_csum(sc, m, rxd); ml_enqueue(&ml, m); } @@ -866,6 +927,12 @@ dwqe_up(struct dwqe_softc *sc) if (!sc->sc_fixed_link) timeout_add_sec(&sc->sc_phy_tick, 1); + + if (dwqe_have_rx_csum_offload(sc)) { + reg = dwqe_read(sc, GMAC_MAC_CONF); + reg |= GMAC_MAC_CONF_IPC; + dwqe_write(sc, GMAC_MAC_CONF, reg); + } } void diff --git a/sys/dev/ic/dwqereg.h b/sys/dev/ic/dwqereg.h index 6f1753b34d3..7db8b2a40d5 100644 --- a/sys/dev/ic/dwqereg.h +++ b/sys/dev/ic/dwqereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dwqereg.h,v 1.7 2024/04/25 11:37:39 stsp Exp $ */ +/* $OpenBSD: dwqereg.h,v 1.8 2024/05/03 13:02:18 stsp Exp $ */ /* * Copyright (c) 2008, 2019 Mark Kettenis * Copyright (c) 2017, 2022 Patrick Wildt @@ -17,6 +17,7 @@ */ #define GMAC_MAC_CONF 0x0000 +#define GMAC_MAC_CONF_IPC (1 << 27) #define GMAC_MAC_CONF_CST (1 << 21) #define GMAC_MAC_CONF_ACS (1 << 20) #define GMAC_MAC_CONF_BE (1 << 18) @@ -61,6 +62,8 @@ #define GMAC_VERSION 0x0110 #define GMAC_VERSION_SNPS_MASK 0xff #define GMAC_MAC_HW_FEATURE(x) (0x011c + (x) * 0x4) +#define GMAC_MAC_HW_FEATURE0_TXCOESEL (1 << 14) +#define GMAC_MAC_HW_FEATURE0_RXCOESEL (1 << 16) #define GMAC_MAC_HW_FEATURE1_TXFIFOSIZE(x) (((x) >> 6) & 0x1f) #define GMAC_MAC_HW_FEATURE1_RXFIFOSIZE(x) (((x) >> 0) & 0x1f) #define GMAC_MAC_MDIO_ADDR 0x0200