aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJustin Hibbits <jhibbits@FreeBSD.org>2026-04-25 20:50:34 +0000
committerJustin Hibbits <jhibbits@FreeBSD.org>2026-05-03 19:09:29 +0000
commit6464974c5a56a9f899f8a673385711253f9fcbd0 (patch)
treefef08ada879489159797fb4e826cfd20e8bdeae5 /sys/dev
parentfd8d34ce272ba40f3e0218198ba542a29c390a4a (diff)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dpaa/dpaa_common.h30
-rw-r--r--sys/dev/dpaa/dpaa_eth.c92
-rw-r--r--sys/dev/dpaa/fman.h30
-rw-r--r--sys/dev/dpaa/fman_parser.h27
-rw-r--r--sys/dev/dpaa/fman_port.c47
-rw-r--r--sys/dev/dpaa/if_memac.c19
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);
}
@@ -319,25 +324,47 @@ dpaa_eth_fq_mext_free(struct mbuf *m)
}
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) {