Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Apr 2026 08:07:55 +0000
From:      Dmitry Salychev <dsl@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 150ac95e4a56 - stable/15 - dpaa2: Extract checksum statuses on ingress
Message-ID:  <69e881db.261d9.ee86653@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/15 has been updated by dsl:

URL: https://cgit.FreeBSD.org/src/commit/?id=150ac95e4a56855e7ffaa1014d7a82e9eda89f65

commit 150ac95e4a56855e7ffaa1014d7a82e9eda89f65
Author:     Dmitry Salychev <dsl@FreeBSD.org>
AuthorDate: 2026-04-13 12:46:49 +0000
Commit:     Dmitry Salychev <dsl@FreeBSD.org>
CommitDate: 2026-04-22 08:06:26 +0000

    dpaa2: Extract checksum statuses on ingress
    
    In order to enable RX checksum offloading we need to check the
    meta-information for the (good) frames to see if the L3/4 checksums
    were calculated and if there was an error.
    
    The way the buffere are setup, the needed frame meta-information is
    already requested. All we have to do is make sure it is really part
    of the RX frame, that it is valid, and if the respective bits are set.
    
    Also do not forget to set the (dummy) csum_data as otherwise upper
    layers will just be cranky. An artefact of the past which likely
    should disappear.
    
    PR:             292006
    Reviewed by:    bz, tuexen
    Tested by:      bz, tuexen
    Approved by:    tuexen
    Obtained from:  bz (initial version, D55320)
    MFC after:      3 days
    Sponsored by:   Traverse Technologies (providing Ten64 HW for testing)
    Differential Revision:  https://reviews.freebsd.org/D56383
    
    (cherry picked from commit 4a6d7fc1a00b69925b3edc39acef0391487a8e3e)
---
 sys/dev/dpaa2/dpaa2_frame.c | 100 ++++++++++++++++++++++++++++++++++++++------
 sys/dev/dpaa2/dpaa2_frame.h |  63 +++++++++++++++++++++++++++-
 sys/dev/dpaa2/dpaa2_ni.c    |  76 ++++++++++++++++++++++++++++++++-
 sys/dev/dpaa2/dpaa2_ni.h    |   6 ++-
 4 files changed, 227 insertions(+), 18 deletions(-)

diff --git a/sys/dev/dpaa2/dpaa2_frame.c b/sys/dev/dpaa2/dpaa2_frame.c
index 4a155f7cb32f..005708228058 100644
--- a/sys/dev/dpaa2/dpaa2_frame.c
+++ b/sys/dev/dpaa2/dpaa2_frame.c
@@ -1,7 +1,8 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright © 2026 Dmitry Salychev
+ * Copyright (c) 2026 Dmitry Salychev
+ * Copyright (c) 2026 Bjoern A. Zeeb
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +30,7 @@
 
 #include <sys/param.h>
 #include <sys/errno.h>
+#include <sys/endian.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -138,28 +140,102 @@ dpaa2_fd_offset(struct dpaa2_fd *fd)
 	return (fd->offset_fmt_sl & DPAA2_FD_OFFSET_MASK);
 }
 
+uint32_t
+dpaa2_fd_get_frc(struct dpaa2_fd *fd)
+{
+	/* TODO: Convert endiannes in the other functions as well. */
+	return (le32toh(fd->frame_ctx));
+}
+
+#ifdef _not_yet_
+void
+dpaa2_fd_set_frc(struct dpaa2_fd *fd, uint32_t frc)
+{
+	/* TODO: Convert endiannes in the other functions as well. */
+	fd->frame_ctx = htole32(frc);
+}
+#endif
+
 int
 dpaa2_fa_get_swa(struct dpaa2_fd *fd, struct dpaa2_swa **swa)
 {
-	int rc;
-
-	if (fd == NULL || swa == NULL)
+	if (__predict_false(fd == NULL || swa == NULL))
 		return (EINVAL);
 
-	if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_MASK) >= 0x4u) {
-		*swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr);
-		rc = 0;
-	} else {
+	if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_PTA_MASK) == 0u) {
 		*swa = NULL;
-		rc = ENOENT;
+		return (ENOENT);
 	}
 
-	return (rc);
+	*swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr);
+
+	return (0);
 }
 
 int
 dpaa2_fa_get_hwa(struct dpaa2_fd *fd, struct dpaa2_hwa **hwa)
 {
-	/* TODO: To be implemented next. */
-	return (ENOENT);
+	uint8_t *buf;
+	uint32_t hwo; /* HW annotation offset */
+
+	if (__predict_false(fd == NULL || hwa == NULL))
+		return (EINVAL);
+
+	/*
+	 * As soon as the ASAL is in the 64-byte units, we don't need to
+	 * calculate the exact length, but make sure that it isn't 0.
+	 */
+	if (((fd->ctrl >> DPAA2_FD_ASAL_SHIFT) & DPAA2_FD_ASAL_MASK) == 0u) {
+		*hwa = NULL;
+		return (ENOENT);
+	}
+
+	buf = (uint8_t *)PHYS_TO_DMAP((bus_addr_t)fd->addr);
+	hwo = ((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_PTA_MASK) > 0u
+	    ? DPAA2_FA_SWA_SIZE : 0u;
+	*hwa = (struct dpaa2_hwa *)(buf + hwo);
+
+	return (0);
+}
+
+int
+dpaa2_fa_get_fas(struct dpaa2_fd *fd, struct dpaa2_hwa_fas *fas)
+{
+	struct dpaa2_hwa *hwa;
+	struct dpaa2_hwa_fas *fasp;
+	int rc;
+
+	if (__predict_false(fd == NULL || fas == NULL))
+		return (EINVAL);
+
+	rc = dpaa2_fa_get_hwa(fd, &hwa);
+	if (__predict_false(rc != 0))
+		return (rc);
+
+	fasp = (struct dpaa2_hwa_fas *)&hwa->fas;
+	*fas = *fasp;
+
+	return (rc);
+}
+
+#ifdef _not_yet_
+int
+dpaa2_fa_set_fas(struct dpaa2_fd *fd, struct dpaa2_hwa_fas *fas)
+{
+	struct dpaa2_hwa *hwa;
+	uint64_t *valp;
+	int rc;
+
+	if (__predict_false(fd == NULL || fas == NULL))
+		return (EINVAL);
+
+	rc = dpaa2_fa_get_hwa(fd, &hwa);
+	if (__predict_false(rc != 0))
+		return (rc);
+
+	valp = (uint64_t *)fas;
+	hwa->fas = *valp;
+
+	return (rc);
 }
+#endif
diff --git a/sys/dev/dpaa2/dpaa2_frame.h b/sys/dev/dpaa2/dpaa2_frame.h
index 0b2a5a7d8e74..ab83b402efa4 100644
--- a/sys/dev/dpaa2/dpaa2_frame.h
+++ b/sys/dev/dpaa2/dpaa2_frame.h
@@ -1,7 +1,8 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright © 2026 Dmitry Salychev
+ * Copyright (c) 2026 Dmitry Salychev
+ * Copyright (c) 2026 Bjoern A. Zeeb
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -56,8 +57,13 @@
 #define DPAA2_FD_SL_SHIFT	(14)
 #define DPAA2_FD_LEN_MASK	(0x3FFFFu)
 #define DPAA2_FD_OFFSET_MASK	(0x0FFFu)
+#define DPAA2_FD_PTAC_PTV2_MASK	(0x1u)
+#define DPAA2_FD_PTAC_PTV1_MASK	(0x2u)
+#define DPAA2_FD_PTAC_PTA_MASK	(0x4u)
 #define DPAA2_FD_PTAC_MASK	(0x7u)
 #define DPAA2_FD_PTAC_SHIFT	(21)
+#define DPAA2_FD_ASAL_MASK	(0xFu)
+#define DPAA2_FD_ASAL_SHIFT	(16)
 
 /*
  * DPAA2 frame annotation sizes
@@ -73,6 +79,31 @@
 #define DPAA2_FA_SWA_SIZE		64u	/* SW frame annotation */
 #define DPAA2_FA_HWA_SIZE		128u	/* HW frame annotation */
 #define DPAA2_FA_WRIOP_SIZE		128u	/* WRIOP HW annotation */
+#define DPAA2_FA_HWA_FAS_SIZE		8u	/* Frame annotation status */
+
+/*
+ * DPAA2 annotation valid bits in FD[FRC].
+ *
+ * See 7.31.2 WRIOP FD frame context (FRC),
+ * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020
+ */
+#define DPAA2_FD_FRC_FASV		(1 << 15)
+#define DPAA2_FD_FRC_FAEADV		(1 << 14)
+#define DPAA2_FD_FRC_FAPRV		(1 << 13)
+#define DPAA2_FD_FRC_FAIADV		(1 << 12)
+#define DPAA2_FD_FRC_FASWOV		(1 << 11)
+#define DPAA2_FD_FRC_FAICFDV		(1 << 10)
+
+/*
+ * DPAA2 Frame annotation status word.
+ *
+ * See 7.34.3 Frame annotation status word (FAS),
+ * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020
+ */
+#define DPAA2_FAS_L3CV			(1 << 3) /* L3 csum validated */
+#define DPAA2_FAS_L3CE			(1 << 2) /* L3 csum error */
+#define DPAA2_FAS_L4CV			(1 << 1) /* L4 csum validated*/
+#define DPAA2_FAS_L4CE			(1 << 0) /* L4 csum error */
 
 /**
  * @brief DPAA2 frame descriptor.
@@ -126,13 +157,18 @@ struct dpaa2_hwa_wriop {
 CTASSERT(sizeof(struct dpaa2_hwa_wriop) == DPAA2_FA_WRIOP_SIZE);
 
 /**
- * @brief DPAA2 hardware frame annotation (accelerator-specific annotation).
+ * @brief DPAA2 hardware frame annotation.
  *
  * See 3.4.1.2 Accelerator-specific annotation,
  * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 
  */
 struct dpaa2_hwa {
 	union {
+		/* Keep fields common to all accelerators at the top. */
+		struct {
+			uint64_t fas;
+		} __packed;
+		/* Keep accelerator-specific annotations below. */
 		struct dpaa2_hwa_wriop wriop;
 	};
 } __packed;
@@ -159,6 +195,20 @@ struct dpaa2_swa {
 } __packed;
 CTASSERT(sizeof(struct dpaa2_swa) == DPAA2_FA_SWA_SIZE);
 
+/**
+ * @brief Frame annotation status word.
+ *
+ * See 7.34.3 Frame annotation status word (FAS),
+ * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020
+ */
+struct dpaa2_hwa_fas {
+	uint8_t  _reserved1;
+	uint8_t  ppid;
+	uint16_t ifpid;
+	uint32_t status;
+} __packed;
+CTASSERT(sizeof(struct dpaa2_hwa_fas) == DPAA2_FA_HWA_FAS_SIZE);
+
 int  dpaa2_fd_build(device_t, const uint16_t, struct dpaa2_buf *,
     bus_dma_segment_t *, const int, struct dpaa2_fd *);
 
@@ -168,7 +218,16 @@ int  dpaa2_fd_format(struct dpaa2_fd *);
 bool dpaa2_fd_short_len(struct dpaa2_fd *);
 int  dpaa2_fd_offset(struct dpaa2_fd *);
 
+uint32_t dpaa2_fd_get_frc(struct dpaa2_fd *);
+#ifdef _not_yet_
+void dpaa2_fd_set_frc(struct dpaa2_fd *, uint32_t);
+#endif
+
 int  dpaa2_fa_get_swa(struct dpaa2_fd *, struct dpaa2_swa **);
 int  dpaa2_fa_get_hwa(struct dpaa2_fd *, struct dpaa2_hwa **);
+int  dpaa2_fa_get_fas(struct dpaa2_fd *, struct dpaa2_hwa_fas *);
+#ifdef _not_yet_
+int  dpaa2_fa_set_fas(struct dpaa2_fd *, struct dpaa2_hwa_fas *);
+#endif
 
 #endif /* _DPAA2_FRAME_H */
diff --git a/sys/dev/dpaa2/dpaa2_ni.c b/sys/dev/dpaa2/dpaa2_ni.c
index f173bff6e65f..5f9282e120e4 100644
--- a/sys/dev/dpaa2/dpaa2_ni.c
+++ b/sys/dev/dpaa2/dpaa2_ni.c
@@ -1,8 +1,9 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright © 2021-2023 Dmitry Salychev
- * Copyright © 2022 Mathew McBride
+ * Copyright (c) 2021-2026 Dmitry Salychev
+ * Copyright (c) 2022 Mathew McBride
+ * Copyright (c) 2026 Bjoern A. Zeeb
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -412,6 +413,7 @@ static int dpaa2_ni_set_dist_key(device_t, enum dpaa2_ni_dist_mode, uint64_t);
 /* Various subroutines */
 static int dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *, uint16_t, uint16_t);
 static int dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *, uint8_t *);
+static int dpaa2_ni_update_csum_flags(struct dpaa2_fd *, struct mbuf *);
 
 /* Network interface routines */
 static void dpaa2_ni_init(void *);
@@ -491,6 +493,7 @@ dpaa2_ni_attach(device_t dev)
 	sc->rx_sg_buf_frames = 0;
 	sc->rx_enq_rej_frames = 0;
 	sc->rx_ieoi_err_frames = 0;
+	sc->rx_other_err_frames = 0;
 	sc->tx_single_buf_frames = 0;
 	sc->tx_sg_frames = 0;
 
@@ -1737,6 +1740,9 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc)
 	SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_ieoi_err_frames",
 	    CTLFLAG_RD, &sc->rx_ieoi_err_frames,
 	    "QMan IEOI error");
+	SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_other_err_frames",
+	    CTLFLAG_RD, &sc->rx_other_err_frames,
+	    "Other Rx frames with errors");
 	SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "tx_single_buf_frames",
 	    CTLFLAG_RD, &sc->tx_single_buf_frames,
 	    "Tx single buffer frames");
@@ -3121,6 +3127,7 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
 	bus_addr_t released[DPAA2_SWP_BUFS_PER_CMD];
 	void *buf_data;
 	int buf_len, error, released_n = 0;
+	bool update_csum_flags;
 
 	error = dpaa2_fa_get_swa(fd, &swa);
 	if (__predict_false(error != 0))
@@ -3131,6 +3138,7 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
 	buf = swa->buf;
 	bch = (struct dpaa2_channel *)buf->opt;
 	sc = device_get_softc(bch->ni_dev);
+	update_csum_flags = true;
 
 	KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__));
 	/*
@@ -3145,6 +3153,14 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
 	}
 
 	switch (dpaa2_fd_err(fd)) {
+	case 0:
+		/*
+		 * FD[ERR] = 0 value is reserved to indicate that there is no
+		 * error encoded in this field. See 3.4.5 Error handling,
+		 * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0,
+		 * 06/2020.
+		 */
+		break;
 	case 1: /* Enqueue rejected by QMan */
 		sc->rx_enq_rej_frames++;
 		break;
@@ -3152,8 +3168,10 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
 		sc->rx_ieoi_err_frames++;
 		break;
 	default:
+		sc->rx_other_err_frames++;
 		break;
 	}
+
 	switch (dpaa2_fd_format(fd)) {
 	case DPAA2_FD_SINGLE:
 		sc->rx_single_buf_frames++;
@@ -3162,6 +3180,7 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
 		sc->rx_sg_buf_frames++;
 		break;
 	default:
+		update_csum_flags = false;
 		break;
 	}
 
@@ -3193,6 +3212,14 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq,
 	m->m_pkthdr.flowid = fq->fqid;
 	M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
 
+	if (update_csum_flags && ((if_getcapenable(sc->ifp) & (IFCAP_RXCSUM |
+	    IFCAP_RXCSUM_IPV6)) != 0)) {
+		error = dpaa2_ni_update_csum_flags(fd, m);
+		if (error != 0)
+			device_printf(sc->dev, "%s: failed to update checksum "
+			    "flags: error=%d\n", __func__, error);
+	}
+
 	if (ctx->head == NULL) {
 		KASSERT(ctx->tail == NULL, ("%s: tail already given?", __func__));
 		ctx->head = m;
@@ -3634,6 +3661,51 @@ dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *cfg, uint8_t *key_cfg_buf)
 	return (0);
 }
 
+static int
+dpaa2_ni_update_csum_flags(struct dpaa2_fd *fd, struct mbuf *m)
+{
+	struct dpaa2_hwa_fas fas;
+	uint32_t status;
+	int rc;
+
+	if (__predict_false((dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) == 0u)
+		return (EINVAL);
+
+	/*
+	 * XXX-DSL: Frame context of the frame descriptor (FD[FRC]) contains
+	 *          an Accelerator ID in the MSbits on some SoCs (e.g. LS1088A),
+	 *          but a frame ParseSummary on the others (e.g. LX2160A).
+	 *          However, frame annotation valid bits seem to be at the
+	 *          same offsets. This is the reason why different accelerators
+	 *          are treated the same here. It isn't clear whether this is
+	 *          a hardware limitation of the SoCs, version of the firmware
+	 *          or DPL configuration.
+	 */
+
+	rc = dpaa2_fa_get_fas(fd, &fas);
+	if (rc != 0)
+		return (rc);
+
+	status = le32toh(fas.status);
+	rc = 0;
+
+	/* L3 */
+	if ((status & DPAA2_FAS_L3CV) != 0) {
+		m->m_pkthdr.csum_flags |= CSUM_L3_CALC;
+		if ((status & DPAA2_FAS_L3CE) == 0)
+			m->m_pkthdr.csum_flags |= CSUM_L3_VALID;
+	}
+	/* L4 */
+	if ((status & DPAA2_FAS_L4CV) != 0) {
+		m->m_pkthdr.csum_flags |= CSUM_L4_CALC;
+		m->m_pkthdr.csum_data = 0xffff;
+		if ((status & DPAA2_FAS_L4CE) == 0)
+			m->m_pkthdr.csum_flags |= CSUM_L4_VALID;
+	}
+
+	return (rc);
+}
+
 static device_method_t dpaa2_ni_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		dpaa2_ni_probe),
diff --git a/sys/dev/dpaa2/dpaa2_ni.h b/sys/dev/dpaa2/dpaa2_ni.h
index fcd37501ebd0..9b1397fc544d 100644
--- a/sys/dev/dpaa2/dpaa2_ni.h
+++ b/sys/dev/dpaa2/dpaa2_ni.h
@@ -1,8 +1,9 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright © 2021-2023 Dmitry Salychev
- * Copyright © 2022 Mathew McBride
+ * Copyright (c) 2021-2023 Dmitry Salychev
+ * Copyright (c) 2022 Mathew McBride
+ * Copyright (c) 2026 Bjoern A. Zeeb
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -466,6 +467,7 @@ struct dpaa2_ni_softc {
 	uint64_t		 rx_sg_buf_frames;
 	uint64_t		 rx_enq_rej_frames;
 	uint64_t		 rx_ieoi_err_frames;
+	uint64_t		 rx_other_err_frames;
 	uint64_t		 tx_single_buf_frames;
 	uint64_t		 tx_sg_frames;
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e881db.261d9.ee86653>