aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/dpaa/qman.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/dpaa/qman.c')
-rw-r--r--sys/dev/dpaa/qman.c772
1 files changed, 458 insertions, 314 deletions
diff --git a/sys/dev/dpaa/qman.c b/sys/dev/dpaa/qman.c
index fccaa853918b..9143ebde5cb4 100644
--- a/sys/dev/dpaa/qman.c
+++ b/sys/dev/dpaa/qman.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2026 Justin Hibbits
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
/*-
* Copyright (c) 2011-2012 Semihalf.
* All rights reserved.
@@ -29,6 +34,7 @@
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@@ -41,139 +47,276 @@
#include <machine/resource.h>
#include <machine/tlb.h>
-#include "qman.h"
+#include "dpaa_common.h"
#include "portals.h"
+#include "qman.h"
+#include "qman_var.h"
+#include "qman_portal_if.h"
+
+/* Registers */
+#define QCSP_IO_CFG(n) (0x004 + (n) * 16)
+#define IO_CFG_SDEST_M 0x00ff0000
+#define IO_CFG_SDEST_S 16
+#define QMAN_DCP_CFG(n) (0x300 + (n) * 0x10)
+#define DCP_CFG_ED 0x00000100
+#define DCP_CFG_ED_3 0x00001000
+#define QMAN_PFDR_FP_LWIT 0x410
+#define QMAN_PFDR_CFG 0x414
+#define QMAN_SFDR_CFG 0x500
+#define QMAN_MCR 0xb00
+#define MCR_INIT_PFDR 0x01000000
+#define MCR_READ_PFDR 0x02000000
+#define MCR_READ_SFDR 0x03000000
+#define MCR_QUERY_FQD_FILL 0x10000000
+#define MCR_QUERY_FQD_TAGS 0x11000000
+#define MCR_QUERY_FQD_CACHE 0x12000000
+#define MCR_QUERY_WQ 0x20000000
+#define MCR_RSLT_OK 0xf0000000
+#define MCR_RSLT_OK_DATA 0xf1000000
+#define MCR_RSLT_ABRT_INV 0xf4000000
+#define MCR_RSLT_ABRT_DIS 0xf8000000
+#define MCR_RSLT_ABRT_IDX 0xff000000
+#define MCR_RSLT_ABRT_MASK 0xff000000
+#define QMAN_MCP0 0xb04
+#define QMAN_MCP1 0xb08
+#define QMAN_IP_REV_1 0xbf8
+#define IP_MJ_M 0x0000ff00
+#define IP_MJ_S 8
+#define IP_MN_M 0x000000ff
+#define QMAN_FQD_BARE 0xc00
+#define QMAN_FQD_BAR 0xc04
+#define QMAN_FQD_AR 0xc10
+#define AR_EN 0x80000000
+#define QMAN_PFDR_BARE 0xc20
+#define QMAN_PFDR_BAR 0xc24
+#define QMAN_PFDR_AR 0xc30
+#define QMAN_QCSP_BARE 0xc80
+#define QMAN_QCSP_BAR 0xc84
+#define QMAN_QCSP_AR 0xc90
+#define QMAN_CI_SCHED_CFG 0xd00
+#define CI_SCHED_CFG_SW 0x80000000
+#define CI_SCHED_CFG_SRCCIV 0x04000000 /* Recommended */
+#define CI_SCHED_CFG_SRQ_W_M 0x00000700
+#define CI_SCHED_CFG_SRQ_W_S 8
+#define CI_SCHED_CFG_RW_W_M 0x00000070
+#define CI_SCHED_CFG_RW_W_S 4
+#define CI_SCHED_CFG_BMAN_W_M 0x00000007
+#define QMAN_ERR_ISR 0xe00
+#define QMAN_ERR_IER 0xe04
+#define QCSP_IO_CFG_3(n) (0x1004 + (n) * 16)
+
+/* Software portals. Cache-inhibited registers */
+
+#define QCSP_DQRR_PDQCR 0x05c
+
+/* Software portals. Cache-enabled registers */
+
+#define QCSP_VERB_INIT_FQ_PARK 0x40
+#define QCSP_VERB_INIT_FQ_SCHED 0x41
+#define QCSP_VERB_QUERY_FQ 0x44
+#define QCSP_VERB_QUERY_FQ_NP 0x45
+#define QCSP_VERB_ALTER_FQ_SCHED 0x48
+#define QCSP_VERB_ALTER_FQ_FE 0x49
+#define QCSP_VERB_ALTER_FQ_RETIRE 0x4a
+#define QCSP_VERB_ALTER_FQ_TAKE_OUT 0x4b
+#define QCSP_VERB_ALTER_FQ_RETIRE_CTXB 0x4c
+#define QCSP_VERB_ALTER_FQ_XON 0x4d
+#define QCSP_VERB_ALTER_FQ_XOFF 0x4e
+
+/* Init FQ */
+#define QCSP_INIT_FQ_WE_OAC 0x0100
+#define QCSP_INIT_FQ_WE_ORPC 0x0080
+#define QCSP_INIT_FQ_WE_CGID 0x0040
+#define QCSP_INIT_FQ_WE_FQ_CTRL 0x0020
+#define QCSP_INIT_FQ_WE_DEST_WQ 0x0010
+#define QCSP_INIT_FQ_WE_ICS_CRED 0x0008
+#define QCSP_INIT_FQ_WE_TD_THRESH 0x0004
+#define QCSP_INIT_FQ_WE_CONTEXT_B 0x0002
+#define QCSP_INIT_FQ_WE_CONTEXT_A 0x0001
+
+#define QMAN_MC_RES_OK 0xf0
+
+#define QMAN_MC_AFQS_NE 0x01
+
+/* Init FQ options */
+#define QM_FQCTRL_CGE 0x0400
+#define QM_FQCTRL_TDE 0x0200
+#define QM_FQCTRL_ORP 0x0100
+#define QM_FQCTRL_CTXASTASH 0x0080
+#define QM_FQCTRL_CPCSTASH 0x0040
+#define QM_FQCTRL_FORCESFDR 0x0008
+#define QM_FQCTRL_AVOIDBLOCK 0x0004
+#define QM_FQCTRL_HOLDACTIVE 0x0002
+#define QM_FQCTRL_LIC 0x0001
+
+#define QMAN_CHANNEL_POOL1_REV1 0x21
+#define QMAN_CHANNEL_POOL1_REV3 0x401
+
+#define QMAN_PFDR_MAX 0xfffeff
+
+/* P1023 has only 3 pool channels, but we don't support that SoC. */
+#define QMAN_POOL_CHANNELS 15
+
+/* P1023 only supports 64 congestion groups... */
+#define QMAN_CGRS 256
-extern struct dpaa_portals_softc *qp_sc;
static struct qman_softc *qman_sc;
-extern t_Handle qman_portal_setup(struct qman_softc *qsc);
+static MALLOC_DEFINE(M_QMAN, "qman", "DPAA Queue Manager structures");
+
+int qman_channel_base;
+int qman_total_fqids;
+struct qman_fq **qman_fq_list;
+
+/* Entries sorted right-to-left in bit order of the ISR */
+static const char * const qman_errors[] = {
+ "Invalid enqueue queue",
+ "Invalid enqueue channel!",
+ "Invalid enqueue state",
+ "Invalid enqueue overflow",
+ "Invalid enqueue configuration",
+ NULL,
+ NULL,
+ NULL,
+ "Invalid dequeue queue",
+ "Invalid dequeue source",
+ "Invalid dequeue FQ",
+ "Invalid dequeue direct connect portal",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Invalid command verb",
+ "Invalid FQ flow control state",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Insufficient free PFDRs",
+ "Single-bit ECC error",
+ "Multi-bit ECC error",
+ "PFDR low watermark",
+ "Invalid target transaction",
+ "Initiator data error",
+ NULL,
+ NULL
+};
static void
-qman_exception(t_Handle app, e_QmExceptions exception)
+qman_isr(void *arg)
{
- struct qman_softc *sc;
- const char *message;
+ struct qman_softc *sc = arg;
+ uint32_t ier, isr, isr_bit;
+ int i;
- sc = app;
+ ier = bus_read_4(sc->sc_rres, QMAN_ERR_IER);
+ isr = bus_read_4(sc->sc_rres, QMAN_ERR_ISR);
- switch (exception) {
- case e_QM_EX_CORENET_INITIATOR_DATA:
- message = "Initiator Data Error";
- break;
- case e_QM_EX_CORENET_TARGET_DATA:
- message = "CoreNet Target Data Error";
- break;
- case e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION:
- message = "Invalid Target Transaction";
- break;
- case e_QM_EX_PFDR_THRESHOLD:
- message = "PFDR Low Watermark Interrupt";
- break;
- case e_QM_EX_PFDR_ENQUEUE_BLOCKED:
- message = "PFDR Enqueues Blocked Interrupt";
- break;
- case e_QM_EX_SINGLE_ECC:
- message = "Single Bit ECC Error Interrupt";
- break;
- case e_QM_EX_MULTI_ECC:
- message = "Multi Bit ECC Error Interrupt";
- break;
- case e_QM_EX_INVALID_COMMAND:
- message = "Invalid Command Verb Interrupt";
- break;
- case e_QM_EX_DEQUEUE_DCP:
- message = "Invalid Dequeue Direct Connect Portal Interrupt";
- break;
- case e_QM_EX_DEQUEUE_FQ:
- message = "Invalid Dequeue FQ Interrupt";
- break;
- case e_QM_EX_DEQUEUE_SOURCE:
- message = "Invalid Dequeue Source Interrupt";
- break;
- case e_QM_EX_DEQUEUE_QUEUE:
- message = "Invalid Dequeue Queue Interrupt";
- break;
- case e_QM_EX_ENQUEUE_OVERFLOW:
- message = "Invalid Enqueue Overflow Interrupt";
- break;
- case e_QM_EX_ENQUEUE_STATE:
- message = "Invalid Enqueue State Interrupt";
- break;
- case e_QM_EX_ENQUEUE_CHANNEL:
- message = "Invalid Enqueue Channel Interrupt";
- break;
- case e_QM_EX_ENQUEUE_QUEUE:
- message = "Invalid Enqueue Queue Interrupt";
- break;
- case e_QM_EX_CG_STATE_CHANGE:
- message = "CG change state notification";
- break;
- default:
- message = "Unknown error";
+ if ((ier & isr) == 0)
+ return;
+
+ isr_bit = (isr & ier);
+ for (i = 0; isr_bit != 0; i++, isr_bit >>= 1) {
+ if (isr_bit & 1)
+ device_printf(sc->sc_dev, "%s", qman_errors[i]);
}
- device_printf(sc->sc_dev, "QMan Exception: %s.\n", message);
+ bus_write_4(sc->sc_rres, QMAN_ERR_ISR, isr);
}
-/**
- * General received frame callback.
- * This is called, when user did not register his own callback for a given
- * frame queue range (fqr).
- */
-e_RxStoreResponse
-qman_received_frame_callback(t_Handle app, t_Handle qm_fqr, t_Handle qm_portal,
- uint32_t fqid_offset, t_DpaaFD *frame)
+
+/* Set up reserved memory configuration for PFDR and FQD, per `off`. */
+static int
+qman_set_memory(struct qman_softc *sc, vm_paddr_t pa,
+ vm_size_t size, bus_size_t off)
{
- struct qman_softc *sc;
+ uint32_t bar, bare;
+ vm_paddr_t old_bar;
+
+ /*
+ * Register offsets:
+ * 0 - BARE
+ * 4 - BAR
+ * 0x10 - AR
+ */
+ bare = bus_read_4(sc->sc_rres, off);
+ bar = bus_read_4(sc->sc_rres, off + 4);
+ old_bar = (vm_paddr_t)bare << 32 | bar;
- sc = app;
+ if (old_bar != 0 && old_bar != pa) {
+ device_printf(sc->sc_dev, "QMan BAR already initialized!\n");
+ return (ENOMEM);
+ } else if (old_bar == pa)
+ return (EEXIST);
- device_printf(sc->sc_dev, "dummy callback for received frame.\n");
- return (e_RX_STORE_RESPONSE_CONTINUE);
+ /*
+ * Zero the memory and flush cache through DMAP. QMan accesses the
+ * memory as non-coherent.
+ */
+ memset((void *)PHYS_TO_DMAP(pa), 0, size);
+ cpu_flush_dcache((void *)PHYS_TO_DMAP(pa), size);
+
+ bus_write_4(sc->sc_rres, off, pa >> 32);
+ bus_write_4(sc->sc_rres, off + 4, (uint32_t)pa);
+ bus_write_4(sc->sc_rres, off + 0x10, AR_EN | (ilog2(size) - 1));
+
+ return (0);
}
-/**
- * General rejected frame callback.
- * This is called, when user did not register his own callback for a given
- * frame queue range (fqr).
+/*
+ * Set up PFDR structures. Some things to keep in mind:
+ * - npfdr is the total number of PFDRs in the private memory. PFDRs are 64
+ * bytes in size, so npfdr is (pfdr_sz/64).
+ * - PFDR 0-7 are reserved, so the base starts at 8, not 0, so we adjust
+ * internally.
+ * - The second parameter is the last PFDR, not the number of PFDRs, so needs to
+ * be adjusted down one more, so subtract 9.
*/
-e_RxStoreResponse
-qman_rejected_frame_callback(t_Handle app, t_Handle qm_fqr, t_Handle qm_portal,
- uint32_t fqid_offset, t_DpaaFD *frame,
- t_QmRejectedFrameInfo *qm_rejected_frame_info)
+static int
+qman_setup_pfdr(struct qman_softc *sc, int npfdr)
{
- struct qman_softc *sc;
+ uint32_t res;
+
+ npfdr = min(npfdr, QMAN_PFDR_MAX);
+ bus_write_4(sc->sc_rres, QMAN_MCP0, 8);
+ bus_write_4(sc->sc_rres, QMAN_MCP1, npfdr - 9);
+ bus_write_4(sc->sc_rres, QMAN_MCR, MCR_INIT_PFDR);
+
+ for (int timeout = 100000; timeout > 0; timeout--) {
+ DELAY(1);
+ res = bus_read_4(sc->sc_rres, QMAN_MCR);
+ if (res >= MCR_RSLT_OK)
+ break;
+ }
- sc = app;
+ if (res < MCR_RSLT_OK)
+ return (EBUSY);
+ if (res == MCR_RSLT_OK)
+ return (0);
- device_printf(sc->sc_dev, "dummy callback for rejected frame.\n");
- return (e_RX_STORE_RESPONSE_CONTINUE);
+ return (ENXIO);
}
int
qman_attach(device_t dev)
{
struct qman_softc *sc;
- t_QmParam qp;
- t_Error error;
- t_QmRevisionInfo rev;
+ int error;
+ vm_paddr_t fqd_pa, pfdr_pa;
+ vm_size_t fqd_sz, pfdr_sz;
+ int qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV1;
+ uint32_t ver;
+ uint32_t nfqd;
+ bool qman3 = false;
sc = device_get_softc(dev);
sc->sc_dev = dev;
qman_sc = sc;
- if (XX_MallocSmartInit() != E_OK) {
- device_printf(dev, "could not initialize smart allocator.\n");
- return (ENXIO);
- }
-
- sched_pin();
-
/* Allocate resources */
sc->sc_rrid = 0;
- sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->sc_rrid, 0, ~0, QMAN_CCSR_SIZE, RF_ACTIVE);
+ sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE);
if (sc->sc_rres == NULL) {
device_printf(dev, "could not allocate memory.\n");
goto err;
@@ -186,57 +329,79 @@ qman_attach(device_t dev)
device_printf(dev, "could not allocate error interrupt.\n");
goto err;
}
+ error = dpaa_map_private_memory(dev, 0, "fsl,qman-fqd",
+ &fqd_pa, &fqd_sz);
+ error = dpaa_map_private_memory(dev, 1, "fsl,qman-pfdr",
+ &pfdr_pa, &pfdr_sz);
+
+ bzero((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz);
+ cpu_flush_dcache((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz);
+ /*
+ * FQDs are 64 bytes in size, with 24 bit pointers, so FQIDs are 24
+ * bits, fits fine in a uint32_t.
+ */
+ nfqd = fqd_sz / 64;
+ qman_total_fqids = nfqd;
+ qman_channel_base = qman_channel_pool1;
+ qman_fq_list = malloc(nfqd * sizeof(struct qman_fq *), M_QMAN,
+ M_WAITOK);
- if (qp_sc == NULL)
+ error = qman_set_memory(sc, fqd_pa, fqd_sz, QMAN_FQD_BARE);
+ if (error != 0 && error != EEXIST)
goto err;
+ error = qman_set_memory(sc, pfdr_pa, pfdr_sz, QMAN_PFDR_BARE);
+ if (error != 0 && error != EEXIST)
+ goto err;
+ if (error == 0) {
+ /* Initialize PFDRs if it hasn't been initialized before */
+ error = qman_setup_pfdr(sc, pfdr_sz / 64);
+ if (error != 0)
+ goto err;
+ /* Magic constant from documentation */
+ bus_write_4(sc->sc_rres, QMAN_PFDR_CFG, 64);
+ }
- dpaa_portal_map_registers(qp_sc);
+ bus_write_4(sc->sc_rres, QMAN_ERR_ISR, 0xffffffff);
+ bus_write_4(sc->sc_rres, QMAN_ERR_IER, 0xffffffff);
- /* Initialize QMan */
- qp.guestId = NCSW_MASTER_ID;
- qp.baseAddress = rman_get_bushandle(sc->sc_rres);
- qp.swPortalsBaseAddress = rman_get_bushandle(qp_sc->sc_rres[0]);
- qp.liodn = 0;
- qp.totalNumOfFqids = QMAN_MAX_FQIDS;
- qp.fqdMemPartitionId = NCSW_MASTER_ID;
- qp.pfdrMemPartitionId = NCSW_MASTER_ID;
- qp.f_Exception = qman_exception;
- qp.h_App = sc;
- qp.errIrq = (uintptr_t)sc->sc_ires;
- qp.partFqidBase = QMAN_FQID_BASE;
- qp.partNumOfFqids = QMAN_MAX_FQIDS;
- qp.partCgsBase = 0;
- qp.partNumOfCgs = 0;
+ ver = bus_read_4(sc->sc_rres, QMAN_IP_REV_1);
+ sc->sc_qman_major = ((ver & IP_MJ_M) >> IP_MJ_S);
+ if (sc->sc_qman_major >= 3)
+ qman3 = true;
- sc->sc_qh = QM_Config(&qp);
- if (sc->sc_qh == NULL) {
- device_printf(dev, "could not be configured\n");
- goto err;
- }
+ if (qman3)
+ qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV3;
- error = QM_Init(sc->sc_qh);
- if (error != E_OK) {
- device_printf(dev, "could not be initialized\n");
+ sc->sc_qman_base_channel = qman_channel_pool1;
+
+ sc->sc_fqalloc =
+ vmem_create("qman-fqalloc", 1, nfqd - 1, 1, 0, M_WAITOK);
+ sc->sc_qpalloc =
+ vmem_create("qman-fqalloc", qman_channel_pool1,
+ QMAN_POOL_CHANNELS, 1, 0, M_WAITOK);
+ sc->sc_cgalloc = vmem_create("qman->cgalloc", 0, QMAN_CGRS,
+ 1, 0, M_WAITOK);
+
+ if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_NET, NULL, qman_isr,
+ sc, &sc->sc_intr_cookie) != 0)
goto err;
- }
- error = QM_GetRevision(sc->sc_qh, &rev);
- if (error != E_OK) {
- device_printf(dev, "could not get QMan revision\n");
+ if (error != 0) {
+ device_printf(dev, "could not be initialized\n");
goto err;
}
+ bus_write_4(sc->sc_rres, QMAN_DCP_CFG(0),
+ qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED);
+ bus_write_4(sc->sc_rres, QMAN_DCP_CFG(1),
+ qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED);
- device_printf(dev, "Hardware version: %d.%d.\n",
- rev.majorRev, rev.minorRev);
+ bus_write_4(sc->sc_rres, 0xd00, 0x80000322);
- sched_unpin();
-
- qman_portal_setup(sc);
+ /* TODO: DO we need a taskqueue? Allocate here if so */
return (0);
err:
- sched_unpin();
qman_detach(dev);
return (ENXIO);
}
@@ -248,11 +413,15 @@ qman_detach(device_t dev)
sc = device_get_softc(dev);
- if (sc->sc_qh)
- QM_Free(sc->sc_qh);
+ if (sc->sc_fqalloc != NULL)
+ vmem_destroy(sc->sc_fqalloc);
+ if (sc->sc_qpalloc != NULL)
+ vmem_destroy(sc->sc_qpalloc);
+ if (sc->sc_cgalloc != NULL)
+ vmem_destroy(sc->sc_cgalloc);
- if (sc->sc_ires != NULL)
- XX_DeallocIntr((uintptr_t)sc->sc_ires);
+ if (sc->sc_intr_cookie != NULL)
+ bus_teardown_intr(dev, sc->sc_ires, sc->sc_intr_cookie);
if (sc->sc_ires != NULL)
bus_release_resource(dev, SYS_RES_IRQ,
@@ -262,6 +431,9 @@ qman_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY,
sc->sc_rrid, sc->sc_rres);
+ free(qman_fq_list, M_QMAN);
+ qman_fq_list = NULL;
+
return (0);
}
@@ -286,261 +458,233 @@ qman_shutdown(device_t dev)
return (0);
}
+int
+qman_alloc_channel(void)
+{
+ struct qman_softc *sc = qman_sc;
+ vmem_addr_t channel;
+
+ vmem_alloc(sc->sc_qpalloc, 1, M_BESTFIT | M_WAITOK, &channel);
+
+ return (channel);
+}
+
+void
+qman_free_channel(int channel)
+{
+ struct qman_softc *sc = qman_sc;
+
+ vmem_free(sc->sc_qpalloc, channel, 1);
+}
/**
* @group QMan API functions implementation.
* @{
*/
-t_Handle
-qman_fqr_create(uint32_t fqids_num, e_QmFQChannel channel, uint8_t wq,
+struct qman_fq *
+qman_fq_from_index(uint32_t fqid)
+{
+ if (fqid > qman_total_fqids)
+ return (NULL);
+ return (qman_fq_list[fqid]);
+}
+
+/* Allocate and initialize an FQ Range */
+struct qman_fq *
+qman_fq_create(uint32_t fqids_num, int channel, uint8_t wq,
bool force_fqid, uint32_t fqid_or_align, bool init_parked,
bool hold_active, bool prefer_in_cache, bool congst_avoid_ena,
- t_Handle congst_group, int8_t overhead_accounting_len,
+ void *congst_group, int8_t overhead_accounting_len,
uint32_t tail_drop_threshold)
{
+ union qman_mc_command cmd;
struct qman_softc *sc;
- t_QmFqrParams fqr;
- t_Handle fqrh, portal;
+ union qman_mc_result *res;
+ struct qman_fq *fqh;
+ device_t portal;
+ vmem_addr_t fqid_base;
+ uint8_t rslt;
sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- goto err;
+ if (fqids_num != 1) {
+ device_printf(sc->sc_dev,
+ "Only one fq allocation allowed currently\n");
+ return (NULL);
}
- fqr.h_Qm = sc->sc_qh;
- fqr.h_QmPortal = portal;
- fqr.initParked = init_parked;
- fqr.holdActive = hold_active;
- fqr.preferInCache = prefer_in_cache;
+ bzero(&cmd, sizeof(cmd));
+ vmem_alloc(sc->sc_fqalloc, fqids_num, M_BESTFIT | M_WAITOK, &fqid_base);
+ cmd.init_fq.fqid = fqid_base;
+ cmd.init_fq.count = fqids_num - 1;
+ cmd.init_fq.dest_chan = channel;
+ cmd.init_fq.dest_wq = wq;
+ cmd.init_fq.we_mask = QCSP_INIT_FQ_WE_DEST_WQ | QCSP_INIT_FQ_WE_FQ_CTRL;
+ if (init_parked)
+ cmd.init_fq.verb = QCSP_VERB_INIT_FQ_PARK;
+ else
+ cmd.init_fq.verb = QCSP_VERB_INIT_FQ_SCHED;
+ cmd.init_fq.fq_ctrl = (prefer_in_cache ? QM_FQCTRL_LIC : 0) |
+ (hold_active ? QM_FQCTRL_HOLDACTIVE : 0) |
+ (congst_avoid_ena ? QM_FQCTRL_AVOIDBLOCK : 0);
- /* We do not support stashing */
- fqr.useContextAForStash = FALSE;
- fqr.p_ContextA = 0;
- fqr.p_ContextB = 0;
+ critical_enter();
- fqr.channel = channel;
- fqr.wq = wq;
- fqr.shadowMode = FALSE;
- fqr.numOfFqids = fqids_num;
+ /* Ensure we have got QMan port initialized */
+ portal = DPCPU_GET(qman_affine_portal);
+ res = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd);
- /* FQID */
- fqr.useForce = force_fqid;
- if (force_fqid) {
- fqr.qs.frcQ.fqid = fqid_or_align;
- } else {
- fqr.qs.nonFrcQs.align = fqid_or_align;
- }
+ rslt = 0;
+ if (res != NULL)
+ rslt = res->init_fq.rslt;
- /* Congestion Avoidance */
- fqr.congestionAvoidanceEnable = congst_avoid_ena;
- if (congst_avoid_ena) {
- fqr.congestionAvoidanceParams.h_QmCg = congst_group;
- fqr.congestionAvoidanceParams.overheadAccountingLength =
- overhead_accounting_len;
- fqr.congestionAvoidanceParams.fqTailDropThreshold =
- tail_drop_threshold;
- } else {
- fqr.congestionAvoidanceParams.h_QmCg = 0;
- fqr.congestionAvoidanceParams.overheadAccountingLength = 0;
- fqr.congestionAvoidanceParams.fqTailDropThreshold = 0;
- }
-
- fqrh = QM_FQR_Create(&fqr);
- if (fqrh == NULL) {
- device_printf(sc->sc_dev, "could not create Frame Queue Range"
- "\n");
+ critical_exit();
+ if (res == NULL || rslt != QMAN_MC_RES_OK) {
+ vmem_free(sc->sc_fqalloc, fqid_base, fqids_num);
goto err;
}
- sc->sc_fqr_cpu[QM_FQR_GetFqid(fqrh)] = PCPU_GET(cpuid);
+ fqh = malloc(sizeof(*fqh), M_QMAN, M_WAITOK | M_ZERO);
+ fqh->fqid = fqid_base;
- sched_unpin();
+ qman_fq_list[fqid_base] = fqh;
- return (fqrh);
+ return (fqh);
err:
- sched_unpin();
return (NULL);
}
-t_Error
-qman_fqr_free(t_Handle fqr)
+static int
+qman_fq_retire(device_t portal, struct qman_fq *fq)
{
- struct qman_softc *sc;
- t_Error error;
-
- sc = qman_sc;
- thread_lock(curthread);
- sched_bind(curthread, sc->sc_fqr_cpu[QM_FQR_GetFqid(fqr)]);
- thread_unlock(curthread);
+ union qman_mc_command cmd;
+ union qman_mc_result *rr;
- error = QM_FQR_Free(fqr);
+ bzero(&cmd, sizeof(cmd));
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
+ cmd.alter_fqs.verb = QCSP_VERB_ALTER_FQ_RETIRE;
+ cmd.alter_fqs.fqid = fq->fqid;
+ rr = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd);
+ if (rr == NULL)
+ return (ETIMEDOUT);
- return (error);
-}
-
-t_Error
-qman_fqr_register_cb(t_Handle fqr, t_QmReceivedFrameCallback *callback,
- t_Handle app)
-{
- struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
-
- sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
+ if (rr->alter_fqs.rslt == QMAN_MC_RES_OK) {
+ if (rr->alter_fqs.fqs & QMAN_MC_AFQS_NE) {
+ /* TODO: Drain.... */
+ }
+ return (0);
}
- error = QM_FQR_RegisterCB(fqr, callback, app);
-
- sched_unpin();
-
- return (error);
+ return (0);
}
-t_Error
-qman_fqr_enqueue(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame)
+int
+qman_fq_free(struct qman_fq *fq)
{
struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
+ int error;
sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
- }
-
- error = QM_FQR_Enqueue(fqr, portal, fqid_off, frame);
- sched_unpin();
+ critical_enter();
+ error = qman_fq_retire(DPCPU_GET(qman_affine_portal), fq);
+ /* TODO: Take FQ out of service. */
+ critical_exit();
+ if (error != 0)
+ return (error);
+ vmem_free(sc->sc_fqalloc, fq->fqid, 1);
+ qman_fq_list[fq->fqid] = NULL;
+ free(fq, M_QMAN);
- return (error);
+ return (0);
}
-uint32_t
-qman_fqr_get_counter(t_Handle fqr, uint32_t fqid_off,
- e_QmFqrCounters counter)
+int
+qman_fq_register_cb(struct qman_fq *fq, qman_cb_dqrr callback,
+ void *ctx)
{
- struct qman_softc *sc;
- uint32_t val;
- t_Handle portal;
-
- sc = qman_sc;
- sched_pin();
-
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (0);
- }
+ fq->cb.dqrr = callback;
+ fq->cb.ctx = ctx;
- val = QM_FQR_GetCounter(fqr, portal, fqid_off, counter);
-
- sched_unpin();
-
- return (val);
+ return (0);
}
-t_Error
-qman_fqr_pull_frame(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame)
+int
+qman_fq_enqueue(struct qman_fq *fq, struct dpaa_fd *frame)
{
struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
+ int error;
+ void *portal;
sc = qman_sc;
- sched_pin();
+ critical_enter();
/* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
+ portal = DPCPU_GET(qman_affine_portal);
if (portal == NULL) {
device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
+ critical_exit();
+ return (ENXIO);
}
- error = QM_FQR_PullFrame(fqr, portal, fqid_off, frame);
+ error = QMAN_PORTAL_ENQUEUE(portal, fq, frame);
- sched_unpin();
+ critical_exit();
return (error);
}
uint32_t
-qman_fqr_get_base_fqid(t_Handle fqr)
+qman_fq_get_fqid(struct qman_fq *fq)
{
- struct qman_softc *sc;
- uint32_t val;
- t_Handle portal;
+ return (fq->fqid);
+}
- sc = qman_sc;
- sched_pin();
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (0);
- }
+uint32_t
+qman_fq_get_counter(struct qman_fq *fq, int counter)
+{
+ union qman_mc_result *cmd_res;
+ union qman_mc_command command;
+ device_t portal;
+ u_int ret = 0;
- val = QM_FQR_GetFqid(fqr);
+ bzero(&command, sizeof(command));
+ command.query_fq_np.verb = QCSP_VERB_QUERY_FQ_NP;
+ command.query_fq_np.fqid = fq->fqid;
+ critical_enter();
+ portal = DPCPU_GET(qman_affine_portal);
+ cmd_res = QMAN_PORTAL_MC_SEND_RAW(portal, &command);
+ if (counter == QMAN_COUNTER_FRAME)
+ ret = cmd_res->query_fq_np.frm_cnt;
+ else if (counter == QMAN_COUNTER_BYTES)
+ ret = cmd_res->query_fq_np.byte_cnt;
- sched_unpin();
+ critical_exit();
- return (val);
+ return (ret);
}
-t_Error
-qman_poll(e_QmPortalPollSource source)
+void
+qman_set_sdest(uint16_t channel, int cpu)
{
- struct qman_softc *sc;
- t_Error error;
- t_Handle portal;
-
- sc = qman_sc;
- sched_pin();
+ struct qman_softc *sc = qman_sc;
+ uint32_t reg;
- /* Ensure we have got QMan port initialized */
- portal = qman_portal_setup(sc);
- if (portal == NULL) {
- device_printf(sc->sc_dev, "could not setup QMan portal\n");
- sched_unpin();
- return (E_NOT_SUPPORTED);
+ if (sc->sc_qman_major >= 3) {
+ reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG_3(channel));
+ reg &= IO_CFG_SDEST_M;
+ reg |= (cpu << IO_CFG_SDEST_S);
+ bus_write_4(sc->sc_rres, QCSP_IO_CFG_3(channel), reg);
+ } else {
+ reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG(channel));
+ reg &= IO_CFG_SDEST_M;
+ reg |= (cpu << IO_CFG_SDEST_S);
+ bus_write_4(sc->sc_rres, QCSP_IO_CFG(channel), reg);
}
-
- error = QM_Poll(sc->sc_qh, source);
-
- sched_unpin();
-
- return (error);
}
/*