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 #define QCSP_VERB_INIT_FQ_PARK 0x40 115 #define QCSP_VERB_INIT_FQ_SCHED 0x41 116 #define QCSP_VERB_QUERY_FQ 0x44 117 #define QCSP_VERB_QUERY_FQ_NP 0x45 118 #define QCSP_VERB_ALTER_FQ_SCHED 0x48 119 #define QCSP_VERB_ALTER_FQ_FE 0x49 120 #define QCSP_VERB_ALTER_FQ_RETIRE 0x4a 121 #define QCSP_VERB_ALTER_FQ_TAKE_OUT 0x4b 122 #define QCSP_VERB_ALTER_FQ_RETIRE_CTXB 0x4c 123 #define QCSP_VERB_ALTER_FQ_XON 0x4d 124 #define QCSP_VERB_ALTER_FQ_XOFF 0x4e 125 126 /* Init FQ */ 127 #define QCSP_INIT_FQ_WE_OAC 0x0100 128 #define QCSP_INIT_FQ_WE_ORPC 0x0080 129 #define QCSP_INIT_FQ_WE_CGID 0x0040 130 #define QCSP_INIT_FQ_WE_FQ_CTRL 0x0020 131 #define QCSP_INIT_FQ_WE_DEST_WQ 0x0010 132 #define QCSP_INIT_FQ_WE_ICS_CRED 0x0008 133 #define QCSP_INIT_FQ_WE_TD_THRESH 0x0004 134 #define QCSP_INIT_FQ_WE_CONTEXT_B 0x0002 135 #define QCSP_INIT_FQ_WE_CONTEXT_A 0x0001 136 137 #define QMAN_MC_RES_OK 0xf0 138 139 #define QMAN_MC_AFQS_NE 0x01 140 141 /* Init FQ options */ 142 #define QM_FQCTRL_CGE 0x0400 143 #define QM_FQCTRL_TDE 0x0200 144 #define QM_FQCTRL_ORP 0x0100 145 #define QM_FQCTRL_CTXASTASH 0x0080 146 #define QM_FQCTRL_CPCSTASH 0x0040 147 #define QM_FQCTRL_FORCESFDR 0x0008 148 #define QM_FQCTRL_AVOIDBLOCK 0x0004 149 #define QM_FQCTRL_HOLDACTIVE 0x0002 150 #define QM_FQCTRL_LIC 0x0001 151 152 #define QMAN_CHANNEL_POOL1_REV1 0x21 153 #define QMAN_CHANNEL_POOL1_REV3 0x401 154 155 #define QMAN_PFDR_MAX 0xfffeff 156 157 /* P1023 has only 3 pool channels, but we don't support that SoC. */ 158 #define QMAN_POOL_CHANNELS 15 159 160 /* P1023 only supports 64 congestion groups... */ 161 #define QMAN_CGRS 256 162 163 static struct qman_softc *qman_sc; 164 165 static MALLOC_DEFINE(M_QMAN, "qman", "DPAA Queue Manager structures"); 166 167 int qman_channel_base; 168 int qman_total_fqids; 169 struct qman_fq **qman_fq_list; 170 171 /* Entries sorted right-to-left in bit order of the ISR */ 172 static const char * const qman_errors[] = { 173 "Invalid enqueue queue", 174 "Invalid enqueue channel!", 175 "Invalid enqueue state", 176 "Invalid enqueue overflow", 177 "Invalid enqueue configuration", 178 NULL, 179 NULL, 180 NULL, 181 "Invalid dequeue queue", 182 "Invalid dequeue source", 183 "Invalid dequeue FQ", 184 "Invalid dequeue direct connect portal", 185 NULL, 186 NULL, 187 NULL, 188 NULL, 189 "Invalid command verb", 190 "Invalid FQ flow control state", 191 NULL, 192 NULL, 193 NULL, 194 NULL, 195 NULL, 196 "Insufficient free PFDRs", 197 "Single-bit ECC error", 198 "Multi-bit ECC error", 199 "PFDR low watermark", 200 "Invalid target transaction", 201 "Initiator data error", 202 NULL, 203 NULL 204 }; 205 206 static void 207 qman_isr(void *arg) 208 { 209 struct qman_softc *sc = arg; 210 uint32_t ier, isr, isr_bit; 211 int i; 212 213 ier = bus_read_4(sc->sc_rres, QMAN_ERR_IER); 214 isr = bus_read_4(sc->sc_rres, QMAN_ERR_ISR); 215 216 if ((ier & isr) == 0) 217 return; 218 219 isr_bit = (isr & ier); 220 for (i = 0; isr_bit != 0; i++, isr_bit >>= 1) { 221 if (isr_bit & 1) 222 device_printf(sc->sc_dev, "%s", qman_errors[i]); 223 } 224 225 bus_write_4(sc->sc_rres, QMAN_ERR_ISR, isr); 226 } 227 228 229 /* Set up reserved memory configuration for PFDR and FQD, per `off`. */ 230 static int 231 qman_set_memory(struct qman_softc *sc, vm_paddr_t pa, 232 vm_size_t size, bus_size_t off) 233 { 234 uint32_t bar, bare; 235 vm_paddr_t old_bar; 236 237 /* 238 * Register offsets: 239 * 0 - BARE 240 * 4 - BAR 241 * 0x10 - AR 242 */ 243 bare = bus_read_4(sc->sc_rres, off); 244 bar = bus_read_4(sc->sc_rres, off + 4); 245 old_bar = (vm_paddr_t)bare << 32 | bar; 246 247 if (old_bar != 0 && old_bar != pa) { 248 device_printf(sc->sc_dev, "QMan BAR already initialized!\n"); 249 return (ENOMEM); 250 } else if (old_bar == pa) 251 return (EEXIST); 252 253 /* 254 * Zero the memory and flush cache through DMAP. QMan accesses the 255 * memory as non-coherent. 256 */ 257 memset((void *)PHYS_TO_DMAP(pa), 0, size); 258 cpu_flush_dcache((void *)PHYS_TO_DMAP(pa), size); 259 260 bus_write_4(sc->sc_rres, off, pa >> 32); 261 bus_write_4(sc->sc_rres, off + 4, (uint32_t)pa); 262 bus_write_4(sc->sc_rres, off + 0x10, AR_EN | (ilog2(size) - 1)); 263 264 return (0); 265 } 266 267 /* 268 * Set up PFDR structures. Some things to keep in mind: 269 * - npfdr is the total number of PFDRs in the private memory. PFDRs are 64 270 * bytes in size, so npfdr is (pfdr_sz/64). 271 * - PFDR 0-7 are reserved, so the base starts at 8, not 0, so we adjust 272 * internally. 273 * - The second parameter is the last PFDR, not the number of PFDRs, so needs to 274 * be adjusted down one more, so subtract 9. 275 */ 276 static int 277 qman_setup_pfdr(struct qman_softc *sc, int npfdr) 278 { 279 uint32_t res; 280 281 npfdr = min(npfdr, QMAN_PFDR_MAX); 282 bus_write_4(sc->sc_rres, QMAN_MCP0, 8); 283 bus_write_4(sc->sc_rres, QMAN_MCP1, npfdr - 9); 284 bus_write_4(sc->sc_rres, QMAN_MCR, MCR_INIT_PFDR); 285 286 for (int timeout = 100000; timeout > 0; timeout--) { 287 DELAY(1); 288 res = bus_read_4(sc->sc_rres, QMAN_MCR); 289 if (res >= MCR_RSLT_OK) 290 break; 291 } 292 293 if (res < MCR_RSLT_OK) 294 return (EBUSY); 295 if (res == MCR_RSLT_OK) 296 return (0); 297 298 return (ENXIO); 299 } 300 301 int 302 qman_attach(device_t dev) 303 { 304 struct qman_softc *sc; 305 int error; 306 vm_paddr_t fqd_pa, pfdr_pa; 307 vm_size_t fqd_sz, pfdr_sz; 308 int qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV1; 309 uint32_t ver; 310 uint32_t nfqd; 311 bool qman3 = false; 312 313 sc = device_get_softc(dev); 314 sc->sc_dev = dev; 315 qman_sc = sc; 316 317 /* Allocate resources */ 318 sc->sc_rrid = 0; 319 sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0, RF_ACTIVE); 320 if (sc->sc_rres == NULL) { 321 device_printf(dev, "could not allocate memory.\n"); 322 goto err; 323 } 324 325 sc->sc_irid = 0; 326 sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 327 &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); 328 if (sc->sc_ires == NULL) { 329 device_printf(dev, "could not allocate error interrupt.\n"); 330 goto err; 331 } 332 error = dpaa_map_private_memory(dev, 0, "fsl,qman-fqd", 333 &fqd_pa, &fqd_sz); 334 error = dpaa_map_private_memory(dev, 1, "fsl,qman-pfdr", 335 &pfdr_pa, &pfdr_sz); 336 337 bzero((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz); 338 cpu_flush_dcache((void *)PHYS_TO_DMAP(fqd_pa), fqd_sz); 339 /* 340 * FQDs are 64 bytes in size, with 24 bit pointers, so FQIDs are 24 341 * bits, fits fine in a uint32_t. 342 */ 343 nfqd = fqd_sz / 64; 344 qman_total_fqids = nfqd; 345 qman_channel_base = qman_channel_pool1; 346 qman_fq_list = malloc(nfqd * sizeof(struct qman_fq *), M_QMAN, 347 M_WAITOK); 348 349 error = qman_set_memory(sc, fqd_pa, fqd_sz, QMAN_FQD_BARE); 350 if (error != 0 && error != EEXIST) 351 goto err; 352 error = qman_set_memory(sc, pfdr_pa, pfdr_sz, QMAN_PFDR_BARE); 353 if (error != 0 && error != EEXIST) 354 goto err; 355 if (error == 0) { 356 /* Initialize PFDRs if it hasn't been initialized before */ 357 error = qman_setup_pfdr(sc, pfdr_sz / 64); 358 if (error != 0) 359 goto err; 360 /* Magic constant from documentation */ 361 bus_write_4(sc->sc_rres, QMAN_PFDR_CFG, 64); 362 } 363 364 bus_write_4(sc->sc_rres, QMAN_ERR_ISR, 0xffffffff); 365 bus_write_4(sc->sc_rres, QMAN_ERR_IER, 0xffffffff); 366 367 ver = bus_read_4(sc->sc_rres, QMAN_IP_REV_1); 368 sc->sc_qman_major = ((ver & IP_MJ_M) >> IP_MJ_S); 369 if (sc->sc_qman_major >= 3) 370 qman3 = true; 371 372 if (qman3) 373 qman_channel_pool1 = QMAN_CHANNEL_POOL1_REV3; 374 375 sc->sc_qman_base_channel = qman_channel_pool1; 376 377 sc->sc_fqalloc = 378 vmem_create("qman-fqalloc", 1, nfqd - 1, 1, 0, M_WAITOK); 379 sc->sc_qpalloc = 380 vmem_create("qman-fqalloc", qman_channel_pool1, 381 QMAN_POOL_CHANNELS, 1, 0, M_WAITOK); 382 sc->sc_cgalloc = vmem_create("qman->cgalloc", 0, QMAN_CGRS, 383 1, 0, M_WAITOK); 384 385 if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_NET, NULL, qman_isr, 386 sc, &sc->sc_intr_cookie) != 0) 387 goto err; 388 389 if (error != 0) { 390 device_printf(dev, "could not be initialized\n"); 391 goto err; 392 } 393 bus_write_4(sc->sc_rres, QMAN_DCP_CFG(0), 394 qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED); 395 bus_write_4(sc->sc_rres, QMAN_DCP_CFG(1), 396 qman3 ? DCP_CFG_ED_3 : DCP_CFG_ED); 397 398 bus_write_4(sc->sc_rres, 0xd00, 0x80000322); 399 400 /* TODO: DO we need a taskqueue? Allocate here if so */ 401 402 return (0); 403 404 err: 405 qman_detach(dev); 406 return (ENXIO); 407 } 408 409 int 410 qman_detach(device_t dev) 411 { 412 struct qman_softc *sc; 413 414 sc = device_get_softc(dev); 415 416 if (sc->sc_fqalloc != NULL) 417 vmem_destroy(sc->sc_fqalloc); 418 if (sc->sc_qpalloc != NULL) 419 vmem_destroy(sc->sc_qpalloc); 420 if (sc->sc_cgalloc != NULL) 421 vmem_destroy(sc->sc_cgalloc); 422 423 if (sc->sc_intr_cookie != NULL) 424 bus_teardown_intr(dev, sc->sc_ires, sc->sc_intr_cookie); 425 426 if (sc->sc_ires != NULL) 427 bus_release_resource(dev, SYS_RES_IRQ, 428 sc->sc_irid, sc->sc_ires); 429 430 if (sc->sc_rres != NULL) 431 bus_release_resource(dev, SYS_RES_MEMORY, 432 sc->sc_rrid, sc->sc_rres); 433 434 free(qman_fq_list, M_QMAN); 435 qman_fq_list = NULL; 436 437 return (0); 438 } 439 440 int 441 qman_suspend(device_t dev) 442 { 443 444 return (0); 445 } 446 447 int 448 qman_resume(device_t dev) 449 { 450 451 return (0); 452 } 453 454 int 455 qman_shutdown(device_t dev) 456 { 457 458 return (0); 459 } 460 461 int 462 qman_alloc_channel(void) 463 { 464 struct qman_softc *sc = qman_sc; 465 vmem_addr_t channel; 466 467 vmem_alloc(sc->sc_qpalloc, 1, M_BESTFIT | M_WAITOK, &channel); 468 469 return (channel); 470 } 471 472 void 473 qman_free_channel(int channel) 474 { 475 struct qman_softc *sc = qman_sc; 476 477 vmem_free(sc->sc_qpalloc, channel, 1); 478 } 479 480 /** 481 * @group QMan API functions implementation. 482 * @{ 483 */ 484 485 struct qman_fq * 486 qman_fq_from_index(uint32_t fqid) 487 { 488 if (fqid > qman_total_fqids) 489 return (NULL); 490 return (qman_fq_list[fqid]); 491 } 492 493 /* Allocate and initialize an FQ Range */ 494 struct qman_fq * 495 qman_fq_create(uint32_t fqids_num, int channel, uint8_t wq, 496 bool force_fqid, uint32_t fqid_or_align, bool init_parked, 497 bool hold_active, bool prefer_in_cache, bool congst_avoid_ena, 498 void *congst_group, int8_t overhead_accounting_len, 499 uint32_t tail_drop_threshold) 500 { 501 union qman_mc_command cmd; 502 struct qman_softc *sc; 503 union qman_mc_result *res; 504 struct qman_fq *fqh; 505 device_t portal; 506 vmem_addr_t fqid_base; 507 uint8_t rslt; 508 509 sc = qman_sc; 510 511 if (fqids_num != 1) { 512 device_printf(sc->sc_dev, 513 "Only one fq allocation allowed currently\n"); 514 return (NULL); 515 } 516 517 bzero(&cmd, sizeof(cmd)); 518 vmem_alloc(sc->sc_fqalloc, fqids_num, M_BESTFIT | M_WAITOK, &fqid_base); 519 cmd.init_fq.fqid = fqid_base; 520 cmd.init_fq.count = fqids_num - 1; 521 cmd.init_fq.dest_chan = channel; 522 cmd.init_fq.dest_wq = wq; 523 cmd.init_fq.we_mask = QCSP_INIT_FQ_WE_DEST_WQ | QCSP_INIT_FQ_WE_FQ_CTRL; 524 if (init_parked) 525 cmd.init_fq.verb = QCSP_VERB_INIT_FQ_PARK; 526 else 527 cmd.init_fq.verb = QCSP_VERB_INIT_FQ_SCHED; 528 cmd.init_fq.fq_ctrl = (prefer_in_cache ? QM_FQCTRL_LIC : 0) | 529 (hold_active ? QM_FQCTRL_HOLDACTIVE : 0) | 530 (congst_avoid_ena ? QM_FQCTRL_AVOIDBLOCK : 0); 531 532 critical_enter(); 533 534 /* Ensure we have got QMan port initialized */ 535 portal = DPCPU_GET(qman_affine_portal); 536 res = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd); 537 538 rslt = 0; 539 if (res != NULL) 540 rslt = res->init_fq.rslt; 541 542 critical_exit(); 543 if (res == NULL || rslt != QMAN_MC_RES_OK) { 544 vmem_free(sc->sc_fqalloc, fqid_base, fqids_num); 545 goto err; 546 } 547 548 fqh = malloc(sizeof(*fqh), M_QMAN, M_WAITOK | M_ZERO); 549 fqh->fqid = fqid_base; 550 551 qman_fq_list[fqid_base] = fqh; 552 553 return (fqh); 554 555 err: 556 557 return (NULL); 558 } 559 560 static int 561 qman_fq_retire(device_t portal, struct qman_fq *fq) 562 { 563 union qman_mc_command cmd; 564 union qman_mc_result *rr; 565 566 bzero(&cmd, sizeof(cmd)); 567 568 cmd.alter_fqs.verb = QCSP_VERB_ALTER_FQ_RETIRE; 569 cmd.alter_fqs.fqid = fq->fqid; 570 rr = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd); 571 if (rr == NULL) 572 return (ETIMEDOUT); 573 574 if (rr->alter_fqs.rslt == QMAN_MC_RES_OK) { 575 if (rr->alter_fqs.fqs & QMAN_MC_AFQS_NE) { 576 /* TODO: Drain.... */ 577 } 578 return (0); 579 } 580 581 return (0); 582 } 583 584 int 585 qman_fq_free(struct qman_fq *fq) 586 { 587 struct qman_softc *sc; 588 int error; 589 590 sc = qman_sc; 591 592 critical_enter(); 593 error = qman_fq_retire(DPCPU_GET(qman_affine_portal), fq); 594 /* TODO: Take FQ out of service. */ 595 critical_exit(); 596 if (error != 0) 597 return (error); 598 vmem_free(sc->sc_fqalloc, fq->fqid, 1); 599 qman_fq_list[fq->fqid] = NULL; 600 free(fq, M_QMAN); 601 602 return (0); 603 } 604 605 int 606 qman_fq_register_cb(struct qman_fq *fq, qman_cb_dqrr callback, 607 void *ctx) 608 { 609 fq->cb.dqrr = callback; 610 fq->cb.ctx = ctx; 611 612 return (0); 613 } 614 615 int 616 qman_fq_enqueue(struct qman_fq *fq, struct dpaa_fd *frame) 617 { 618 struct qman_softc *sc; 619 int error; 620 void *portal; 621 622 sc = qman_sc; 623 critical_enter(); 624 625 /* Ensure we have got QMan port initialized */ 626 portal = DPCPU_GET(qman_affine_portal); 627 if (portal == NULL) { 628 device_printf(sc->sc_dev, "could not setup QMan portal\n"); 629 critical_exit(); 630 return (ENXIO); 631 } 632 633 error = QMAN_PORTAL_ENQUEUE(portal, fq, frame); 634 635 critical_exit(); 636 637 return (error); 638 } 639 640 uint32_t 641 qman_fq_get_fqid(struct qman_fq *fq) 642 { 643 return (fq->fqid); 644 } 645 646 647 uint32_t 648 qman_fq_get_counter(struct qman_fq *fq, int counter) 649 { 650 union qman_mc_result *cmd_res; 651 union qman_mc_command command; 652 device_t portal; 653 u_int ret = 0; 654 655 bzero(&command, sizeof(command)); 656 command.query_fq_np.verb = QCSP_VERB_QUERY_FQ_NP; 657 command.query_fq_np.fqid = fq->fqid; 658 critical_enter(); 659 portal = DPCPU_GET(qman_affine_portal); 660 cmd_res = QMAN_PORTAL_MC_SEND_RAW(portal, &command); 661 if (counter == QMAN_COUNTER_FRAME) 662 ret = cmd_res->query_fq_np.frm_cnt; 663 else if (counter == QMAN_COUNTER_BYTES) 664 ret = cmd_res->query_fq_np.byte_cnt; 665 666 critical_exit(); 667 668 return (ret); 669 } 670 671 void 672 qman_set_sdest(uint16_t channel, int cpu) 673 { 674 struct qman_softc *sc = qman_sc; 675 uint32_t reg; 676 677 if (sc->sc_qman_major >= 3) { 678 reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG_3(channel)); 679 reg &= IO_CFG_SDEST_M; 680 reg |= (cpu << IO_CFG_SDEST_S); 681 bus_write_4(sc->sc_rres, QCSP_IO_CFG_3(channel), reg); 682 } else { 683 reg = bus_read_4(sc->sc_rres, QCSP_IO_CFG(channel)); 684 reg &= IO_CFG_SDEST_M; 685 reg |= (cpu << IO_CFG_SDEST_S); 686 bus_write_4(sc->sc_rres, QCSP_IO_CFG(channel), reg); 687 } 688 } 689 690 /* 691 * TODO: add polling and/or congestion support. 692 */ 693 694 /** @} */ 695