diff options
| author | Justin Hibbits <jhibbits@FreeBSD.org> | 2026-04-25 20:50:34 +0000 |
|---|---|---|
| committer | Justin Hibbits <jhibbits@FreeBSD.org> | 2026-05-03 19:09:29 +0000 |
| commit | 6464974c5a56a9f899f8a673385711253f9fcbd0 (patch) | |
| tree | fef08ada879489159797fb4e826cfd20e8bdeae5 /sys/dev | |
| parent | fd8d34ce272ba40f3e0218198ba542a29c390a4a (diff) | |
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/dpaa/dpaa_common.h | 30 | ||||
| -rw-r--r-- | sys/dev/dpaa/dpaa_eth.c | 92 | ||||
| -rw-r--r-- | sys/dev/dpaa/fman.h | 30 | ||||
| -rw-r--r-- | sys/dev/dpaa/fman_parser.h | 27 | ||||
| -rw-r--r-- | sys/dev/dpaa/fman_port.c | 47 | ||||
| -rw-r--r-- | 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); } @@ -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) { |
