1 /*- 2 * Copyright (c) 2026 Justin Hibbits 3 * Copyright (c) 2012 Semihalf. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/kernel.h> 31 #include <sys/module.h> 32 #include <sys/bus.h> 33 #include <sys/rman.h> 34 #include <sys/malloc.h> 35 #include <sys/mbuf.h> 36 #include <sys/smp.h> 37 #include <sys/socket.h> 38 #include <sys/sockio.h> 39 #include <sys/sysctl.h> 40 41 #include <net/ethernet.h> 42 #include <net/if.h> 43 #include <net/if_dl.h> 44 #include <net/if_media.h> 45 #include <net/if_types.h> 46 #include <net/if_arp.h> 47 #include <netinet/ip.h> 48 #include <netinet/ip6.h> 49 50 #include <dev/mii/mii.h> 51 #include <dev/mii/miivar.h> 52 53 #include <vm/vm.h> 54 #include <vm/pmap.h> 55 56 #include "miibus_if.h" 57 58 #include "bman.h" 59 #include "dpaa_common.h" 60 #include "dpaa_eth.h" 61 #include "fman.h" 62 #include "fman_parser.h" 63 #include "fman_port.h" 64 #include "fman_if.h" 65 #include "fman_port_if.h" 66 #include "if_dtsec.h" 67 #include "qman.h" 68 #include "qman_var.h" 69 #include "qman_portal_if.h" 70 71 72 #define DPAA_ETH_LOCK(sc) mtx_lock(&(sc)->sc_lock) 73 #define DPAA_ETH_UNLOCK(sc) mtx_unlock(&(sc)->sc_lock) 74 #define DPAA_ETH_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED) 75 76 /* 77 * On 64-bit Book-E the direct map is always present, and the driver's 78 * UMA zones plus page-sized mbuf clusters live in it. Bypass the 79 * page-table walk in pmap_kextract() for those; fall back for 80 * MJUM9BYTES/MJUM16BYTES clusters, which are kmem_alloc_contig()'d 81 * into KVA. 82 */ 83 static inline vm_paddr_t 84 dpaa_eth_va_to_phys(vm_offset_t va) 85 { 86 if (__predict_true(va >= DMAP_BASE_ADDRESS && va <= DMAP_MAX_ADDRESS)) 87 return (DMAP_TO_PHYS(va)); 88 return (pmap_kextract(va)); 89 } 90 91 /** 92 * @group dTSEC RM private defines. 93 * @{ 94 */ 95 #define DTSEC_BPOOLS_USED (1) 96 #define DTSEC_MAX_TX_QUEUE_LEN 256 97 /* 98 * Sample the hardware TX FQ counter every Nth packet. The FQ counter is 99 * 24 bits and the soft cap above is 256, so overshoot by N is trivial. 100 */ 101 #define DTSEC_MAX_TX_QUEUE_CHECK_INTERVAL 32 102 /* 103 * Confirmation callback drain-detection. Fast path (TX not backpressured) 104 * skips the MC call entirely; when flagged, we sample every Nth callback to 105 * detect the drain-to-zero transition. 106 */ 107 #define DTSEC_TX_CONF_CHECK_INTERVAL 32 108 109 struct dpaa_eth_frame_info { 110 struct fman_internal_context fi_ic; 111 struct mbuf *fi_mbuf; 112 struct dpaa_sgte fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY]; 113 }; 114 115 enum dpaa_eth_pool_params { 116 DTSEC_RM_POOL_RX_LOW_MARK = 16, 117 DTSEC_RM_POOL_RX_HIGH_MARK = 64, 118 DTSEC_RM_POOL_RX_MAX_SIZE = 256, 119 /* 120 * MAX_SIZE is a soft cap set well below the BMan hardware pool 121 * limit, so sampling the depth every N put-backs per CPU is safe: 122 * worst-case overshoot is N * ncpus buffers, still tiny vs. the 123 * hardware pool. 124 */ 125 DTSEC_RM_POOL_RX_CHECK_INTERVAL = 32, 126 127 DTSEC_RM_POOL_FI_LOW_MARK = 16, 128 DTSEC_RM_POOL_FI_HIGH_MARK = 64, 129 DTSEC_RM_POOL_FI_MAX_SIZE = 256, 130 }; 131 132 #define DTSEC_RM_FQR_RX_CHANNEL 0x401 133 #define DTSEC_RM_FQR_TX_CONF_CHANNEL 0 134 enum dpaa_eth_fq_params { 135 DTSEC_RM_FQR_RX_WQ = 1, 136 DTSEC_RM_FQR_TX_WQ = 1, 137 DTSEC_RM_FQR_TX_CONF_WQ = 1 138 }; 139 /** @} */ 140 141 142 /** 143 * @group dTSEC Frame Info routines. 144 * @{ 145 */ 146 void 147 dpaa_eth_fi_pool_free(struct dpaa_eth_softc *sc) 148 { 149 150 if (sc->sc_fi_zone != NULL) 151 uma_zdestroy(sc->sc_fi_zone); 152 } 153 154 int 155 dpaa_eth_fi_pool_init(struct dpaa_eth_softc *sc) 156 { 157 158 snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info", 159 device_get_nameunit(sc->sc_dev)); 160 161 sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname, 162 sizeof(struct dpaa_eth_frame_info), NULL, NULL, NULL, NULL, 163 UMA_ALIGN_PTR, 0); 164 165 return (0); 166 } 167 168 static struct dpaa_eth_frame_info * 169 dpaa_eth_fi_alloc(struct dpaa_eth_softc *sc) 170 { 171 struct dpaa_eth_frame_info *fi; 172 173 fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT | M_ZERO); 174 175 return (fi); 176 } 177 178 static void 179 dpaa_eth_fi_free(struct dpaa_eth_softc *sc, struct dpaa_eth_frame_info *fi) 180 { 181 182 uma_zfree(sc->sc_fi_zone, fi); 183 } 184 /** @} */ 185 186 187 /** 188 * @group dTSEC FMan PORT routines. 189 * @{ 190 */ 191 int 192 dpaa_eth_fm_port_rx_init(struct dpaa_eth_softc *sc) 193 { 194 struct fman_port_params params; 195 int error; 196 197 params.dflt_fqid = sc->sc_rx_fqid; 198 params.err_fqid = sc->sc_rx_fqid; 199 params.rx_params.num_pools = 1; 200 params.rx_params.bpools[0].bpid = bman_get_bpid(sc->sc_rx_pool); 201 params.rx_params.bpools[0].size = MCLBYTES; 202 error = FMAN_PORT_CONFIG(sc->sc_rx_port, ¶ms); 203 error = FMAN_PORT_INIT(sc->sc_rx_port); 204 if (error != 0) { 205 device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n"); 206 return (ENXIO); 207 } 208 209 return (0); 210 } 211 212 int 213 dpaa_eth_fm_port_tx_init(struct dpaa_eth_softc *sc) 214 { 215 struct fman_port_params params; 216 int error; 217 218 params.dflt_fqid = sc->sc_tx_conf_fqid; 219 params.err_fqid = sc->sc_tx_conf_fqid; 220 221 error = FMAN_PORT_CONFIG(sc->sc_tx_port, ¶ms); 222 error = FMAN_PORT_INIT(sc->sc_tx_port); 223 if (error != 0) { 224 device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n"); 225 return (ENXIO); 226 } 227 228 return (0); 229 } 230 /** @} */ 231 232 233 /** 234 * @group dTSEC buffer pools routines. 235 * @{ 236 */ 237 static int 238 dpaa_eth_pool_rx_put_buffer(struct dpaa_eth_softc *sc, uint8_t *buffer, 239 void *context) 240 { 241 242 uma_zfree(sc->sc_rx_zone, buffer); 243 244 return (0); 245 } 246 247 static int 248 dtsec_add_buffers(struct dpaa_eth_softc *sc, int count) 249 { 250 struct bman_buffer bufs[8] = {}; 251 int err; 252 int c; 253 254 while (count > 0) { 255 c = min(8, count); 256 for (int i = 0; i < c; i++) { 257 void *b; 258 vm_paddr_t pa; 259 260 b = uma_zalloc(sc->sc_rx_zone, M_NOWAIT); 261 if (b == NULL) 262 return (ENOMEM); 263 pa = DMAP_TO_PHYS((vm_offset_t)b); 264 bufs[i].buf_hi = (pa >> 32); 265 bufs[i].buf_lo = (pa & 0xffffffff); 266 } 267 268 err = bman_put_buffers(sc->sc_rx_pool, bufs, c); 269 if (err != 0) 270 return (err); 271 count -= c; 272 } 273 274 return (0); 275 } 276 277 static void 278 dpaa_eth_pool_rx_depleted(void *h_App, bool in) 279 { 280 struct dpaa_eth_softc *sc; 281 unsigned int count; 282 283 sc = h_App; 284 285 if (!in) 286 return; 287 288 while (1) { 289 count = bman_count(sc->sc_rx_pool); 290 if (count > DTSEC_RM_POOL_RX_HIGH_MARK) 291 return; 292 293 /* Can only release 8 buffers at a time */ 294 count = min(DTSEC_RM_POOL_RX_HIGH_MARK - count + 8, 8); 295 if (dtsec_add_buffers(sc, count) != 0) 296 return; 297 } 298 } 299 300 void 301 dpaa_eth_pool_rx_free(struct dpaa_eth_softc *sc) 302 { 303 304 if (sc->sc_rx_pool != NULL) 305 bman_pool_destroy(sc->sc_rx_pool); 306 307 if (sc->sc_rx_zone != NULL) 308 uma_zdestroy(sc->sc_rx_zone); 309 310 free(sc->sc_rx_pool_check_cnt, M_DEVBUF); 311 sc->sc_rx_pool_check_cnt = NULL; 312 } 313 314 int 315 dpaa_eth_pool_rx_init(struct dpaa_eth_softc *sc) 316 { 317 318 /* MCLBYTES must be less than PAGE_SIZE */ 319 CTASSERT(MCLBYTES < PAGE_SIZE); 320 321 snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers", 322 device_get_nameunit(sc->sc_dev)); 323 324 sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, MCLBYTES, NULL, 325 NULL, NULL, NULL, MCLBYTES - 1, 0); 326 327 sc->sc_rx_pool_check_cnt = malloc_aligned( 328 (mp_maxid + 1) * sizeof(struct dpaa_pcpu_cnt), 329 CACHE_LINE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); 330 331 sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, MCLBYTES, 332 DTSEC_RM_POOL_RX_MAX_SIZE, DTSEC_RM_POOL_RX_LOW_MARK, 333 DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dpaa_eth_pool_rx_depleted, sc); 334 if (sc->sc_rx_pool == NULL) { 335 device_printf(sc->sc_dev, "NULL rx pool somehow\n"); 336 dpaa_eth_pool_rx_free(sc); 337 return (EIO); 338 } 339 340 dtsec_add_buffers(sc, DTSEC_RM_POOL_RX_HIGH_MARK); 341 342 return (0); 343 } 344 /** @} */ 345 346 347 /** 348 * @group dTSEC Frame Queue Range routines. 349 * @{ 350 */ 351 static void 352 dpaa_eth_fq_mext_free(struct mbuf *m) 353 { 354 struct dpaa_eth_softc *sc; 355 void *buffer; 356 357 buffer = m->m_ext.ext_arg1; 358 sc = m->m_ext.ext_arg2; 359 /* 360 * Sloppy per-CPU sampling: no pin, no atomic. A stray migration 361 * between the curcpu read and the increment can only mis-attribute 362 * one bump to the wrong CPU's counter; the sampling rate stays 363 * within the acceptable slop window. 364 */ 365 if ((++sc->sc_rx_pool_check_cnt[curcpu].cnt & 366 (DTSEC_RM_POOL_RX_CHECK_INTERVAL - 1)) == 0 && 367 bman_count(sc->sc_rx_pool) > DTSEC_RM_POOL_RX_MAX_SIZE) 368 dpaa_eth_pool_rx_put_buffer(sc, buffer, NULL); 369 else 370 bman_put_buffer(sc->sc_rx_pool, 371 DMAP_TO_PHYS((vm_offset_t)buffer), sc->sc_rx_bpid); 372 } 373 374 static int 375 dpaa_eth_update_csum_flags(struct qman_fd *frame, 376 struct fman_parse_result *prs, struct mbuf *m) 377 { 378 uint16_t l3r = be16toh(prs->l3r); 379 380 /* TODO: nested protocols? */ 381 if ((l3r & L3R_FIRST_IP_M) != 0) { 382 m->m_pkthdr.csum_flags |= CSUM_L3_CALC; 383 if ((l3r & L3R_FIRST_ERROR) == 0) 384 m->m_pkthdr.csum_flags |= CSUM_L3_VALID; 385 } 386 if (frame->cmd_stat & DPAA_FD_RX_STATUS_L4CV) { 387 m->m_pkthdr.csum_flags |= CSUM_L4_CALC; 388 m->m_pkthdr.csum_data = 0xffff; 389 if ((prs->l4r & L4R_TYPE_M) != 0 && 390 (prs->l4r & L4R_ERR) == 0) 391 m->m_pkthdr.csum_flags |= CSUM_L4_VALID; 392 } 393 394 return (0); 395 } 396 397 static int 398 dpaa_eth_fq_rx_callback(device_t portal, struct qman_fq *fq, 399 struct qman_fd *frame, void *app) 400 { 401 struct dpaa_eth_softc *sc; 402 struct mbuf *m; 403 struct fman_internal_context *frame_ic; 404 void *frame_va; 405 406 m = NULL; 407 sc = app; 408 409 frame_va = DPAA_FD_GET_ADDR(frame); 410 frame_ic = frame_va; /* internal context at head of the frame */ 411 /* Only simple (single- or multi-) frames are supported. */ 412 KASSERT(frame->format == 0 || frame->format == 4, 413 ("%s(): Got unsupported frame format 0x%02X!", __func__, 414 frame->format)); 415 416 if ((frame->cmd_stat & DPAA_FD_CMD_STAT_ERR_M) != 0) { 417 device_printf(sc->sc_dev, "RX error: 0x%08X\n", 418 frame->cmd_stat); 419 goto err; 420 } 421 422 m = m_gethdr(M_NOWAIT, MT_HEADER); 423 if (m == NULL) 424 goto err; 425 426 if (frame->format == 0) { 427 /* Single-frame format */ 428 m_extadd(m, (char *)frame_va + frame->offset, frame->length, 429 dpaa_eth_fq_mext_free, frame_va, sc, 0, EXT_NET_DRV); 430 } else { 431 struct dpaa_sgte *sgt = 432 (struct dpaa_sgte *)(char *)frame_va + frame->offset; 433 /* Simple multi-frame format */ 434 for (int i = 0; i < DPAA_NUM_OF_SG_TABLE_ENTRY; i++) { 435 if (sgt[i].length > 0) 436 m_extadd(m, PHYS_TO_DMAP(sgt[i].addr), 437 sgt[i].length, dpaa_eth_fq_mext_free, 438 PHYS_TO_DMAP(sgt[i].addr), sc, 0, 439 EXT_NET_DRV); 440 if (sgt[i].final) 441 break; 442 } 443 /* Free the SGT buffer, it's no longer needed. */ 444 bman_put_buffer(sc->sc_rx_pool, frame->addr, sc->sc_rx_bpid); 445 } 446 447 if (if_getcapenable(sc->sc_ifnet) & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) 448 dpaa_eth_update_csum_flags(frame, &frame_ic->prs, m); 449 450 m->m_pkthdr.rcvif = sc->sc_ifnet; 451 m->m_len = frame->length; 452 m_fixhdr(m); 453 454 if_input(sc->sc_ifnet, m); 455 456 return (1); 457 458 err: 459 bman_put_buffer(sc->sc_rx_pool, frame->addr, sc->sc_rx_bpid); 460 if (m != NULL) 461 m_freem(m); 462 463 return (1); 464 } 465 466 static int 467 dpaa_eth_fq_tx_confirm_callback(device_t portal, struct qman_fq *fq, 468 struct qman_fd *frame, void *app) 469 { 470 struct dpaa_eth_frame_info *fi; 471 struct dpaa_eth_softc *sc; 472 473 sc = app; 474 475 if ((frame->cmd_stat & DPAA_FD_TX_STAT_ERR_M) != 0) 476 device_printf(sc->sc_dev, "TX error: 0x%08X\n", 477 frame->cmd_stat); 478 479 /* 480 * We are storing struct dpaa_eth_frame_info in first entry 481 * of scatter-gather table. 482 */ 483 fi = (struct dpaa_eth_frame_info *)PHYS_TO_DMAP(frame->addr); 484 485 /* Free transmitted frame */ 486 m_freem(fi->fi_mbuf); 487 dpaa_eth_fi_free(sc, fi); 488 489 /* 490 * Fast path: TX isn't backpressured, so there's nothing to 491 * restart. Acquire load pairs with the release store on the 492 * TX path so a concurrent set of the flag is observed here. 493 */ 494 if (atomic_load_acq_int(&sc->sc_tx_fq_full) == 0) 495 return (1); 496 497 /* Rate-limit the MC round-trip to detect drain-to-zero. */ 498 if ((sc->sc_tx_conf_check_cnt++ & 499 (DTSEC_TX_CONF_CHECK_INTERVAL - 1)) != 0) 500 return (1); 501 if (qman_fq_get_counter(sc->sc_tx_conf_fq, QMAN_COUNTER_FRAME) != 0) 502 return (1); 503 504 DPAA_ETH_LOCK(sc); 505 if (sc->sc_tx_fq_full) { 506 atomic_store_rel_int(&sc->sc_tx_fq_full, 0); 507 dpaa_eth_if_start_locked(sc); 508 } 509 DPAA_ETH_UNLOCK(sc); 510 511 return (1); 512 } 513 514 void 515 dpaa_eth_fq_rx_free(struct dpaa_eth_softc *sc) 516 { 517 int cpu; 518 519 if (sc->sc_rx_fq) 520 qman_fq_free(sc->sc_rx_fq); 521 if (sc->sc_rx_channel != 0) { 522 CPU_FOREACH(cpu) { 523 device_t portal = DPCPU_ID_GET(cpu, qman_affine_portal); 524 QMAN_PORTAL_STATIC_DEQUEUE_RM_CHANNEL(portal, 525 sc->sc_rx_channel); 526 } 527 qman_free_channel(sc->sc_rx_channel); 528 } 529 } 530 531 int 532 dpaa_eth_fq_rx_init(struct dpaa_eth_softc *sc) 533 { 534 void *fq; 535 int error; 536 int cpu; 537 538 /* Default Frame Queue */ 539 if (sc->sc_rx_channel == 0) 540 sc->sc_rx_channel = qman_alloc_channel(); 541 /* 542 * Stash 1 cacheline of frame annotation (parse result / IC) and 543 * 1 of frame data head into the destination core's cache when 544 * QMan dequeues an RX frame -- the RX callback reads both. 545 */ 546 fq = qman_fq_create(1, sc->sc_rx_channel, DTSEC_RM_FQR_RX_WQ, 547 false, 0, false, false, true, false, 0, 0, 0, 1, 1); 548 if (fq == NULL) { 549 device_printf(sc->sc_dev, 550 "could not create default RX queue\n"); 551 return (EIO); 552 } 553 554 CPU_FOREACH(cpu) { 555 device_t portal = DPCPU_ID_GET(cpu, qman_affine_portal); 556 QMAN_PORTAL_STATIC_DEQUEUE_CHANNEL(portal, sc->sc_rx_channel); 557 } 558 559 sc->sc_rx_fq = fq; 560 sc->sc_rx_fqid = qman_fq_get_fqid(fq); 561 562 error = qman_fq_register_cb(fq, dpaa_eth_fq_rx_callback, sc); 563 if (error != 0) { 564 device_printf(sc->sc_dev, "could not register RX callback\n"); 565 dpaa_eth_fq_rx_free(sc); 566 return (EIO); 567 } 568 569 return (0); 570 } 571 572 void 573 dpaa_eth_fq_tx_free(struct dpaa_eth_softc *sc) 574 { 575 576 if (sc->sc_tx_fq) 577 qman_fq_free(sc->sc_tx_fq); 578 579 if (sc->sc_tx_conf_fq) 580 qman_fq_free(sc->sc_tx_conf_fq); 581 } 582 583 int 584 dpaa_eth_fq_tx_init(struct dpaa_eth_softc *sc) 585 { 586 int error; 587 void *fq; 588 589 /* TX Frame Queue */ 590 fq = qman_fq_create(1, sc->sc_port_tx_qman_chan, 591 DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0, 592 0, 0); 593 if (fq == NULL) { 594 device_printf(sc->sc_dev, "could not create default TX queue" 595 "\n"); 596 return (EIO); 597 } 598 599 sc->sc_tx_fq = fq; 600 601 if (sc->sc_rx_channel == 0) 602 sc->sc_rx_channel = qman_alloc_channel(); 603 /* TX Confirmation Frame Queue */ 604 fq = qman_fq_create(1, sc->sc_rx_channel, 605 DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0, 606 0, 0, 0); 607 if (fq == NULL) { 608 device_printf(sc->sc_dev, "could not create TX confirmation " 609 "queue\n"); 610 dpaa_eth_fq_tx_free(sc); 611 return (EIO); 612 } 613 614 sc->sc_tx_conf_fq = fq; 615 sc->sc_tx_conf_fqid = qman_fq_get_fqid(fq); 616 617 error = qman_fq_register_cb(fq, dpaa_eth_fq_tx_confirm_callback, sc); 618 if (error != 0) { 619 device_printf(sc->sc_dev, "could not register TX confirmation " 620 "callback\n"); 621 dpaa_eth_fq_tx_free(sc); 622 return (EIO); 623 } 624 625 return (0); 626 } 627 /** @} */ 628 629 /* Returns the cmd_stat field for the frame descriptor */ 630 static uint32_t 631 dpaa_eth_tx_add_csum(struct dpaa_eth_frame_info *fi) 632 { 633 struct mbuf *m = fi->fi_mbuf; 634 struct fman_parse_result *prs = &fi->fi_ic.prs; 635 uint32_t csum_flags = m->m_pkthdr.csum_flags; 636 uint8_t ether_size = ETHER_HDR_LEN; 637 638 if ((csum_flags & CSUM_FLAGS_TX) == 0) 639 return (0); 640 641 if (m->m_flags & M_VLANTAG) 642 ether_size += ETHER_VLAN_ENCAP_LEN; 643 if (csum_flags & CSUM_IP) 644 prs->l3r = L3R_FIRST_IPV4; 645 if (csum_flags & CSUM_IP_UDP) { 646 prs->l4r = L4R_TYPE_UDP; 647 prs->l4_off = ether_size + sizeof(struct ip); 648 } else if (csum_flags & CSUM_IP_TCP) { 649 prs->l4r = L4R_TYPE_TCP; 650 prs->l4_off = ether_size + sizeof(struct ip); 651 } else if (csum_flags & CSUM_IP6_UDP) { 652 prs->l3r = L3R_FIRST_IPV6; 653 prs->l4r = L4R_TYPE_UDP; 654 prs->l4_off = ether_size + sizeof(struct ip6_hdr); 655 } else if (csum_flags & CSUM_IP6_TCP) { 656 prs->l3r = L3R_FIRST_IPV6; 657 prs->l4r = L4R_TYPE_TCP; 658 prs->l4_off = ether_size + sizeof(struct ip6_hdr); 659 } 660 661 prs->ip_off[0] = ether_size; 662 663 return (DPAA_FD_TX_CMD_RPD | DPAA_FD_TX_CMD_DTC); 664 } 665 666 /** 667 * @group dTSEC IFnet routines. 668 * @{ 669 */ 670 void 671 dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc) 672 { 673 vm_size_t dsize, psize, ssize; 674 struct dpaa_eth_frame_info *fi; 675 unsigned int i; 676 struct mbuf *m0, *m; 677 vm_offset_t vaddr; 678 struct dpaa_fd fd; 679 680 DPAA_ETH_LOCK_ASSERT(sc); 681 /* TODO: IFF_DRV_OACTIVE */ 682 683 if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0) 684 return; 685 686 if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING) 687 return; 688 689 if (sc->sc_tx_fq_full) 690 return; 691 692 while (!if_sendq_empty(sc->sc_ifnet)) { 693 if ((sc->sc_tx_queue_check_cnt++ & 694 (DTSEC_MAX_TX_QUEUE_CHECK_INTERVAL - 1)) == 0 && 695 qman_fq_get_counter(sc->sc_tx_fq, QMAN_COUNTER_FRAME) >= 696 DTSEC_MAX_TX_QUEUE_LEN) { 697 atomic_store_rel_int(&sc->sc_tx_fq_full, 1); 698 sc->sc_tx_queue_check_cnt = 0; 699 return; 700 } 701 702 fi = dpaa_eth_fi_alloc(sc); 703 if (fi == NULL) 704 return; 705 706 m0 = if_dequeue(sc->sc_ifnet); 707 if (m0 == NULL) { 708 dpaa_eth_fi_free(sc, fi); 709 return; 710 } 711 712 i = 0; 713 m = m0; 714 psize = 0; 715 dsize = 0; 716 fi->fi_mbuf = m0; 717 718 while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) { 719 if (m->m_len == 0) 720 continue; 721 722 dsize = m->m_len; 723 vaddr = (vm_offset_t)m->m_data; 724 while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) { 725 ssize = PAGE_SIZE - (vaddr & PAGE_MASK); 726 if (m->m_len < ssize) 727 ssize = m->m_len; 728 729 fi->fi_sgt[i].addr = dpaa_eth_va_to_phys(vaddr); 730 fi->fi_sgt[i].length = ssize; 731 732 fi->fi_sgt[i].extension = 0; 733 fi->fi_sgt[i].final = 0; 734 fi->fi_sgt[i].bpid = 0; 735 fi->fi_sgt[i].offset = 0; 736 737 dsize -= ssize; 738 vaddr += ssize; 739 psize += ssize; 740 i++; 741 } 742 743 if (dsize > 0) 744 break; 745 746 m = m->m_next; 747 } 748 749 /* Check if SG table was constructed properly */ 750 if (m != NULL || dsize != 0) { 751 dpaa_eth_fi_free(sc, fi); 752 m_freem(m0); 753 continue; 754 } 755 756 fi->fi_sgt[i - 1].final = 1; 757 758 fd.addr = DMAP_TO_PHYS((vm_offset_t)fi); 759 fd.length = psize; 760 fd.format = DPAA_FD_FORMAT_SHORT_MBSF; 761 762 fd.liodn = 0; 763 fd.bpid = 0; 764 fd.eliodn = 0; 765 fd.offset = offsetof(struct dpaa_eth_frame_info, fi_sgt); 766 fd.cmd_stat = dpaa_eth_tx_add_csum(fi); 767 768 DPAA_ETH_UNLOCK(sc); 769 if (qman_fq_enqueue(sc->sc_tx_fq, &fd) != 0) { 770 dpaa_eth_fi_free(sc, fi); 771 m_freem(m0); 772 } 773 DPAA_ETH_LOCK(sc); 774 } 775 } 776 /** @} */ 777