From nobody Mon Aug 24 03:11:52 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hSwtc4Czjz6q8JQ for ; Mon, 24 Aug 2026 03:11:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hSwtc30S2z3Nsb for ; Mon, 24 Aug 2026 03:11:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787541112; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NafqJk1wuAfLtfAcNy6gkq6s/iE0Tnm2hRcbLlMSFDc=; b=RhJWawmWtW6jGy5czoieexeoU2T++ow3kECH5UZV8wvxK1VMTNY/D4qTraAlHB/N5AxKyt DfzS+amxWUmSgOiDE7yzpZlwtmMSIsYqE193iGXAYGZDH7ZUxas9hmlKiGdjqjCxIdhoEw vsxg+C4pI5sk7Avp8sWItPxlnJYMVv8W2a0EXO9Z4o3RfslTG/W2T9M1rtAXoeetjgZeku jvZTdQUGD9TJpYqo8OhV62CXvaBQWTbOKBUcEbs2yHHmulLPuQx9gt3PbjoRhPmaZNI8pA Szpvb1sWMwAFO9ptO/SPtK0G7+0a0a8FooYwaj605un52XraohuDaFhcPw0yQQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787541112; a=rsa-sha256; cv=none; b=LpzAlic8lQznxYpDSG4ovRSYo/te7bfPThUyT25IY3a1NF2nSFDarXQPXXJPcmZAIZ/CQt OV6x0oqNRDjTC+2pROCClpSw9OdAWwtFqGr/HCZAzSf9ewUFwKaKpVVtYUeBQnAc4lh1Ce th22haFza/reqiJNt6Dvyb3VYsQaPrOdBloju+rKjKpXOnoqXZzE6HZtz0in23b0X+N1zT Q/gzTgNStGmALzZo3TuUA0HwaZzqD2OgIeG+VdL4U3rAbX9mNb2UkyyOl9uuQkU3ictE6P NkhTsLoREYIsyDF3bAGVhsooZxHSfVr/KMg32MfQKxBb/gnizQ3Zmp8cxRFdVQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787541112; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NafqJk1wuAfLtfAcNy6gkq6s/iE0Tnm2hRcbLlMSFDc=; b=V3i41IFx++CQAxPdNq2JJmH+oy0T+yqs0hxysRCJWNIl4ymCWImF1O9VJyX9sfWqpOgtjw kR5PGeLxM+8pWIwbxZZTrMxi+k+ezTzGj1Q4jiYho27NgdLEgUfsY0LyH92lvC1zQ0TDc0 C/W75EG5H9ae8LNB6Khi+O2bq77BSUaHXp4Zc0cDM+Q3zBYOMcu0SZyjseCBNjVGctcrqc ZSkZewk5QsXfib9Ac2Xb4efSyKnzX2W0sh6APMkJHdSCLr8mM260OyoPOwk9qJnZffOCnw s6zkyaP5wqYmiG2RxxSp+I7v6CmoZ8f7bkkXYquC4ojqy0LGW5l75sGwEVPC/g== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hSwtc0xWKzmkH for ; Mon, 24 Aug 2026 03:11:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 18a30 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 24 Aug 2026 03:11:52 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Justin Hibbits Subject: git: 4dccd3ac8685 - main - dpaa/fman: KeyGen (Parse-Classify-Distribute) driver List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhibbits X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 4dccd3ac8685355e97593d5e27adf14e2b0b8473 Auto-Submitted: auto-generated Date: Mon, 24 Aug 2026 03:11:52 +0000 Message-Id: <6a8bb678.18a30.47b4f414@gitrepo.freebsd.org> The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=4dccd3ac8685355e97593d5e27adf14e2b0b8473 commit 4dccd3ac8685355e97593d5e27adf14e2b0b8473 Author: Justin Hibbits AuthorDate: 2026-08-10 14:03:01 +0000 Commit: Justin Hibbits CommitDate: 2026-08-24 03:11:26 +0000 dpaa/fman: KeyGen (Parse-Classify-Distribute) driver Add sys/dev/dpaa/fman_keygen.[ch]. Public API is four functions: * fman_kg_init(sc) -- Initialize KeyGen subsystem, clear out any stale config. * fman_kg_fini(sc) -- Teardown KeyGen * fman_kg_alloc_hash_scheme(sc, port, base_fqid, nfqs) -- Allocate a scheme, program it for RSS-over-IP-5-tuple hashing to nfqs FQs starting at base_fqid, bind it to port. * fman_kg_free_hash_scheme(sc, port) -- Remove a scheme added by fman_kg_alloc_hash_scheme(). KeyGen state (bitmap + port->scheme table) is added to the fman softc. Future work may allow configuring the KG hash inputs, but what we have now (5-tuple of src/src-port/dst/dst-port/IPSec SPI field) is sufficient. --- sys/conf/files.powerpc | 1 + sys/dev/dpaa/fman.c | 10 +- sys/dev/dpaa/fman.h | 22 +++ sys/dev/dpaa/fman_keygen.c | 371 +++++++++++++++++++++++++++++++++++++++++++++ sys/dev/dpaa/fman_keygen.h | 39 +++++ sys/dev/dpaa/fman_port.c | 12 -- 6 files changed, 435 insertions(+), 20 deletions(-) diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index e8027be7c344..3623a8f15424 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -96,6 +96,7 @@ dev/dpaa/dpaa_eth.c optional dpaa dev/dpaa/fman.c optional dpaa fdt dev/dpaa/fman_fdt.c optional dpaa fdt dev/dpaa/fman_if.m optional dpaa +dev/dpaa/fman_keygen.c optional dpaa dev/dpaa/fman_mdio.c optional dpaa fdt dev/dpaa/fman_port_if.m optional dpaa dev/dpaa/fman_port.c optional dpaa diff --git a/sys/dev/dpaa/fman.c b/sys/dev/dpaa/fman.c index e9e16d3c409d..84350853949f 100644 --- a/sys/dev/dpaa/fman.c +++ b/sys/dev/dpaa/fman.c @@ -24,6 +24,7 @@ #include #include "fman.h" +#include "fman_keygen.h" #define FMAN_BMI_OFFSET 0x80000 #define FMAN_QMI_OFFSET 0x80400 @@ -566,13 +567,6 @@ fman_enable_timestamp(struct fman_softc *sc) return (0); } -static int -fman_keygen_init(struct fman_softc *sc) -{ - /* TODO: keygen */ - return (0); -} - static int fman_fpm_init(struct fman_softc *sc) { @@ -623,7 +617,7 @@ fman_init(struct fman_softc *sc) fman_bmi_init(sc); fman_qmi_init(sc); fman_hwp_init(sc); - if (fman_keygen_init(sc) != 0) + if (fman_kg_init(sc) != 0) goto err; if (fman_enable(sc) != 0) diff --git a/sys/dev/dpaa/fman.h b/sys/dev/dpaa/fman.h index a0af1b36b5a3..bc4a5752fbfb 100644 --- a/sys/dev/dpaa/fman.h +++ b/sys/dev/dpaa/fman.h @@ -46,6 +46,19 @@ #define FM_FD_ERR_PHE 0x00000020 #define FM_FD_ERR_BLE 0x00000008 +/* Common defines (Next Invoked Action) */ +#define NIA_ORDER_RESTORE 0x00800000 +#define NIA_ENG_BMI 0x00500000 +#define NIA_ENG_QMI_DEQ 0x00580000 +#define NIA_ENG_QMI_ENQ 0x00540000 +#define NIA_ENG_HWP 0x00440000 +#define NIA_ENG_HWK 0x00480000 +#define NIA_BMI_AC_TX_RELEASE 0x000002c0 +#define NIA_BMI_AC_TX 0x00000274 +#define NIA_BMI_AC_RELEASE 0x000000c0 +#define NIA_BMI_AC_ENQ_FRAME 0x00000002 +#define NIA_BMI_AC_FETCH_ALLFRAME 0x0000020c + /** * FMan driver instance data. */ @@ -89,6 +102,15 @@ struct fman_softc { uint32_t qman_channel_base; uint32_t qman_channels; + + /* + * FMan KeyGen (Parse-Classify-Distribute) state. See + * fman_keygen.c. 32 KG schemes fit in a u32 bitmap; the + * port->scheme table is sized to the KG hardware limit of + * 64 possible port IDs. + */ + uint32_t sc_kg_schemes_used; + int8_t sc_kg_port_scheme[64]; }; struct fman_port_init_params { diff --git a/sys/dev/dpaa/fman_keygen.c b/sys/dev/dpaa/fman_keygen.c new file mode 100644 index 000000000000..b2384721c5b0 --- /dev/null +++ b/sys/dev/dpaa/fman_keygen.c @@ -0,0 +1,371 @@ +/*- + * Copyright (c) 2026 Justin Hibbits + * + * SPDX-License-Identifier: BSD-2-Clause + * + * FMan KeyGen (KG) support. The KG block is the FMan sub-unit that + * classifies incoming frames into destination FQIDs via user-defined + * "schemes". Each scheme extracts a key from the frame's parse + * result, hashes it, and enqueues to FQID = base | (hash & mask). + */ + +#include +#include +#include +#include + +#include + +#include "fman.h" +#include "fman_keygen.h" + +#define FMAN_KG_OFFSET 0xc1000 + +/* + * Register offsets, relative to FMAN_KG_OFFSET (0xc1000) inside the + * FMan register block. + */ +#define FMKG_GCR 0x000 /* general configuration */ +#define FMKG_GCR_EN 0x80000000 +#define FMKG_EER 0x00C /* error event */ +#define FMKG_EER_DOUBLE_ECC 0x80000000 +#define FMKG_EER_KEYSIZE_OVF 0x40000000 +#define FMKG_EEER 0x010 /* error event enable */ +#define FMKG_SEER 0x01C /* scheme error event */ +#define FMKG_SEEER 0x020 /* scheme error event enable */ +#define FMKG_GSR 0x024 /* global status */ +#define FMKG_GSR_BSY 0x80000000 +#define FMKG_TPC 0x028 /* total packet counter */ +#define FMKG_SERC 0x02C /* soft error capture */ +#define FMKG_FDOR 0x034 /* frame data offset */ +#define FMKG_GDV0R 0x038 /* global default value 0 */ +#define FMKG_GDV1R 0x03C /* global default value 1 */ +#define FMKG_FEER 0x044 /* force error event */ +#define FMKG_AR 0x1FC /* action register */ +#define FMKG_AR_GO 0x80000000 +#define FMKG_AR_READ 0x40000000 /* clear = write */ +#define FMKG_AR_ERR 0x20000000 +#define FMKG_AR_SEL_CLS_PLAN 0x01000000 +#define FMKG_AR_SEL_PORT 0x02000000 /* clear = scheme entry */ +#define FMKG_AR_PORT_WSEL_SP 0x00008000 +#define FMKG_AR_PORT_WSEL_CPP 0x00004000 +#define FMKG_AR_SCM_WSEL_UPDCNT 0x00008000 +#define FMKG_AR_NUM_SHIFT 16 /* scheme id here */ + +/* + * Indirect access sub-region (union of "scheme entry" and "port + * entry" views, discriminated by the last AR selector written). + */ +#define FMKG_IND 0x100 + +/* Scheme-view offsets, relative to FMKG_IND. */ +#define FMKG_SE_MODE 0x00 /* mode + NIA */ +#define FMKG_SE_MODE_EN 0x80000000 +#define FMKG_SE_EKFC 0x04 /* extract known fields command */ +#define FMKG_EKFC_IPSRC1 0x00100000 +#define FMKG_EKFC_IPDST1 0x00080000 +#define FMKG_EKFC_L4PSRC 0x00000004 +#define FMKG_EKFC_L4PDST 0x00000002 +#define FMKG_EKFC_IPSEC_SPI 0x00000200 +#define FMKG_SE_EKDV 0x08 /* extract known default value */ +#define FMKG_EKDV_IP_ADDR_SHIFT 18 +#define FMKG_EKDV_L4_PORT_SHIFT 8 +#define FMKG_EKDV_USE_DV0 2 +#define FMKG_EKDV_USE_DV1 3 +#define FMKG_SE_BMCH 0x0C /* bit mask high */ +#define FMKG_SE_BMCL 0x10 /* bit mask low */ +#define FMKG_SE_FQB 0x14 /* frame queue base */ +#define FMKG_SE_HC 0x18 /* hash command */ +#define FMKG_SE_HC_SYM 0x40000000 /* symmetric hash */ +#define FMKG_SE_HC_SHIFT_SHIFT 24 +#define FMKG_SE_HC_MASK_SHIFT 0 +#define FMKG_SE_PPC 0x1C /* policer profile command */ +#define FMKG_SE_GEC(i) (0x20 + (i) * 4) /* generic extract command [0..7] */ +#define FMKG_SE_SPC 0x40 /* statistic packet counter */ +#define FMKG_SE_DV0 0x44 /* default value 0 */ +#define FMKG_SE_DV1 0x48 /* default value 1 */ +#define FMKG_SE_CCBS 0x4C /* coarse classification */ +#define FMKG_SE_MV 0x50 /* match vector */ +#define FMKG_SE_OM 0x54 /* operation mode */ +#define FMKG_SE_VSP 0x58 /* virtual storage profile */ +#define FMKG_SE_VSP_NO_KSP_EN 0x80000000 + +/* Port-view offsets, relative to FMKG_IND. */ +#define FMKG_PE_SP 0x00 /* port scheme partition */ +#define FMKG_PE_CPP 0x04 /* port classification-plan partition */ + +/* + * Default NIA for post-KeyGen + */ +#define FMKG_ENQ_KG_DFLT_NIA \ + (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME) + +/* + * Arbitrary fillers used for the "missing field" fallback slots. + * The exact values don't matter for correctness -- the hash still + * distributes uniformly across FQs -- but a non-zero pattern makes + * two frames missing the same field hash to a consistent bucket. + */ +#define FMKG_DFLT_IPv4_ADDR 0x0a0a0a0a +#define FMKG_DFLT_L4_PORT 0x0b0b0b0b + +/* Sizing. */ +#define FMKG_MAX_SCHEMES 32 +#define FMKG_MAX_HW_PORTS 64 + +/* + * AR-write acknowledge wait. Linux busy-loops with no bound; we + * cap at ~1 ms of DELAY(1) to survive a wedged block without + * hanging the boot. + */ +#define FMKG_AR_WAIT_US 1000 + +static inline uint32_t +kg_read(struct fman_softc *sc, bus_size_t off) +{ + return (bus_read_4(sc->mem_res, FMAN_KG_OFFSET + off)); +} + +static inline void +kg_write(struct fman_softc *sc, bus_size_t off, uint32_t val) +{ + bus_write_4(sc->mem_res, FMAN_KG_OFFSET + off, val); +} + +static int +kg_ar_write(struct fman_softc *sc, uint32_t ar) +{ + int i; + + kg_write(sc, FMKG_AR, ar); + for (i = 0; i < FMKG_AR_WAIT_US; i++) { + ar = kg_read(sc, FMKG_AR); + if ((ar & FMKG_AR_GO) == 0) + break; + DELAY(1); + } + if ((ar & FMKG_AR_GO) != 0) { + device_printf(sc->sc_base.dev, + "fman_kg: AR stuck busy (0x%08x)\n", ar); + return (ETIMEDOUT); + } + if ((ar & FMKG_AR_ERR) != 0) { + device_printf(sc->sc_base.dev, + "fman_kg: AR reported error (0x%08x)\n", ar); + return (EIO); + } + return (0); +} + +/* + * Populate the indirect scheme registers for an RSS-style hash + * scheme and commit it via an AR-write. + */ +static int +kg_program_scheme(struct fman_softc *sc, uint8_t scheme_id, + uint32_t base_fqid, uint32_t nfqs) +{ + uint32_t ekdv; + int error; + + kg_write(sc, FMKG_IND + FMKG_SE_MODE, + FMKG_SE_MODE_EN | FMKG_ENQ_KG_DFLT_NIA); + + kg_write(sc, FMKG_IND + FMKG_SE_EKFC, + FMKG_EKFC_IPSRC1 | FMKG_EKFC_IPDST1 | + FMKG_EKFC_L4PSRC | FMKG_EKFC_L4PDST | + FMKG_EKFC_IPSEC_SPI); + + ekdv = (FMKG_EKDV_USE_DV0 << FMKG_EKDV_IP_ADDR_SHIFT) | + (FMKG_EKDV_USE_DV1 << FMKG_EKDV_L4_PORT_SHIFT); + kg_write(sc, FMKG_IND + FMKG_SE_EKDV, ekdv); + kg_write(sc, FMKG_IND + FMKG_SE_DV0, FMKG_DFLT_IPv4_ADDR); + kg_write(sc, FMKG_IND + FMKG_SE_DV1, FMKG_DFLT_L4_PORT); + + kg_write(sc, FMKG_IND + FMKG_SE_FQB, base_fqid); + /* + * FQID mask width = (nfqs - 1), no hash right-shift. Symmetric + * hash is deliberately off: per NXP's own driver notes, + * spreading breaks with SYM set even though the extraction key + * is nominally symmetric. + */ + kg_write(sc, FMKG_IND + FMKG_SE_HC, + (nfqs - 1) << FMKG_SE_HC_MASK_SHIFT); + + /* + * TODO: Revisit these registers later, if necessary. + */ + kg_write(sc, FMKG_IND + FMKG_SE_BMCH, 0); + kg_write(sc, FMKG_IND + FMKG_SE_BMCL, 0); + kg_write(sc, FMKG_IND + FMKG_SE_PPC, 0); + kg_write(sc, FMKG_IND + FMKG_SE_SPC, 0); + for (int i = 0; i < 8; i++) + kg_write(sc, FMKG_IND + FMKG_SE_GEC(i), 0); + kg_write(sc, FMKG_IND + FMKG_SE_CCBS, 0); + kg_write(sc, FMKG_IND + FMKG_SE_MV, 0); /* indirect scheme */ + kg_write(sc, FMKG_IND + FMKG_SE_OM, 0); + /* + * Don't let the scheme override the port's Virtual Storage + * Profile. + */ + kg_write(sc, FMKG_IND + FMKG_SE_VSP, FMKG_SE_VSP_NO_KSP_EN); + error = kg_ar_write(sc, FMKG_AR_GO | + (scheme_id << FMKG_AR_NUM_SHIFT) | FMKG_AR_SCM_WSEL_UPDCNT); + if (error != 0) + device_printf(sc->sc_base.dev, + "fman_kg: scheme %u program failed\n", scheme_id); + return (error); +} + +static int +kg_disable_scheme(struct fman_softc *sc, uint8_t scheme_id) +{ + kg_write(sc, FMKG_IND + FMKG_SE_MODE, 0); + return (kg_ar_write(sc, FMKG_AR_GO | (scheme_id << FMKG_AR_NUM_SHIFT))); +} + +/* + * Read-modify-write the port's scheme-partition bitmap to add or + * remove @scheme_id. + */ +static int +kg_bind_scheme(struct fman_softc *sc, uint8_t hw_port_id, uint8_t scheme_id, + bool bind) +{ + uint32_t sp; + int error; + + error = kg_ar_write(sc, + FMKG_AR_GO | FMKG_AR_READ | FMKG_AR_SEL_PORT | + hw_port_id | FMKG_AR_PORT_WSEL_SP); + if (error != 0) + return (error); + + sp = kg_read(sc, FMKG_IND + FMKG_PE_SP); + if (bind) + sp |= (1U << (31 - scheme_id)); + else + sp &= ~(1U << (31 - scheme_id)); + kg_write(sc, FMKG_IND + FMKG_PE_SP, sp); + + return (kg_ar_write(sc, + FMKG_AR_GO | FMKG_AR_SEL_PORT | hw_port_id | FMKG_AR_PORT_WSEL_SP)); +} + +int +fman_kg_init(struct fman_softc *sc) +{ + int error, i; + + sc->sc_kg_schemes_used = 0; + for (i = 0; i < FMKG_MAX_HW_PORTS; i++) + sc->sc_kg_port_scheme[i] = -1; + + kg_write(sc, FMKG_GCR, FMKG_ENQ_KG_DFLT_NIA); + kg_write(sc, FMKG_EER, + FMKG_EER_DOUBLE_ECC | FMKG_EER_KEYSIZE_OVF); + + kg_write(sc, FMKG_FDOR, 0); + kg_write(sc, FMKG_GDV0R, 0); + kg_write(sc, FMKG_GDV1R, 0); + + for (i = 0; i < FMKG_MAX_HW_PORTS; i++) { + kg_write(sc, FMKG_IND + FMKG_PE_SP, 0); + error = kg_ar_write(sc, FMKG_AR_GO | FMKG_AR_SEL_PORT | + i | FMKG_AR_PORT_WSEL_SP); + if (error != 0) + return (error); + + kg_write(sc, FMKG_IND + FMKG_PE_CPP, 0); + error = kg_ar_write(sc, FMKG_AR_GO | FMKG_AR_SEL_PORT | + i | FMKG_AR_PORT_WSEL_CPP); + if (error != 0) + return (error); + } + + /* Enable per-scheme error events. */ + kg_write(sc, FMKG_SEER, 0xffffffff); + kg_write(sc, FMKG_SEEER, 0xffffffff); + + /* TODO: Error handling interrupts -- register with FMan */ + + /* Enable the block. */ + kg_write(sc, FMKG_GCR, kg_read(sc, FMKG_GCR) | FMKG_GCR_EN); + + return (0); +} + +void +fman_kg_fini(struct fman_softc *sc) +{ + /* No need for a full teardown, just disable the module. */ + kg_write(sc, FMKG_GCR, 0); + while ((kg_read(sc, FMKG_GSR) & FMKG_GSR_BSY) != 0) + DELAY(1); +} + +int +fman_kg_alloc_hash_scheme(struct fman_softc *sc, int hw_port_id, + uint32_t base_fqid, uint32_t nfqs) +{ + uint8_t scheme_id; + int error, i; + + if (hw_port_id < 0 || hw_port_id >= FMKG_MAX_HW_PORTS) + return (EINVAL); + if (base_fqid == 0 || (base_fqid & ~0x00ffffff) != 0) + return (EINVAL); + if (nfqs == 0 || (nfqs & (nfqs - 1)) != 0) + return (EINVAL); /* not a power of two */ + if ((base_fqid & (nfqs - 1)) != 0) + return (EINVAL); /* base not aligned to nfqs */ + if (sc->sc_kg_port_scheme[hw_port_id] != -1) + return (EBUSY); + + for (i = 0; i < FMKG_MAX_SCHEMES; i++) { + if ((sc->sc_kg_schemes_used & (1U << i)) == 0) { + scheme_id = i; + break; + } + } + if (i == FMKG_MAX_SCHEMES) + return (ENOSPC); + + error = kg_program_scheme(sc, scheme_id, base_fqid, nfqs); + if (error != 0) + return (error); + + error = kg_bind_scheme(sc, hw_port_id, scheme_id, true); + if (error != 0) { + (void)kg_disable_scheme(sc, scheme_id); + return (error); + } + + sc->sc_kg_schemes_used |= (1U << scheme_id); + sc->sc_kg_port_scheme[hw_port_id] = scheme_id; + return (0); +} + +int +fman_kg_free_hash_scheme(struct fman_softc *sc, int hw_port_id) +{ + int8_t scheme_id; + int error; + + if (hw_port_id < 0 || hw_port_id >= FMKG_MAX_HW_PORTS) + return (EINVAL); + scheme_id = sc->sc_kg_port_scheme[hw_port_id]; + if (scheme_id == -1) + return (ENOENT); + + error = kg_bind_scheme(sc, hw_port_id, scheme_id, false); + if (error != 0) + return (error); + error = kg_disable_scheme(sc, scheme_id); + if (error != 0) + return (error); + + sc->sc_kg_schemes_used &= ~(1U << scheme_id); + sc->sc_kg_port_scheme[hw_port_id] = -1; + return (0); +} diff --git a/sys/dev/dpaa/fman_keygen.h b/sys/dev/dpaa/fman_keygen.h new file mode 100644 index 000000000000..0aa44954adee --- /dev/null +++ b/sys/dev/dpaa/fman_keygen.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2026 Justin Hibbits + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _DEV_DPAA_FMAN_KEYGEN_H_ +#define _DEV_DPAA_FMAN_KEYGEN_H_ + +struct fman_softc; + +/* + * Bring up the FMan KeyGen block once per FMan instance. Enables error + * event reporting and clears all port/scheme bindings. Called from + * fman_init() in fman.c. + */ +int fman_kg_init(struct fman_softc *sc); +void fman_kg_fini(struct fman_softc *sc); + +/* + * Configure a hash-distribution scheme for @hw_port_id: RSS-style + * spreading over @nfqs FQs starting at @base_fqid, keyed on the IP + * 5-tuple. @nfqs must be a power of two, @base_fqid must be aligned + * to @nfqs, and both fit in 24 bits (Linux constraint, matches the + * FMKG_SCM_FQB field width). Returns 0 on success or a non-zero + * errno; on success the scheme is bound to the port immediately and + * incoming frames start hashing on the next dequeue cycle. + */ +int fman_kg_alloc_hash_scheme(struct fman_softc *sc, int hw_port_id, + uint32_t base_fqid, uint32_t nfqs); + +/* + * Undo fman_kg_alloc_hash_scheme() for @hw_port_id. Unbinds the + * scheme from the port, disables it, and releases the scheme slot. + * Frames after this point fall through to the port's dflt_fqid. + */ +int fman_kg_free_hash_scheme(struct fman_softc *sc, int hw_port_id); + +#endif /* _DEV_DPAA_FMAN_KEYGEN_H_ */ diff --git a/sys/dev/dpaa/fman_port.c b/sys/dev/dpaa/fman_port.c index 5e71fc2c2268..04ddf22c1250 100644 --- a/sys/dev/dpaa/fman_port.c +++ b/sys/dev/dpaa/fman_port.c @@ -159,18 +159,6 @@ struct fman_port_softc { #define PORT_MAX_FRAME_LENGTH 9600 -#define NIA_ORDER_RESTORE 0x00800000 -#define NIA_ENG_BMI 0x00500000 -#define NIA_ENG_QMI_DEQ 0x00580000 -#define NIA_ENG_QMI_ENQ 0x00540000 -#define NIA_ENG_HWP 0x00440000 -#define NIA_ENG_HWK 0x00480000 -#define NIA_BMI_AC_TX_RELEASE 0x000002c0 -#define NIA_BMI_AC_TX 0x00000274 -#define NIA_BMI_AC_RELEASE 0x000000c0 -#define NIA_BMI_AC_ENQ_FRAME 0x00000002 -#define NIA_BMI_AC_FETCH_ALLFRAME 0x0000020c - #define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \ FM_FD_ERR_FSE | FM_FD_ERR_DIS | \ FM_FD_ERR_EOF | FM_FD_ERR_NSS | \