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