1 /* 2 * Copyright (c) 2026 Justin Hibbits 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 /*- 7 * Copyright (c) 2011-2012 Semihalf. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/bus.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/module.h> 39 #include <sys/mutex.h> 40 #include <sys/proc.h> 41 #include <sys/pcpu.h> 42 #include <sys/rman.h> 43 #include <sys/sched.h> 44 #include <sys/smp.h> 45 46 #include <machine/bus.h> 47 #include <machine/resource.h> 48 #include <machine/tlb.h> 49 50 #include "dpaa_common.h" 51 #include "portals.h" 52 #include "qman.h" 53 #include "qman_var.h" 54 #include "qman_portal_if.h" 55 56 /* Registers */ 57 #define QCSP_IO_CFG(n) (0x004 + (n) * 16) 58 #define IO_CFG_SDEST_M 0x00ff0000 59 #define IO_CFG_SDEST_S 16 60 #define QMAN_DCP_CFG(n) (0x300 + (n) * 0x10) 61 #define DCP_CFG_ED 0x00000100 62 #define DCP_CFG_ED_3 0x00001000 63 #define QMAN_PFDR_FP_LWIT 0x410 64 #define QMAN_PFDR_CFG 0x414 65 #define QMAN_SFDR_CFG 0x500 66 #define QMAN_MCR 0xb00 67 #define MCR_INIT_PFDR 0x01000000 68 #define MCR_READ_PFDR 0x02000000 69 #define MCR_READ_SFDR 0x03000000 70 #define MCR_QUERY_FQD_FILL 0x10000000 71 #define MCR_QUERY_FQD_TAGS 0x11000000 72 #define MCR_QUERY_FQD_CACHE 0x12000000 73 #define MCR_QUERY_WQ 0x20000000 74 #define MCR_RSLT_OK 0xf0000000 75 #define MCR_RSLT_OK_DATA 0xf1000000 76 #define MCR_RSLT_ABRT_INV 0xf4000000 77 #define MCR_RSLT_ABRT_DIS 0xf8000000 78 #define MCR_RSLT_ABRT_IDX 0xff000000 79 #define MCR_RSLT_ABRT_MASK 0xff000000 80 #define QMAN_MCP0 0xb04 81 #define QMAN_MCP1 0xb08 82 #define QMAN_IP_REV_1 0xbf8 83 #define IP_MJ_M 0x0000ff00 84 #define IP_MJ_S 8 85 #define IP_MN_M 0x000000ff 86 #define QMAN_FQD_BARE 0xc00 87 #define QMAN_FQD_BAR 0xc04 88 #define QMAN_FQD_AR 0xc10 89 #define AR_EN 0x80000000 90 #define QMAN_PFDR_BARE 0xc20 91 #define QMAN_PFDR_BAR 0xc24 92 #define QMAN_PFDR_AR 0xc30 93 #define QMAN_QCSP_BARE 0xc80 94 #define QMAN_QCSP_BAR 0xc84 95 #define QMAN_QCSP_AR 0xc90 96 #define QMAN_CI_SCHED_CFG 0xd00 97 #define CI_SCHED_CFG_SW 0x80000000 98 #define CI_SCHED_CFG_SRCCIV 0x04000000 /* Recommended */ 99 #define CI_SCHED_CFG_SRQ_W_M 0x00000700 100 #define CI_SCHED_CFG_SRQ_W_S 8 101 #define CI_SCHED_CFG_RW_W_M 0x00000070 102 #define CI_SCHED_CFG_RW_W_S 4 103 #define CI_SCHED_CFG_BMAN_W_M 0x00000007 104 #define QMAN_ERR_ISR 0xe00 105 #define QMAN_ERR_IER 0xe04 106 #define QCSP_IO_CFG_3(n) (0x1004 + (n) * 16) 107 108 /* Software portals. Cache-inhibited registers */ 109 110 #define QCSP_DQRR_PDQCR 0x05c 111 112 /* Software portals. Cache-enabled registers */ 113 114 /* 115 * Context_A stashing config. 116 */ 117 #define QM_STASHING_EXCL_ANNOTATION 0x04 118 #define QM_STASHING_EXCL_DATA 0x02 119 #define QM_STASHING_EXCL_CONTEXT 0x01 120 121 #define QMAN_CHANNEL_POOL1_REV1 0x21 122 #define QMAN_CHANNEL_POOL1_REV3 0x401 123 124 #define QMAN_PFDR_MAX 0xfffeff 125 126 /* P1023 has only 3 pool channels, but we don't support that SoC. */ 127 #define QMAN_POOL_CHANNELS 15 128 129 /* P1023 only supports 64 congestion groups... */ 130 #define QMAN_CGRS 256 131 132 static struct qman_softc *qman_sc; 133 134 static MALLOC_DEFINE(M_QMAN, "qman", "DPAA Queue Manager structures"); 135 136 int qman_channel_base; 137 int qman_total_fqids; 138 struct qman_fq **qman_fq_list; 139 140 /* Entries sorted right-to-left in bit order of the ISR */ 141 static const char * const qman_errors[] = { 142 "Invalid enqueue queue", 143 "Invalid enqueue channel!", 144 "Invalid enqueue state", 145 "Invalid enqueue overflow", 146 "Invalid enqueue configuration", 147 NULL, 148 NULL, 149 NULL, 150 "Invalid dequeue queue", 151 "Invalid dequeue source", 152 "Invalid dequeue FQ", 153 "Invalid dequeue direct connect portal", 154 NULL, 155 NULL, 156 NULL, 157 NULL, 158 "Invalid command verb", 159 "Invalid FQ flow control state", 160 NULL, 161 NULL, 162 NULL, 163 NULL, 164 NULL, 165 "Insufficient free PFDRs", 166 "Single-bit ECC error", 167 "Multi-bit ECC error", 168 "PFDR low watermark", 169 "Invalid target transaction", 170 "Initiator data error", 171 NULL, 172 NULL 173 }; 174 175 static void 176 qman_isr(void *arg) 177 { 178 struct qman_softc *sc = arg; 179 uint32_t ier, isr, isr_bit; 180 int i; 181 182 ier = bus_read_4(sc->sc_rres, QMAN_ERR_IER); 183 isr = bus_read_4(sc->sc_rres, QMAN_ERR_ISR); 184 185 if ((ier & isr) == 0) 186 return; 187 188 isr_bit = (isr & ier); 189 for (i = 0; isr_bit != 0; i++, isr_bit >>= 1) { 190 if (isr_bit & 1) 191 device_printf(sc->sc_dev, "%s", qman_errors[i]); 192 } 193 194 bus_write_4(sc->sc_rres, QMAN_ERR_ISR, isr); 195 } 196 197 198 /* Set up reserved memory configuration for PFDR and FQD, per `off`. */ 199 static int 200 qman_set_memory(struct qman_softc *sc, vm_paddr_t pa, 201 vm_size_t size, bus_size_t off) 202 { 203 uint32_t bar, bare; 204 vm_paddr_t old_bar; 205 206 /* 207 * Register offsets: 208 * 0 - BARE 209 * 4 - BAR 210 * 0x10 - AR 211 */ 212 bare = bus_read_4(sc->sc_rres, off); 213 bar = bus_read_4(sc->sc_rres, off + 4); 214 old_bar = (vm_paddr_t)bare << 32 | bar; 215 216 if (old_bar != 0 && old_bar != pa) { 217 device_printf(sc->sc_dev, "QMan BAR already initialized!\n"); 218 return (ENOMEM); 219 } else if (old_bar == pa) 220 return (EEXIST); 221 222 /* 223 * Zero the memory and flush cache through DMAP. QMan accesses the 224 * memory as non-coherent. 225 */ 226 memset((void *)PHYS_TO_DMAP(pa), 0, size); 227 cpu_flush_dcache((void *)PHYS_TO_DMAP(pa), size); 228 229 bus_write_4(sc->sc_rres, off, pa >> 32); 230 bus_write_4(sc->sc_rres, off + 4, (uint32_t)pa); 231 bus_write_4(sc->sc_rres, off + 0x10, AR_EN | (ilog2(size) - 1)); 232 233 return (0); 234 } 235 236 /* 237 * Set up PFDR structures. Some things to keep in mind: 238 * - npfdr is the total number of PFDRs in the private memory. PFDRs are 64 239 * bytes in size, so npfdr is (pfdr_sz/64). 240 * - PFDR 0-7 are reserved, so the base starts at 8, not 0, so we adjust 241 * internally. 242 * - The second parameter is the last PFDR, not the number of PFDRs, so needs to 243 * be adjusted down one more, so subtract 9. 244 */ 245 static int 246 qman_setup_pfdr(struct qman_softc *sc, int npfdr) 247 { 248 uint32_t res; 249 250 npfdr = min(npfdr, QMAN_PFDR_MAX); 251 bus_write_4(sc->sc_rres, QMAN_MCP0, 8); 252 bus_write_4(sc->sc_rres, QMAN_MCP1, npfdr - 9); 253 bus_write_4(sc->sc_rres, QMAN_MCR, MCR_INIT_PFDR); 254 255 for (int timeout = 100000; timeout > 0; timeout--) { 256 DELAY(1); 257 res = bus_read_4(sc->sc_rres, QMAN_MCR); 258 if (res >= MCR_RSLT_OK) 259 break; 260 } 261 262 if (res < MCR_RSLT_OK) 263 return (EBUSY); 264 if (res == MCR_RSLT_OK) 265 return (0); 266 267 return (ENXIO); 268 } 269 270 int 271 qman_attach(device_t dev) 272 { 273 struct qman_softc *sc; 274 int error; 275 vm_paddr_t fqd_pa, pfdr_pa; 276 vm_size_t fqd_sz, pfdr_sz; 277 int qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV1; 278 uint32_t ver; 279 uint32_t nfqd; 280 bool qman3 = false; 281 282 sc = device_get_softc(dev); 283 sc->sc_dev = dev; 284 qman_sc = sc; 285 286 /* Allocate resources */ 287 sc->sc_rrid = 0; 288 sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE); 289 if (sc->sc_rres == NULL) { 290 device_printf(dev, "could not allocate memory.\n"); 291 goto err; 292 } 293 294 sc->sc_irid = 0; 295 sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 296 &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); 297 if (sc->sc_ires == NULL) { 298 device_printf(dev, "could not allocate error interrupt.\n"); 299 goto err; 300 } 301 error = dpaa_map_private_memory(dev, 0, "fsl,qman-fqd", 302 &fqd_pa, &fqd_sz); 303 error = dpaa_map_private_memory(dev, 1, "fsl,qman-pfdr", 304 &pfdr_pa, &pfdr_sz); 305 306 bzero((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz); 307 cpu_flush_dcache((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz); 308 /* 309 * FQDs are 64 bytes in size, with 24 bit pointers, so FQIDs are 24 310 * bits, fits fine in a uint32_t. 311 */ 312 nfqd = fqd_sz / 64; 313 qman_total_fqids = nfqd; 314 qman_channel_base = qman_channel_pool1; 315 qman_fq_list = malloc(nfqd * sizeof(struct qman_fq *), M_QMAN, 316 M_WAITOK); 317 318 error = qman_set_memory(sc, fqd_pa, fqd_sz, QMAN_FQD_BARE); 319 if (error != 0 && error != EEXIST) 320 goto err; 321 error = qman_set_memory(sc, pfdr_pa, pfdr_sz, QMAN_PFDR_BARE); 322 if (error != 0 && error != EEXIST) 323 goto err; 324 if (error == 0) { 325 /* Initialize PFDRs if it hasn't been initialized before */ 326 error = qman_setup_pfdr(sc, pfdr_sz / 64); 327 if (error != 0) 328 goto err; 329 /* Magic constant from documentation */ 330 bus_write_4(sc->sc_rres, QMAN_PFDR_CFG, 64); 331 } 332 333 bus_write_4(sc->sc_rres, QMAN_ERR_ISR, 0xffffffff); 334 bus_write_4(sc->sc_rres, QMAN_ERR_IER, 0xffffffff); 335 336 ver = bus_read_4(sc->sc_rres, QMAN_IP_REV_1); 337 sc->sc_qman_major = ((ver & IP_MJ_M) >> IP_MJ_S); 338 if (sc->sc_qman_major >= 3) 339 qman3 = true; 340 341 if (qman3) 342 qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV3; 343 344 sc->sc_qman_base_channel = qman_channel_pool1; 345 346 sc->sc_fqalloc = 347 vmem_create("qman-fqalloc", 1, nfqd - 1, 1, 0, M_WAITOK); 348 sc->sc_qpalloc = 349 vmem_create("qman-fqalloc", qman_channel_pool1, 350 QMAN_POOL_CHANNELS, 1, 0, M_WAITOK); 351 sc->sc_cgalloc = vmem_create("qman->cgalloc", 0, QMAN_CGRS, 352 1, 0, M_WAITOK); 353 354 if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_NET, NULL, qman_isr, 355 sc, &sc->sc_intr_cookie) != 0) 356 goto err; 357 358 if (error != 0) { 359 device_printf(dev, "could not be initialized\n"); 360 goto err; 361 } 362 bus_write_4(sc->sc_rres, QMAN_DCP_CFG(0), 363 qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED); 364 bus_write_4(sc->sc_rres, QMAN_DCP_CFG(1), 365 qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED); 366 367 bus_write_4(sc->sc_rres, 0xd00, 0x80000322); 368 369 /* TODO: DO we need a taskqueue? Allocate here if so */ 370 371 return (0); 372 373 err: 374 qman_detach(dev); 375 return (ENXIO); 376 } 377 378 int 379 qman_detach(device_t dev) 380 { 381 struct qman_softc *sc; 382 383 sc = device_get_softc(dev); 384 385 if (sc->sc_fqalloc != NULL) 386 vmem_destroy(sc->sc_fqalloc); 387 if (sc->sc_qpalloc != NULL) 388 vmem_destroy(sc->sc_qpalloc); 389 if (sc->sc_cgalloc != NULL) 390 vmem_destroy(sc->sc_cgalloc); 391 392 if (sc->sc_intr_cookie != NULL) 393 bus_teardown_intr(dev, sc->sc_ires, sc->sc_intr_cookie); 394 395 if (sc->sc_ires != NULL) 396 bus_release_resource(dev, SYS_RES_IRQ, 397 sc->sc_irid, sc->sc_ires); 398 399 if (sc->sc_rres != NULL) 400 bus_release_resource(dev, SYS_RES_MEMORY, 401 sc->sc_rrid, sc->sc_rres); 402 403 free(qman_fq_list, M_QMAN); 404 qman_fq_list = NULL; 405 406 return (0); 407 } 408 409 int 410 qman_suspend(device_t dev) 411 { 412 413 return (0); 414 } 415 416 int 417 qman_resume(device_t dev) 418 { 419 420 return (0); 421 } 422 423 int 424 qman_shutdown(device_t dev) 425 { 426 427 return (0); 428 } 429 430 int 431 qman_alloc_channel(void) 432 { 433 struct qman_softc *sc = qman_sc; 434 vmem_addr_t channel; 435 436 vmem_alloc(sc->sc_qpalloc, 1, M_BESTFIT | M_WAITOK, &channel); 437 438 return (channel); 439 } 440 441 void 442 qman_free_channel(int channel) 443 { 444 struct qman_softc *sc = qman_sc; 445 446 vmem_free(sc->sc_qpalloc, channel, 1); 447 } 448 449 /** 450 * @group QMan API functions implementation. 451 * @{ 452 */ 453 454 struct qman_fq * 455 qman_fq_from_index(uint32_t fqid) 456 { 457 if (fqid > qman_total_fqids) 458 return (NULL); 459 return (qman_fq_list[fqid]); 460 } 461 462 /* Allocate and initialize an FQ Range */ 463 struct qman_fq * 464 qman_fq_create(uint32_t fqids_num, int channel, uint8_t wq, 465 bool force_fqid, uint32_t fqid_or_align, bool init_parked, 466 bool hold_active, bool prefer_in_cache, bool congst_avoid_ena, 467 void *congst_group, int8_t overhead_accounting_len, 468 uint32_t tail_drop_threshold, 469 uint8_t annotation_cl, uint8_t data_cl) 470 { 471 union qman_mc_command cmd; 472 struct qman_softc *sc; 473 union qman_mc_result *res; 474 struct qman_fq *fqh; 475 device_t portal; 476 vmem_addr_t fqid_base; 477 uint8_t rslt; 478 479 sc = qman_sc; 480 481 if (fqids_num != 1) { 482 device_printf(sc->sc_dev, 483 "Only one fq allocation allowed currently\n"); 484 return (NULL); 485 } 486 487 bzero(&cmd, sizeof(cmd)); 488 vmem_alloc(sc->sc_fqalloc, fqids_num, M_BESTFIT | M_WAITOK, &fqid_base); 489 cmd.init_fq.fqid = fqid_base; 490 cmd.init_fq.count = fqids_num - 1; 491 cmd.init_fq.dest_chan = channel; 492 cmd.init_fq.dest_wq = wq; 493 cmd.init_fq.we_mask = QCSP_INIT_FQ_WE_DEST_WQ | QCSP_INIT_FQ_WE_FQ_CTRL; 494 if (init_parked) 495 cmd.init_fq.verb = QCSP_VERB_INIT_FQ_PARK; 496 else 497 cmd.init_fq.verb = QCSP_VERB_INIT_FQ_SCHED; 498 cmd.init_fq.fq_ctrl = (prefer_in_cache ? QM_FQCTRL_LIC : 0) | 499 (hold_active ? QM_FQCTRL_HOLDACTIVE : 0) | 500 (congst_avoid_ena ? QM_FQCTRL_AVOIDBLOCK : 0); 501 502 /* 503 * Configure hardware cache stashing: on dequeue, QMan will push 504 * the requested number of cachelines of frame annotation and/or 505 * frame data into the destination core's cache, hiding memory 506 * latency for the RX callback. 507 */ 508 if (annotation_cl != 0 || data_cl != 0) { 509 uint64_t excl, cl; 510 511 excl = (annotation_cl != 0 ? QM_STASHING_EXCL_ANNOTATION : 0) | 512 (data_cl != 0 ? QM_STASHING_EXCL_DATA : 0); 513 cl = ((annotation_cl & 3) << 4) | ((data_cl & 3) << 2); 514 /* excl in wire byte 0 (bits 63-56), cl in wire byte 1. */ 515 cmd.init_fq.context_a = (excl << 56) | (cl << 48); 516 cmd.init_fq.fq_ctrl |= QM_FQCTRL_CTXASTASH; 517 cmd.init_fq.we_mask |= QCSP_INIT_FQ_WE_CONTEXT_A; 518 } 519 520 critical_enter(); 521 522 /* Ensure we have got QMan port initialized */ 523 portal = DPCPU_GET(qman_affine_portal); 524 res = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd); 525 526 rslt = 0; 527 if (res != NULL) 528 rslt = res->init_fq.rslt; 529 530 critical_exit(); 531 if (res == NULL || rslt != QMAN_MC_RES_OK) { 532 vmem_free(sc->sc_fqalloc, fqid_base, fqids_num); 533 goto err; 534 } 535 536 fqh = malloc(sizeof(*fqh), M_QMAN, M_WAITOK | M_ZERO); 537 fqh->fqid = fqid_base; 538 539 qman_fq_list[fqid_base] = fqh; 540 541 return (fqh); 542 543 err: 544 545 return (NULL); 546 } 547 548 static int 549 qman_fq_retire(device_t portal, struct qman_fq *fq) 550 { 551 union qman_mc_command cmd; 552 union qman_mc_result *rr; 553 554 bzero(&cmd, sizeof(cmd)); 555 556 cmd.alter_fqs.verb = QCSP_VERB_ALTER_FQ_RETIRE; 557 cmd.alter_fqs.fqid = fq->fqid; 558 rr = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd); 559 if (rr == NULL) 560 return (ETIMEDOUT); 561 562 if (rr->alter_fqs.rslt == QMAN_MC_RES_OK) { 563 if (rr->alter_fqs.fqs & QMAN_MC_AFQS_NE) { 564 /* TODO: Drain.... */ 565 } 566 return (0); 567 } 568 569 return (0); 570 } 571 572 int 573 qman_fq_free(struct qman_fq *fq) 574 { 575 struct qman_softc *sc; 576 int error; 577 578 sc = qman_sc; 579 580 critical_enter(); 581 error = qman_fq_retire(DPCPU_GET(qman_affine_portal), fq); 582 /* TODO: Take FQ out of service. */ 583 critical_exit(); 584 if (error != 0) 585 return (error); 586 vmem_free(sc->sc_fqalloc, fq->fqid, 1); 587 qman_fq_list[fq->fqid] = NULL; 588 free(fq, M_QMAN); 589 590 return (0); 591 } 592 593 int 594 qman_fq_register_cb(struct qman_fq *fq, qman_cb_dqrr callback, 595 void *ctx) 596 { 597 fq->cb.dqrr = callback; 598 fq->cb.ctx = ctx; 599 600 return (0); 601 } 602 603 int 604 qman_fq_enqueue(struct qman_fq *fq, struct dpaa_fd *frame) 605 { 606 struct qman_softc *sc; 607 int error; 608 void *portal; 609 610 sc = qman_sc; 611 critical_enter(); 612 613 /* Ensure we have got QMan port initialized */ 614 portal = DPCPU_GET(qman_affine_portal); 615 if (portal == NULL) { 616 device_printf(sc->sc_dev, "could not setup QMan portal\n"); 617 critical_exit(); 618 return (ENXIO); 619 } 620 621 error = QMAN_PORTAL_ENQUEUE(portal, fq, frame); 622 623 critical_exit(); 624 625 return (error); 626 } 627 628 uint32_t 629 qman_fq_get_fqid(struct qman_fq *fq) 630 { 631 return (fq->fqid); 632 } 633 634 635 uint32_t 636 qman_fq_get_counter(struct qman_fq *fq, int counter) 637 { 638 union qman_mc_result *cmd_res; 639 union qman_mc_command command; 640 device_t portal; 641 u_int ret = 0; 642 643 bzero(&command, sizeof(command)); 644 command.query_fq_np.verb = QCSP_VERB_QUERY_FQ_NP; 645 command.query_fq_np.fqid = fq->fqid; 646 critical_enter(); 647 portal = DPCPU_GET(qman_affine_portal); 648 cmd_res = QMAN_PORTAL_MC_SEND_RAW(portal, &command); 649 if (counter == QMAN_COUNTER_FRAME) 650 ret = cmd_res->query_fq_np.frm_cnt; 651 else if (counter == QMAN_COUNTER_BYTES) 652 ret = cmd_res->query_fq_np.byte_cnt; 653 654 critical_exit(); 655 656 return (ret); 657 } 658 659 void 660 qman_set_sdest(uint16_t channel, int cpu) 661 { 662 struct qman_softc *sc = qman_sc; 663 uint32_t reg; 664 665 if (sc->sc_qman_major >= 3) { 666 reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG_3(channel)); 667 reg &= IO_CFG_SDEST_M; 668 reg |= (cpu << IO_CFG_SDEST_S); 669 bus_write_4(sc->sc_rres, QCSP_IO_CFG_3(channel), reg); 670 } else { 671 reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG(channel)); 672 reg &= IO_CFG_SDEST_M; 673 reg |= (cpu << IO_CFG_SDEST_S); 674 bus_write_4(sc->sc_rres, QCSP_IO_CFG(channel), reg); 675 } 676 } 677 678 /* 679 * TODO: add polling and/or congestion support. 680 */ 681 682 /** @} */ 683