-/* $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 <kettenis@openbsd.org>
* Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
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)
{
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;
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)
{
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;
-/* $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 <kettenis@openbsd.org>
* Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
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)