Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 03 May 2026 19:11:58 +0000
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 6464974c5a56 - main - dpaa: Enable checksum offloading for IPv4 and IPv6
Message-ID:  <69f79dfe.3cac1.2033c7a2@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by jhibbits:

URL: https://cgit.FreeBSD.org/src/commit/?id=6464974c5a56a9f899f8a673385711253f9fcbd0

commit 6464974c5a56a9f899f8a673385711253f9fcbd0
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2026-04-25 20:50:34 +0000
Commit:     Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2026-05-03 19:09:29 +0000

    dpaa: Enable checksum offloading for IPv4 and IPv6
    
    Enable the FMan hardware parser to take advantage of some offloading.
    This enables receive and transmit checksum offloading for both IPv4 and
    IPv6.
    
    Additional offloading capabilities the DPAA supports include:
    * vlan parsing
    * Transmit rate limiting
    * IEEE-1588 timestamps
    * Soft parsing for custom protocol checking
    * Congestion handling
---
 sys/dev/dpaa/dpaa_common.h | 30 +++++++++++++++
 sys/dev/dpaa/dpaa_eth.c    | 92 +++++++++++++++++++++++++++++++++++++++-------
 sys/dev/dpaa/fman.h        | 30 +++++++++++++++
 sys/dev/dpaa/fman_parser.h | 27 ++++++++++++++
 sys/dev/dpaa/fman_port.c   | 47 +++++++++++++++--------
 sys/dev/dpaa/if_memac.c    | 19 +++++++++-
 6 files changed, 216 insertions(+), 29 deletions(-)

diff --git a/sys/dev/dpaa/dpaa_common.h b/sys/dev/dpaa/dpaa_common.h
index 7c030f16bd6c..1d81d63877a4 100644
--- a/sys/dev/dpaa/dpaa_common.h
+++ b/sys/dev/dpaa/dpaa_common.h
@@ -26,6 +26,36 @@ struct dpaa_fd {
 
 #define	DPAA_FD_FORMAT_SHORT_MBSF	4
 
+#define	DPAA_FD_RX_STATUS_DCL4C		0x10000000
+#define	DPAA_FD_RX_STATUS_DME		0x01000000
+#define	DPAA_FD_RX_STATUS_IPRE_M	0x00300000
+#define	DPAA_FD_RX_STATUS_FPE		0x00080000
+#define	DPAA_FD_RX_STATUS_FSE		0x00040000
+#define	DPAA_FD_RX_STATUS_DIS		0x00020000
+#define	DPAA_FD_RX_STATUS_EOF		0x00008000
+#define	DPAA_FD_RX_STATUS_NSS		0x00004000
+#define	DPAA_FD_RX_STATUS_KSO		0x00002000
+#define	DPAA_FD_RX_STATUS_FCL_M		0x00000c00
+#define	DPAA_FD_RX_STATUS_IPP		0x00000200
+#define	DPAA_FD_RX_STATUS_FLM		0x00000100
+#define	DPAA_FD_RX_STATUS_PTE		0x00000080
+#define	DPAA_FD_RX_STATUS_ISP		0x00000040
+#define	DPAA_FD_RX_STATUS_PHE		0x00000020
+#define	DPAA_FD_RX_STATUS_FRDR		0x00000010
+#define	DPAA_FD_RX_STATUS_BLE		0x00000008
+#define	DPAA_FD_RX_STATUS_L4CV		0x00000004
+#define	DPAA_FD_RX_STATUS_IPR		0x00000001
+
+#define	DPAA_FD_TX_CMD_RPD		0x40000000
+#define	DPAA_FD_TX_CMD_DTC		0x10000000
+#define	DPAA_FD_TX_STATUS_UFD		0x04000000
+#define	DPAA_FD_TX_STATUS_LGE		0x02000000
+#define	DPAA_FD_TX_STATUS_DME		0x01000000
+
+/* Most of the above are error flags, but some aren't */
+#define	DPAA_FD_CMD_STAT_ERR_M		0x010ce3e8
+#define	DPAA_FD_TX_STAT_ERR_M		0x03000000
+
 #define	DPAA_FD_GET_ADDR(fd)	((void *)PHYS_TO_DMAP(fd->addr))
 
 struct dpaa_sgte {
diff --git a/sys/dev/dpaa/dpaa_eth.c b/sys/dev/dpaa/dpaa_eth.c
index 6f86dfe5045f..95e2c57e014e 100644
--- a/sys/dev/dpaa/dpaa_eth.c
+++ b/sys/dev/dpaa/dpaa_eth.c
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2026 Justin Hibbits
  * Copyright (c) 2012 Semihalf.
  * All rights reserved.
  *
@@ -43,6 +44,8 @@
 #include <net/if_media.h>
 #include <net/if_types.h>
 #include <net/if_arp.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
 
 #include <dev/mii/mii.h>
 #include <dev/mii/miivar.h>
@@ -56,6 +59,7 @@
 #include "dpaa_common.h"
 #include "dpaa_eth.h"
 #include "fman.h"
+#include "fman_parser.h"
 #include "fman_port.h"
 #include "fman_if.h"
 #include "fman_port_if.h"
@@ -78,6 +82,7 @@
 
 struct dpaa_eth_frame_info {
 	struct mbuf			*fi_mbuf;
+	struct fman_internal_context	fi_ic;
 	struct dpaa_sgte		fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY];
 };
 
@@ -132,7 +137,7 @@ dpaa_eth_fi_alloc(struct dpaa_eth_softc *sc)
 {
 	struct dpaa_eth_frame_info *fi;
 
-	fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT);
+	fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT | M_ZERO);
 
 	return (fi);
 }
@@ -318,26 +323,48 @@ dpaa_eth_fq_mext_free(struct mbuf *m)
 		dpaa_eth_pool_rx_put_buffer(sc, buffer, NULL);
 }
 
+static int
+dpaa_eth_update_csum_flags(struct qman_fd *frame,
+    struct fman_parse_result *prs, struct mbuf *m)
+{
+	uint16_t l3r = be16toh(prs->l3r);
+
+	/* TODO: nested protocols? */
+	if ((l3r & L3R_FIRST_IP_M) != 0) {
+		m->m_pkthdr.csum_flags |= CSUM_L3_CALC;
+		if ((l3r & L3R_FIRST_ERROR) == 0)
+			m->m_pkthdr.csum_flags |= CSUM_L3_VALID;
+	}
+	if (frame->cmd_stat & DPAA_FD_RX_STATUS_L4CV) {
+		m->m_pkthdr.csum_flags |= CSUM_L4_CALC;
+		m->m_pkthdr.csum_data = 0xffff;
+		if ((prs->l4r & L4R_TYPE_M) != 0 &&
+		    (prs->l4r & L4R_ERR) == 0)
+			m->m_pkthdr.csum_flags |= CSUM_L4_VALID;
+	}
+
+	return (0);
+}
+
 static int
 dpaa_eth_fq_rx_callback(device_t portal, struct qman_fq *fq,
     struct qman_fd *frame, void *app)
 {
 	struct dpaa_eth_softc *sc;
 	struct mbuf *m;
+	struct fman_internal_context *frame_ic;
 	void *frame_va;
 
 	m = NULL;
 	sc = app;
 
 	frame_va = DPAA_FD_GET_ADDR(frame);
+	frame_ic = frame_va;	/* internal context at head of the frame */
 	KASSERT(frame->format == 0,
 	    ("%s(): Got unsupported frame format 0x%02X!", __func__,
 	    frame->format));
 
-	KASSERT(frame->offset == 0,
-	    ("%s(): Only offset 0 is supported!", __func__));
-
-	if (frame->cmd_stat != 0) {
+	if ((frame->cmd_stat & DPAA_FD_CMD_STAT_ERR_M) != 0) {
 		device_printf(sc->sc_dev, "RX error: 0x%08X\n",
 		    frame->cmd_stat);
 		goto err;
@@ -347,8 +374,11 @@ dpaa_eth_fq_rx_callback(device_t portal, struct qman_fq *fq,
 	if (m == NULL)
 		goto err;
 
-	m_extadd(m, frame_va, MCLBYTES, dpaa_eth_fq_mext_free, frame_va, sc, 0,
-	    EXT_NET_DRV);
+	m_extadd(m, (char *)frame_va + frame->offset, frame->length,
+	    dpaa_eth_fq_mext_free, frame_va, sc, 0, EXT_NET_DRV);
+
+	if (if_getcapenable(sc->sc_ifnet) & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6))
+		dpaa_eth_update_csum_flags(frame, &frame_ic->prs, m);
 
 	m->m_pkthdr.rcvif = sc->sc_ifnet;
 	m->m_len = frame->length;
@@ -377,7 +407,7 @@ dpaa_eth_fq_tx_confirm_callback(device_t portal, struct qman_fq *fq,
 
 	sc = app;
 
-	if (frame->cmd_stat != 0)
+	if ((frame->cmd_stat & DPAA_FD_TX_STAT_ERR_M) != 0)
 		device_printf(sc->sc_dev, "TX error: 0x%08X\n",
 		    frame->cmd_stat);
 
@@ -385,7 +415,7 @@ dpaa_eth_fq_tx_confirm_callback(device_t portal, struct qman_fq *fq,
 	 * We are storing struct dpaa_eth_frame_info in first entry
 	 * of scatter-gather table.
 	 */
-	sgt0 = (struct dpaa_sgte *)PHYS_TO_DMAP(frame->addr);
+	sgt0 = (struct dpaa_sgte *)PHYS_TO_DMAP(frame->addr + frame->offset);
 	fi = (struct dpaa_eth_frame_info *)PHYS_TO_DMAP(sgt0->addr);
 
 	/* Free transmitted frame */
@@ -517,6 +547,42 @@ dpaa_eth_fq_tx_init(struct dpaa_eth_softc *sc)
 }
 /** @} */
 
+/* Returns the cmd_stat field for the frame descriptor */
+static uint32_t
+dpaa_eth_tx_add_csum(struct dpaa_eth_frame_info *fi)
+{
+	struct mbuf *m = fi->fi_mbuf;
+	struct fman_parse_result *prs = &fi->fi_ic.prs;
+	uint32_t csum_flags = m->m_pkthdr.csum_flags;
+	uint8_t ether_size = ETHER_HDR_LEN;
+
+	if ((csum_flags & CSUM_FLAGS_TX) == 0)
+		return (0);
+
+	if (m->m_flags & M_VLANTAG)
+		ether_size += ETHER_VLAN_ENCAP_LEN;
+	if (csum_flags & CSUM_IP)
+		prs->l3r = L3R_FIRST_IPV4;
+	if (csum_flags & CSUM_IP_UDP) {
+		prs->l4r = L4R_TYPE_UDP;
+		prs->l4_off = ether_size + sizeof(struct ip);
+	} else if (csum_flags & CSUM_IP_TCP) {
+		prs->l4r = L4R_TYPE_TCP;
+		prs->l4_off = ether_size + sizeof(struct ip);
+	} else if (csum_flags & CSUM_IP6_UDP) {
+		prs->l3r = L3R_FIRST_IPV6;
+		prs->l4r = L4R_TYPE_UDP;
+		prs->l4_off = ether_size + sizeof(struct ip6_hdr);
+	} else if (csum_flags & CSUM_IP6_TCP) {
+		prs->l3r = L3R_FIRST_IPV6;
+		prs->l4r = L4R_TYPE_TCP;
+		prs->l4_off = ether_size + sizeof(struct ip6_hdr);
+	}
+
+	prs->ip_off[0] = ether_size;
+
+	return (DPAA_FD_TX_CMD_RPD | DPAA_FD_TX_CMD_DTC);
+}
 
 /**
  * @group dTSEC IFnet routines.
@@ -573,7 +639,6 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
 			 * First entry in scatter-gather table is used to keep
 			 * pointer to frame info structure.
 			 */
-			memset(&fi->fi_sgt[i], 0, sizeof(fi->fi_sgt[i]));
 			fi->fi_sgt[i].addr = pmap_kextract((vm_offset_t)fi);
 			i++;
 
@@ -613,15 +678,16 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
 
 		fi->fi_sgt[i - 1].final = 1;
 
-		fd.addr = pmap_kextract((vm_offset_t)fi->fi_sgt);
+		fd.addr = pmap_kextract((vm_offset_t)&fi->fi_ic);
 		fd.length = psize;
 		fd.format = DPAA_FD_FORMAT_SHORT_MBSF;
 
 		fd.liodn = 0;
 		fd.bpid = 0;
 		fd.eliodn = 0;
-		fd.offset = 0;
-		fd.cmd_stat = 0;
+		fd.offset = offsetof(struct dpaa_eth_frame_info, fi_sgt) -
+		    offsetof(struct dpaa_eth_frame_info, fi_ic);
+		fd.cmd_stat = dpaa_eth_tx_add_csum(fi);
 
 		DPAA_ETH_UNLOCK(sc);
 		if (qman_fq_enqueue(sc->sc_tx_fq, &fd) != 0) {
diff --git a/sys/dev/dpaa/fman.h b/sys/dev/dpaa/fman.h
index 68b0b7d1900e..a0af1b36b5a3 100644
--- a/sys/dev/dpaa/fman.h
+++ b/sys/dev/dpaa/fman.h
@@ -105,6 +105,36 @@ struct fman_port_init_params {
 	uint16_t liodn;
 };
 
+struct fman_parse_result {
+	uint8_t lpid;
+	uint8_t shimr;
+	uint16_t l2r;
+	uint16_t l3r;
+	uint8_t l4r;
+	uint8_t cpid;
+	uint16_t nxthdr;
+	uint16_t cksum;
+	uint32_t lcv;
+	uint8_t shim_off[2];
+	uint8_t ip_pid_off;
+	uint8_t eth_off;
+	uint8_t llc_snap_off;
+	uint8_t vlan_tic_off[2];
+	uint8_t last_e_type_off;
+	uint8_t pppoe_off;
+	uint8_t mpls_off[2];
+	uint8_t ip_off[2];
+	uint8_t gre_off;
+	uint8_t l4_off;
+	uint8_t nxthdr_off;
+};
+
+struct fman_internal_context {
+	struct fman_parse_result prs;
+	uint64_t timestamp;
+	uint64_t hash;
+};
+
 /**
  * @group FMan bus interface.
  * @{
diff --git a/sys/dev/dpaa/fman_parser.h b/sys/dev/dpaa/fman_parser.h
new file mode 100644
index 000000000000..65dc5bcabe69
--- /dev/null
+++ b/sys/dev/dpaa/fman_parser.h
@@ -0,0 +1,27 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Justin Hibbits
+ */
+
+#ifndef	DPAA_FMAN_PARSER_H
+#define	DPAA_FMAN_PARSER_H
+
+#define	FMAN_PARSE_RESULT_OFF	32
+#define	L3R_FIRST_IPV4		0x8000
+#define	L3R_FIRST_IPV6		0x4000
+#define	L3R_FIRST_IP_M		(L3R_FIRST_IPV4 | L3R_FIRST_IPV6)
+#define	L3R_LAST_IPV4		0x8000
+#define	L3R_LAST_IPV6		0x4000
+#define	L3R_LAST_IP_M		(L3R_LAST_IPV4 | L3R_LAST_IPV6)
+#define	L3R_FIRST_ERROR		0x2000
+#define	L3R_LAST_ERROR		0x0080
+#define	L4R_TYPE_M		0xe0
+#define	L4R_TYPE_TCP		0x20
+#define	L4R_TYPE_UDP		0x40
+#define	L4R_TYPE_IPSEC		0x60
+#define	L4R_TYPE_SCTP		0x80
+#define	L4R_DCCP		0xa0
+#define	L4R_ERR			0x10
+
+#endif
diff --git a/sys/dev/dpaa/fman_port.c b/sys/dev/dpaa/fman_port.c
index 3e6f2b7dca30..548557edc7f8 100644
--- a/sys/dev/dpaa/fman_port.c
+++ b/sys/dev/dpaa/fman_port.c
@@ -11,6 +11,7 @@
 #include <dev/ofw/ofw_bus_subr.h>
 #include <machine/bus.h>
 #include "fman.h"
+#include "fman_parser.h"
 #include "fman_port.h"
 #include "fman_if.h"
 #include "fman_port_if.h"
@@ -73,9 +74,17 @@ struct fman_port_softc {
 #define	FMBM_RFP		0x00c
 #define	FMBM_RFED		0x010
 #define	  BMI_RX_FRAME_END_CUT_SHIFT	16
-#define	FMBM_RICP		0x014
+#define	FMBM_RICP		0x014	/* Counts are units of 16 bytes */
+#define	  RICP_ICEOF_M		  0x001f0000
+#define	  RICP_ICEOF_S		  16
+#define	  RICP_ICIOF_M		  0x00000f00
+#define	  RICP_ICIOF_S		  8
+#define	  RICP_ICSZ_S		  0x0000001f
 #define	FMBM_RIM		0x018
 #define	FMBM_REBM		0x01c
+#define	  REBM_BSM_M		  0x01ff0000
+#define	  REBM_BSM_S		  16
+#define	  REBM_BEM_M		  0x000001ff
 #define	FMBM_RFNE		0x020
 #define	FMBM_RFCA		0x024
 #define	  RFCA_OR		  0x80000000
@@ -105,6 +114,12 @@ struct fman_port_softc {
 #define	FMBM_TFP		0x00c
 #define	  BMI_FIFO_PIPELINE_DEPTH_SHIFT	12
 #define	FMBM_TFED	0x010
+#define	FMBM_TICP	0x014
+#define	  TICP_ICEOF_M		  0x001f0000
+#define	  TICP_ICEOF_S		  16
+#define	  TICP_ICIOF_M		  0x00000f00
+#define	  TICP_ICIOF_S		  8
+#define	  TICP_ICSZ_S		  0x0000001f
 #define	FMBM_TFDNE	0x018
 #define	FMBM_TFCA	0x01c
 #define	  TFCA_MR_DEF	  0
@@ -385,6 +400,7 @@ fman_port_config(device_t dev, struct fman_port_params *params)
 static int
 fman_port_init_bmi_rx(struct fman_port_softc *sc)
 {
+	uint32_t reg;
 
 	/* TODO: Sort the buffer pool list.  */
 	/* TODO: Backup pools */
@@ -407,7 +423,7 @@ fman_port_init_bmi_rx(struct fman_port_softc *sc)
 	    RFCA_OR | RFCA_SYNC_REQ | RFCA_MR_DEF);
 
 	bus_write_4(sc->sc_mem, FMBM_RFPNE,
-	    NIA_ENG_HWK);
+	    NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
 	bus_write_4(sc->sc_mem, FMBM_RFENE,
 	    NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
 
@@ -424,11 +440,14 @@ fman_port_init_bmi_rx(struct fman_port_softc *sc)
 		bus_write_4(sc->sc_mem, FMBM_RFED,
 		    DEFAULT_RX_CUT_END_BYTES << BMI_RX_FRAME_END_CUT_SHIFT);
 
-	/* No internal context */
-	bus_write_4(sc->sc_mem, FMBM_RICP, 0);
+	/* Insert internal context ahead of the frame */
+	reg = sizeof(struct fman_internal_context) << REBM_BSM_S;
+	bus_write_4(sc->sc_mem, FMBM_REBM, reg);
+	reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << RICP_ICIOF_S;
+	reg |= howmany(sizeof(struct fman_internal_context), 0x10);
+	bus_write_4(sc->sc_mem, FMBM_RICP, reg);
 
-	/* TODO: Enable HW Parser. */
-	bus_write_4(sc->sc_mem, FMBM_RFNE, NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
+	bus_write_4(sc->sc_mem, FMBM_RFNE, NIA_ENG_HWP);
 	bus_write_4(sc->sc_mem, FMBM_RFSDM, FM_FD_ERR_DIS);
 	bus_write_4(sc->sc_mem, FMBM_RFSEM, BMI_RX_ERR & ~FM_FD_ERR_DIS);
 
@@ -462,6 +481,11 @@ fman_port_init_bmi_tx(struct fman_port_softc *sc)
 	bus_write_4(sc->sc_mem, FMBM_TFENE,
 	    NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
 
+	/* Insert internal context ahead of the frame */
+	reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << TICP_ICIOF_S;
+	reg |= howmany(sizeof(struct fman_internal_context), 0x10);
+	bus_write_4(sc->sc_mem, FMBM_TICP, reg);
+
 	if (sc->sc_revision_major >= 6)
 		bus_write_4(sc->sc_mem, FMBM_TFNE,
 		    (sc->sc_default_fqid == 0 ? TFNE_EBD : 0) |
@@ -477,7 +501,7 @@ fman_port_init_hwp(struct fman_port_softc *sc)
 {
 	int i;
 
-	/* TODO: fman_port_init_hwp */
+	/* Stop the parser so we can initialize it for our uses */
 	bus_write_4(sc->sc_mem, HWP_PCAC, HWP_PCAC_PSTOP);
 
 	for (i = 0; i < 100 &&
@@ -497,16 +521,9 @@ fman_port_init_hwp(struct fman_port_softc *sc)
 	bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_TCP), HXS_SH_PAD_REM);
 	bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_UDP), HXS_SH_PAD_REM);
 
+	/* Re-enable the parser */
 	bus_write_4(sc->sc_mem, HWP_PCAC, 0);
 
-	for (i = 100; i > 0 &&
-	    (bus_read_4(sc->sc_mem, HWP_PCAC) & HWP_HXS_PCAC_PSTAT) == 0; i--) {
-		DELAY(10);
-	}
-	if (i == 0) {
-		device_printf(sc->sc_dev, "Timeout starting HW parser\n");
-		return (ENXIO);
-	}
 	return (0);
 }
 
diff --git a/sys/dev/dpaa/if_memac.c b/sys/dev/dpaa/if_memac.c
index c490cc1dede9..ec216e8b2185 100644
--- a/sys/dev/dpaa/if_memac.c
+++ b/sys/dev/dpaa/if_memac.c
@@ -89,6 +89,7 @@
 
 #define	DEFAULT_PAUSE_QUANTA	0xf000
 
+#define	DPAA_CSUM_TX_OFFLOAD	(CSUM_IP | CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6)
 
 
 /**
@@ -308,6 +309,7 @@ memac_if_ioctl(if_t ifp, u_long command, caddr_t data)
 {
 	struct memac_softc *sc;
 	struct ifreq *ifr;
+	uint32_t changed;
 	int error;
 
 	sc = if_getsoftc(ifp);
@@ -344,6 +346,18 @@ memac_if_ioctl(if_t ifp, u_long command, caddr_t data)
 		}
 		break;
 
+	case SIOCSIFCAP:
+		changed = if_getcapenable(ifp) ^ ifr->ifr_reqcap;
+		if ((changed & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) != 0)
+			if_togglecapenable(ifp,
+			    IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6);
+		if ((changed & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) != 0) {
+			if_togglecapenable(ifp,
+			    IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+			if_togglehwassist(ifp, DPAA_CSUM_TX_OFFLOAD);
+		}
+		break;
+
 	case SIOCGIFMEDIA:
 	case SIOCSIFMEDIA:
 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_base.sc_mii->mii_media,
@@ -603,8 +617,11 @@ memac_attach(device_t dev)
 		    device_get_unit(sc->sc_base.sc_dev));
 
 
-	if_setcapabilities(ifp, IFCAP_VLAN_MTU);
+	if_setcapabilities(ifp, IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM |
+	    IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 |
+	    IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
 	if_setcapenable(ifp, if_getcapabilities(ifp));
+	if_sethwassist(ifp, DPAA_CSUM_TX_OFFLOAD);
 
 	/* Attach PHY(s) */
 	if (!sc->sc_fixed_link) {


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f79dfe.3cac1.2033c7a2>