From 710839378ce502ebb62a6739a9ede7f7184c13c2 Mon Sep 17 00:00:00 2001 From: stsp Date: Mon, 6 May 2024 09:54:38 +0000 Subject: [PATCH] Add support for Tx checksum offloading to dwqe(4). Also improve our macros documenting Tx descriptor formats. Tested: RK3568: kettenis, jmatthew Elkhart Lake: stsp ok kettenis@, jmatthew@ --- sys/dev/ic/dwqe.c | 36 ++++++++++++++++++++++++++++++++++-- sys/dev/ic/dwqereg.h | 31 +++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/sys/dev/ic/dwqe.c b/sys/dev/ic/dwqe.c index b683535744e..04cdc69851a 100644 --- a/sys/dev/ic/dwqe.c +++ b/sys/dev/ic/dwqe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dwqe.c,v 1.20 2024/05/03 13:02:18 stsp Exp $ */ +/* $OpenBSD: dwqe.c,v 1.21 2024/05/06 09:54:38 stsp Exp $ */ /* * Copyright (c) 2008, 2019 Mark Kettenis * Copyright (c) 2017, 2022 Patrick Wildt @@ -93,6 +93,12 @@ void dwqe_dmamem_free(struct dwqe_softc *, struct dwqe_dmamem *); struct mbuf *dwqe_alloc_mbuf(struct dwqe_softc *, bus_dmamap_t); void dwqe_fill_rx_ring(struct dwqe_softc *); +int +dwqe_have_tx_csum_offload(struct dwqe_softc *sc) +{ + return (sc->sc_hw_feature[0] & GMAC_MAC_HW_FEATURE0_TXCOESEL); +} + int dwqe_attach(struct dwqe_softc *sc) { @@ -121,6 +127,11 @@ dwqe_attach(struct dwqe_softc *sc) bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_capabilities = IFCAP_VLAN_MTU; + if (dwqe_have_tx_csum_offload(sc)) { + ifp->if_capabilities |= (IFCAP_CSUM_IPv4 | + IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 | + IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6); + } sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = dwqe_mii_readreg; @@ -1077,6 +1088,25 @@ dwqe_iff(struct dwqe_softc *sc) dwqe_write(sc, GMAC_MAC_PACKET_FILTER, reg); } +void +dwqe_tx_csum(struct dwqe_softc *sc, struct mbuf *m, struct dwqe_desc *txd) +{ + if (!dwqe_have_tx_csum_offload(sc)) + return; + + /* Checksum flags are valid only on first descriptor. */ + if ((txd->sd_tdes3 & TDES3_FS) == 0) + return; + + /* TSO and Tx checksum offloading are incompatible. */ + if (txd->sd_tdes3 & TDES3_TSO_EN) + return; + + if (m->m_pkthdr.csum_flags & (M_IPV4_CSUM_OUT | + M_TCP_CSUM_OUT | M_UDP_CSUM_OUT)) + txd->sd_tdes3 |= TDES3_CSUM_IPHDR_PAYLOAD_PSEUDOHDR; +} + int dwqe_encap(struct dwqe_softc *sc, struct mbuf *m, int *idx, int *used) { @@ -1107,8 +1137,10 @@ dwqe_encap(struct dwqe_softc *sc, struct mbuf *m, int *idx, int *used) txd->sd_tdes1 = (uint32_t)(map->dm_segs[i].ds_addr >> 32); txd->sd_tdes2 = map->dm_segs[i].ds_len; txd->sd_tdes3 = m->m_pkthdr.len; - if (i == 0) + if (i == 0) { txd->sd_tdes3 |= TDES3_FS; + dwqe_tx_csum(sc, m, txd); + } if (i == (map->dm_nsegs - 1)) { txd->sd_tdes2 |= TDES2_IC; txd->sd_tdes3 |= TDES3_LS; diff --git a/sys/dev/ic/dwqereg.h b/sys/dev/ic/dwqereg.h index 7db8b2a40d5..ab479d54c13 100644 --- a/sys/dev/ic/dwqereg.h +++ b/sys/dev/ic/dwqereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dwqereg.h,v 1.8 2024/05/03 13:02:18 stsp Exp $ */ +/* $OpenBSD: dwqereg.h,v 1.9 2024/05/06 09:54:38 stsp Exp $ */ /* * Copyright (c) 2008, 2019 Mark Kettenis * Copyright (c) 2017, 2022 Patrick Wildt @@ -230,14 +230,37 @@ struct dwqe_desc { uint32_t sd_tdes3; }; -/* Tx bits */ +/* Tx bits (read format; host to device) */ +#define TDES2_HDR_LEN 0x000003ff /* if TSO is enabled */ +#define TDES2_BUF1_LEN 0x00003fff /* if TSO is disabled */ +#define TDES2_VLAN_TIR 0x0000c000 +#define TDES2_NO_VLAN_TAGGING (0x0 << 14) +#define TDES2_VLAN_TAG_STRIP (0x1 << 14) +#define TDES2_VLAN_TAG_INSERT (0x2 << 14) +#define TDES2_VLAN_TAG_REPLACE (0x3 << 14) +#define TDES2_BUF2_LEN 0x3fff0000 +#define TDES2_TX_TIMESTAMP_EN (1 << 30) /* if TSO is disabled */ +#define TDES2_TSO_EXTMEM_DIS (1 << 30) /* if TSO is enabled */ #define TDES2_IC (1U << 31) -#define TDES3_ES (1 << 15) -#define TDES3_DE (1 << 23) +#define TDES3_TCP_PAYLOAD_LEN 0x0003ffff /* if TSO is enabled */ +#define TDES3_FRAME_LEN 0x00007fff /* if TSO is disabled */ +#define TDES3_CIC 0x00030000 /* if TSO is disabled */ +#define TDES3_CSUM_DISABLE (0x0 << 16) +#define TDES3_CSUM_IPHDR (0x1 << 16) +#define TDES3_CSUM_IPHDR_PAYLOAD (0x2 << 16) +#define TDES3_CSUM_IPHDR_PAYLOAD_PSEUDOHDR (0x3 << 16) +#define TDES3_TSO_EN (1 << 18) #define TDES3_LS (1 << 28) #define TDES3_FS (1 << 29) #define TDES3_OWN (1U << 31) +/* Tx bits (writeback format; device to host) */ +#define TDES3_ES (1 << 15) +#define TDES3_DE (1 << 23) +/* Bit 28 is the LS bit, as in "read" format. */ +/* Bit 29 is the FS bit, as in "read" format. */ +/* Bit 31 is the OWN bit, as in "read" format. */ + /* Rx bits (read format; host to device) */ #define RDES3_BUF1V (1 << 24) #define RDES3_BUF2V (1 << 25) -- 2.20.1