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