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