1 /*- 2 * Copyright (c) 2012 Semihalf. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/bus.h> 35 #include <sys/rman.h> 36 #include <sys/malloc.h> 37 #include <sys/mbuf.h> 38 #include <sys/socket.h> 39 #include <sys/sysctl.h> 40 #include <sys/sockio.h> 41 42 #include <net/ethernet.h> 43 #include <net/if.h> 44 #include <net/if_dl.h> 45 #include <net/if_media.h> 46 #include <net/if_types.h> 47 #include <net/if_arp.h> 48 49 #include <dev/mii/mii.h> 50 #include <dev/mii/miivar.h> 51 52 #include "miibus_if.h" 53 54 #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h> 55 #include <contrib/ncsw/inc/Peripherals/fm_ext.h> 56 #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h> 57 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h> 58 #include <contrib/ncsw/inc/xx_ext.h> 59 60 #include "fman.h" 61 #include "bman.h" 62 #include "qman.h" 63 #include "if_dtsec.h" 64 #include "if_dtsec_rm.h" 65 66 67 /** 68 * @group dTSEC RM private defines. 69 * @{ 70 */ 71 #define DTSEC_BPOOLS_USED (1) 72 #define DTSEC_MAX_TX_QUEUE_LEN 256 73 74 struct dtsec_rm_frame_info { 75 struct mbuf *fi_mbuf; 76 t_DpaaSGTE fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY]; 77 }; 78 79 enum dtsec_rm_pool_params { 80 DTSEC_RM_POOL_RX_LOW_MARK = 16, 81 DTSEC_RM_POOL_RX_HIGH_MARK = 64, 82 DTSEC_RM_POOL_RX_MAX_SIZE = 256, 83 84 DTSEC_RM_POOL_FI_LOW_MARK = 16, 85 DTSEC_RM_POOL_FI_HIGH_MARK = 64, 86 DTSEC_RM_POOL_FI_MAX_SIZE = 256, 87 }; 88 89 #define DTSEC_RM_FQR_RX_CHANNEL e_QM_FQ_CHANNEL_POOL1 90 #define DTSEC_RM_FQR_TX_CONF_CHANNEL e_QM_FQ_CHANNEL_SWPORTAL0 91 enum dtsec_rm_fqr_params { 92 DTSEC_RM_FQR_RX_WQ = 1, 93 DTSEC_RM_FQR_TX_WQ = 1, 94 DTSEC_RM_FQR_TX_CONF_WQ = 1 95 }; 96 /** @} */ 97 98 99 /** 100 * @group dTSEC Frame Info routines. 101 * @{ 102 */ 103 void 104 dtsec_rm_fi_pool_free(struct dtsec_softc *sc) 105 { 106 107 if (sc->sc_fi_zone != NULL) 108 uma_zdestroy(sc->sc_fi_zone); 109 } 110 111 int 112 dtsec_rm_fi_pool_init(struct dtsec_softc *sc) 113 { 114 115 snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info", 116 device_get_nameunit(sc->sc_dev)); 117 118 sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname, 119 sizeof(struct dtsec_rm_frame_info), NULL, NULL, NULL, NULL, 120 UMA_ALIGN_PTR, 0); 121 if (sc->sc_fi_zone == NULL) 122 return (EIO); 123 124 return (0); 125 } 126 127 static struct dtsec_rm_frame_info * 128 dtsec_rm_fi_alloc(struct dtsec_softc *sc) 129 { 130 struct dtsec_rm_frame_info *fi; 131 132 fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT); 133 134 return (fi); 135 } 136 137 static void 138 dtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi) 139 { 140 141 uma_zfree(sc->sc_fi_zone, fi); 142 } 143 /** @} */ 144 145 146 /** 147 * @group dTSEC FMan PORT routines. 148 * @{ 149 */ 150 int 151 dtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit) 152 { 153 t_FmPortParams params; 154 t_FmPortRxParams *rx_params; 155 t_FmExtPools *pool_params; 156 t_Error error; 157 158 memset(¶ms, 0, sizeof(params)); 159 160 params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id; 161 params.h_Fm = sc->sc_fmh; 162 params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type); 163 params.portId = sc->sc_eth_id; 164 params.independentModeEnable = false; 165 params.liodnBase = FM_PORT_LIODN_BASE; 166 params.f_Exception = dtsec_fm_port_rx_exception_callback; 167 params.h_App = sc; 168 169 rx_params = ¶ms.specificParams.rxParams; 170 rx_params->errFqid = sc->sc_rx_fqid; 171 rx_params->dfltFqid = sc->sc_rx_fqid; 172 rx_params->liodnOffset = 0; 173 174 pool_params = &rx_params->extBufPools; 175 pool_params->numOfPoolsUsed = DTSEC_BPOOLS_USED; 176 pool_params->extBufPool->id = sc->sc_rx_bpid; 177 pool_params->extBufPool->size = FM_PORT_BUFFER_SIZE; 178 179 sc->sc_rxph = FM_PORT_Config(¶ms); 180 if (sc->sc_rxph == NULL) { 181 device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n"); 182 return (ENXIO); 183 } 184 185 error = FM_PORT_Init(sc->sc_rxph); 186 if (error != E_OK) { 187 device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n"); 188 FM_PORT_Free(sc->sc_rxph); 189 return (ENXIO); 190 } 191 192 if (bootverbose) 193 device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n", 194 sc->sc_port_rx_hw_id); 195 196 return (0); 197 } 198 199 int 200 dtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit) 201 { 202 t_FmPortParams params; 203 t_FmPortNonRxParams *tx_params; 204 t_Error error; 205 206 memset(¶ms, 0, sizeof(params)); 207 208 params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id; 209 params.h_Fm = sc->sc_fmh; 210 params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type); 211 params.portId = sc->sc_eth_id; 212 params.independentModeEnable = false; 213 params.liodnBase = FM_PORT_LIODN_BASE; 214 params.f_Exception = dtsec_fm_port_tx_exception_callback; 215 params.h_App = sc; 216 217 tx_params = ¶ms.specificParams.nonRxParams; 218 tx_params->errFqid = sc->sc_tx_conf_fqid; 219 tx_params->dfltFqid = sc->sc_tx_conf_fqid; 220 tx_params->qmChannel = sc->sc_port_tx_qman_chan; 221 #ifdef FM_OP_PARTITION_ERRATA_FMANx8 222 tx_params->opLiodnOffset = 0; 223 #endif 224 225 sc->sc_txph = FM_PORT_Config(¶ms); 226 if (sc->sc_txph == NULL) { 227 device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n"); 228 return (ENXIO); 229 } 230 231 error = FM_PORT_Init(sc->sc_txph); 232 if (error != E_OK) { 233 device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n"); 234 FM_PORT_Free(sc->sc_txph); 235 return (ENXIO); 236 } 237 238 if (bootverbose) 239 device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n", 240 sc->sc_port_tx_hw_id); 241 242 return (0); 243 } 244 /** @} */ 245 246 247 /** 248 * @group dTSEC buffer pools routines. 249 * @{ 250 */ 251 static t_Error 252 dtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool, uint8_t *buffer, 253 t_Handle context) 254 { 255 struct dtsec_softc *sc; 256 257 sc = h_BufferPool; 258 uma_zfree(sc->sc_rx_zone, buffer); 259 260 return (E_OK); 261 } 262 263 static uint8_t * 264 dtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool, t_Handle *context) 265 { 266 struct dtsec_softc *sc; 267 uint8_t *buffer; 268 269 sc = h_BufferPool; 270 buffer = uma_zalloc(sc->sc_rx_zone, M_NOWAIT); 271 272 return (buffer); 273 } 274 275 static void 276 dtsec_rm_pool_rx_depleted(t_Handle h_App, bool in) 277 { 278 struct dtsec_softc *sc; 279 unsigned int count; 280 281 sc = h_App; 282 283 if (!in) 284 return; 285 286 while (1) { 287 count = bman_count(sc->sc_rx_pool); 288 if (count > DTSEC_RM_POOL_RX_HIGH_MARK) 289 return; 290 291 bman_pool_fill(sc->sc_rx_pool, DTSEC_RM_POOL_RX_HIGH_MARK); 292 } 293 } 294 295 void 296 dtsec_rm_pool_rx_free(struct dtsec_softc *sc) 297 { 298 299 if (sc->sc_rx_pool != NULL) 300 bman_pool_destroy(sc->sc_rx_pool); 301 302 if (sc->sc_rx_zone != NULL) 303 uma_zdestroy(sc->sc_rx_zone); 304 } 305 306 int 307 dtsec_rm_pool_rx_init(struct dtsec_softc *sc) 308 { 309 310 /* FM_PORT_BUFFER_SIZE must be less than PAGE_SIZE */ 311 CTASSERT(FM_PORT_BUFFER_SIZE < PAGE_SIZE); 312 313 snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers", 314 device_get_nameunit(sc->sc_dev)); 315 316 sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, FM_PORT_BUFFER_SIZE, NULL, 317 NULL, NULL, NULL, FM_PORT_BUFFER_SIZE - 1, 0); 318 if (sc->sc_rx_zone == NULL) 319 return (EIO); 320 321 sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, FM_PORT_BUFFER_SIZE, 322 0, 0, DTSEC_RM_POOL_RX_MAX_SIZE, dtsec_rm_pool_rx_get_buffer, 323 dtsec_rm_pool_rx_put_buffer, DTSEC_RM_POOL_RX_LOW_MARK, 324 DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL, 325 NULL); 326 if (sc->sc_rx_pool == NULL) { 327 device_printf(sc->sc_dev, "NULL rx pool somehow\n"); 328 dtsec_rm_pool_rx_free(sc); 329 return (EIO); 330 } 331 332 return (0); 333 } 334 /** @} */ 335 336 337 /** 338 * @group dTSEC Frame Queue Range routines. 339 * @{ 340 */ 341 static void 342 dtsec_rm_fqr_mext_free(struct mbuf *m) 343 { 344 struct dtsec_softc *sc; 345 void *buffer; 346 347 buffer = m->m_ext.ext_arg1; 348 sc = m->m_ext.ext_arg2; 349 if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE) 350 bman_put_buffer(sc->sc_rx_pool, buffer); 351 else 352 dtsec_rm_pool_rx_put_buffer(sc, buffer, NULL); 353 } 354 355 static e_RxStoreResponse 356 dtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal, 357 uint32_t fqid_off, t_DpaaFD *frame) 358 { 359 struct dtsec_softc *sc; 360 struct mbuf *m; 361 void *frame_va; 362 363 m = NULL; 364 sc = app; 365 366 frame_va = DPAA_FD_GET_ADDR(frame); 367 KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF, 368 ("%s(): Got unsupported frame format 0x%02X!", __func__, 369 DPAA_FD_GET_FORMAT(frame))); 370 371 KASSERT(DPAA_FD_GET_OFFSET(frame) == 0, 372 ("%s(): Only offset 0 is supported!", __func__)); 373 374 if (DPAA_FD_GET_STATUS(frame) != 0) { 375 device_printf(sc->sc_dev, "RX error: 0x%08X\n", 376 DPAA_FD_GET_STATUS(frame)); 377 goto err; 378 } 379 380 m = m_gethdr(M_NOWAIT, MT_HEADER); 381 if (m == NULL) 382 goto err; 383 384 m_extadd(m, frame_va, FM_PORT_BUFFER_SIZE, 385 dtsec_rm_fqr_mext_free, frame_va, sc, 0, 386 EXT_NET_DRV); 387 388 m->m_pkthdr.rcvif = sc->sc_ifnet; 389 m->m_len = DPAA_FD_GET_LENGTH(frame); 390 m_fixhdr(m); 391 392 (*sc->sc_ifnet->if_input)(sc->sc_ifnet, m); 393 394 return (e_RX_STORE_RESPONSE_CONTINUE); 395 396 err: 397 bman_put_buffer(sc->sc_rx_pool, frame_va); 398 if (m != NULL) 399 m_freem(m); 400 401 return (e_RX_STORE_RESPONSE_CONTINUE); 402 } 403 404 static e_RxStoreResponse 405 dtsec_rm_fqr_tx_confirm_callback(t_Handle app, t_Handle fqr, t_Handle portal, 406 uint32_t fqid_off, t_DpaaFD *frame) 407 { 408 struct dtsec_rm_frame_info *fi; 409 struct dtsec_softc *sc; 410 unsigned int qlen; 411 t_DpaaSGTE *sgt0; 412 413 sc = app; 414 415 if (DPAA_FD_GET_STATUS(frame) != 0) 416 device_printf(sc->sc_dev, "TX error: 0x%08X\n", 417 DPAA_FD_GET_STATUS(frame)); 418 419 /* 420 * We are storing struct dtsec_rm_frame_info in first entry 421 * of scatter-gather table. 422 */ 423 sgt0 = DPAA_FD_GET_ADDR(frame); 424 fi = DPAA_SGTE_GET_ADDR(sgt0); 425 426 /* Free transmitted frame */ 427 m_freem(fi->fi_mbuf); 428 dtsec_rm_fi_free(sc, fi); 429 430 qlen = qman_fqr_get_counter(sc->sc_tx_conf_fqr, 0, 431 e_QM_FQR_COUNTERS_FRAME); 432 433 if (qlen == 0) { 434 DTSEC_LOCK(sc); 435 436 if (sc->sc_tx_fqr_full) { 437 sc->sc_tx_fqr_full = 0; 438 dtsec_rm_if_start_locked(sc); 439 } 440 441 DTSEC_UNLOCK(sc); 442 } 443 444 return (e_RX_STORE_RESPONSE_CONTINUE); 445 } 446 447 void 448 dtsec_rm_fqr_rx_free(struct dtsec_softc *sc) 449 { 450 451 if (sc->sc_rx_fqr) 452 qman_fqr_free(sc->sc_rx_fqr); 453 } 454 455 int 456 dtsec_rm_fqr_rx_init(struct dtsec_softc *sc) 457 { 458 t_Error error; 459 t_Handle fqr; 460 461 /* Default Frame Queue */ 462 fqr = qman_fqr_create(1, DTSEC_RM_FQR_RX_CHANNEL, DTSEC_RM_FQR_RX_WQ, 463 false, 0, false, false, true, false, 0, 0, 0); 464 if (fqr == NULL) { 465 device_printf(sc->sc_dev, "could not create default RX queue" 466 "\n"); 467 return (EIO); 468 } 469 470 sc->sc_rx_fqr = fqr; 471 sc->sc_rx_fqid = qman_fqr_get_base_fqid(fqr); 472 473 error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_rx_callback, sc); 474 if (error != E_OK) { 475 device_printf(sc->sc_dev, "could not register RX callback\n"); 476 dtsec_rm_fqr_rx_free(sc); 477 return (EIO); 478 } 479 480 return (0); 481 } 482 483 void 484 dtsec_rm_fqr_tx_free(struct dtsec_softc *sc) 485 { 486 487 if (sc->sc_tx_fqr) 488 qman_fqr_free(sc->sc_tx_fqr); 489 490 if (sc->sc_tx_conf_fqr) 491 qman_fqr_free(sc->sc_tx_conf_fqr); 492 } 493 494 int 495 dtsec_rm_fqr_tx_init(struct dtsec_softc *sc) 496 { 497 t_Error error; 498 t_Handle fqr; 499 500 /* TX Frame Queue */ 501 fqr = qman_fqr_create(1, sc->sc_port_tx_qman_chan, 502 DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0); 503 if (fqr == NULL) { 504 device_printf(sc->sc_dev, "could not create default TX queue" 505 "\n"); 506 return (EIO); 507 } 508 509 sc->sc_tx_fqr = fqr; 510 511 /* TX Confirmation Frame Queue */ 512 fqr = qman_fqr_create(1, DTSEC_RM_FQR_TX_CONF_CHANNEL, 513 DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0, 514 0); 515 if (fqr == NULL) { 516 device_printf(sc->sc_dev, "could not create TX confirmation " 517 "queue\n"); 518 dtsec_rm_fqr_tx_free(sc); 519 return (EIO); 520 } 521 522 sc->sc_tx_conf_fqr = fqr; 523 sc->sc_tx_conf_fqid = qman_fqr_get_base_fqid(fqr); 524 525 error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_tx_confirm_callback, sc); 526 if (error != E_OK) { 527 device_printf(sc->sc_dev, "could not register TX confirmation " 528 "callback\n"); 529 dtsec_rm_fqr_tx_free(sc); 530 return (EIO); 531 } 532 533 return (0); 534 } 535 /** @} */ 536 537 538 /** 539 * @group dTSEC IFnet routines. 540 * @{ 541 */ 542 void 543 dtsec_rm_if_start_locked(struct dtsec_softc *sc) 544 { 545 vm_size_t dsize, psize, ssize; 546 struct dtsec_rm_frame_info *fi; 547 unsigned int qlen, i; 548 struct mbuf *m0, *m; 549 vm_offset_t vaddr; 550 t_DpaaFD fd; 551 552 DTSEC_LOCK_ASSERT(sc); 553 /* TODO: IFF_DRV_OACTIVE */ 554 555 if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0) 556 return; 557 558 if ((sc->sc_ifnet->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING) 559 return; 560 561 while (!IFQ_DRV_IS_EMPTY(&sc->sc_ifnet->if_snd)) { 562 /* Check length of the TX queue */ 563 qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0, 564 e_QM_FQR_COUNTERS_FRAME); 565 566 if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) { 567 sc->sc_tx_fqr_full = 1; 568 return; 569 } 570 571 fi = dtsec_rm_fi_alloc(sc); 572 if (fi == NULL) 573 return; 574 575 IFQ_DRV_DEQUEUE(&sc->sc_ifnet->if_snd, m0); 576 if (m0 == NULL) { 577 dtsec_rm_fi_free(sc, fi); 578 return; 579 } 580 581 i = 0; 582 m = m0; 583 psize = 0; 584 dsize = 0; 585 fi->fi_mbuf = m0; 586 while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) { 587 if (m->m_len == 0) 588 continue; 589 590 /* 591 * First entry in scatter-gather table is used to keep 592 * pointer to frame info structure. 593 */ 594 DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi); 595 DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0); 596 597 DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0); 598 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0); 599 DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0); 600 DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0); 601 i++; 602 603 dsize = m->m_len; 604 vaddr = (vm_offset_t)m->m_data; 605 while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) { 606 ssize = PAGE_SIZE - (vaddr & PAGE_MASK); 607 if (m->m_len < ssize) 608 ssize = m->m_len; 609 610 DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], 611 (void *)vaddr); 612 DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], ssize); 613 614 DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0); 615 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0); 616 DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0); 617 DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0); 618 619 dsize -= ssize; 620 vaddr += ssize; 621 psize += ssize; 622 i++; 623 } 624 625 if (dsize > 0) 626 break; 627 628 m = m->m_next; 629 } 630 631 /* Check if SG table was constructed properly */ 632 if (m != NULL || dsize != 0) { 633 dtsec_rm_fi_free(sc, fi); 634 m_freem(m0); 635 continue; 636 } 637 638 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i-1], 1); 639 640 DPAA_FD_SET_ADDR(&fd, fi->fi_sgt); 641 DPAA_FD_SET_LENGTH(&fd, psize); 642 DPAA_FD_SET_FORMAT(&fd, e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF); 643 644 fd.liodn = 0; 645 fd.bpid = 0; 646 fd.elion = 0; 647 DPAA_FD_SET_OFFSET(&fd, 0); 648 DPAA_FD_SET_STATUS(&fd, 0); 649 650 DTSEC_UNLOCK(sc); 651 if (qman_fqr_enqueue(sc->sc_tx_fqr, 0, &fd) != E_OK) { 652 dtsec_rm_fi_free(sc, fi); 653 m_freem(m0); 654 } 655 DTSEC_LOCK(sc); 656 } 657 } 658 /** @} */ 659