]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/dpaa/if_dtsec_rm.c
MFhead@r325209
[FreeBSD/FreeBSD.git] / sys / dev / dpaa / if_dtsec_rm.c
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 enum dtsec_rm_fqr_params {
90         DTSEC_RM_FQR_RX_CHANNEL         = e_QM_FQ_CHANNEL_POOL1,
91         DTSEC_RM_FQR_RX_WQ              = 1,
92         DTSEC_RM_FQR_TX_CONF_CHANNEL    = e_QM_FQ_CHANNEL_SWPORTAL0,
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(&params, 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 = &params.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(&params);
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(&params, 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 = &params.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(&params);
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
362         m = NULL;
363         sc = app;
364
365         KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF,
366             ("%s(): Got unsupported frame format 0x%02X!", __func__,
367             DPAA_FD_GET_FORMAT(frame)));
368
369         KASSERT(DPAA_FD_GET_OFFSET(frame) == 0,
370             ("%s(): Only offset 0 is supported!", __func__));
371
372         if (DPAA_FD_GET_STATUS(frame) != 0) {
373                 device_printf(sc->sc_dev, "RX error: 0x%08X\n",
374                     DPAA_FD_GET_STATUS(frame));
375                 goto err;
376         }
377
378         m = m_gethdr(M_NOWAIT, MT_HEADER);
379         if (m == NULL)
380                 goto err;
381
382         m_extadd(m, DPAA_FD_GET_ADDR(frame), FM_PORT_BUFFER_SIZE,
383             dtsec_rm_fqr_mext_free, DPAA_FD_GET_ADDR(frame), sc, 0,
384             EXT_NET_DRV);
385
386         m->m_pkthdr.rcvif = sc->sc_ifnet;
387         m->m_len = DPAA_FD_GET_LENGTH(frame);
388         m_fixhdr(m);
389
390         (*sc->sc_ifnet->if_input)(sc->sc_ifnet, m);
391
392         return (e_RX_STORE_RESPONSE_CONTINUE);
393
394 err:
395         bman_put_buffer(sc->sc_rx_pool, DPAA_FD_GET_ADDR(frame));
396         if (m != NULL)
397                 m_freem(m);
398
399         return (e_RX_STORE_RESPONSE_CONTINUE);
400 }
401
402 static e_RxStoreResponse
403 dtsec_rm_fqr_tx_confirm_callback(t_Handle app, t_Handle fqr, t_Handle portal,
404     uint32_t fqid_off, t_DpaaFD *frame)
405 {
406         struct dtsec_rm_frame_info *fi;
407         struct dtsec_softc *sc;
408         unsigned int qlen;
409         t_DpaaSGTE *sgt0;
410
411         sc = app;
412
413         if (DPAA_FD_GET_STATUS(frame) != 0)
414                 device_printf(sc->sc_dev, "TX error: 0x%08X\n",
415                     DPAA_FD_GET_STATUS(frame));
416
417         /*
418          * We are storing struct dtsec_rm_frame_info in first entry
419          * of scatter-gather table.
420          */
421         sgt0 = DPAA_FD_GET_ADDR(frame);
422         fi = DPAA_SGTE_GET_ADDR(sgt0);
423
424         /* Free transmitted frame */
425         m_freem(fi->fi_mbuf);
426         dtsec_rm_fi_free(sc, fi);
427
428         qlen = qman_fqr_get_counter(sc->sc_tx_conf_fqr, 0,
429             e_QM_FQR_COUNTERS_FRAME);
430
431         if (qlen == 0) {
432                 DTSEC_LOCK(sc);
433
434                 if (sc->sc_tx_fqr_full) {
435                         sc->sc_tx_fqr_full = 0;
436                         dtsec_rm_if_start_locked(sc);
437                 }
438
439                 DTSEC_UNLOCK(sc);
440         }
441
442         return (e_RX_STORE_RESPONSE_CONTINUE);
443 }
444
445 void
446 dtsec_rm_fqr_rx_free(struct dtsec_softc *sc)
447 {
448
449         if (sc->sc_rx_fqr)
450                 qman_fqr_free(sc->sc_rx_fqr);
451 }
452
453 int
454 dtsec_rm_fqr_rx_init(struct dtsec_softc *sc)
455 {
456         t_Error error;
457         t_Handle fqr;
458
459         /* Default Frame Queue */
460         fqr = qman_fqr_create(1, DTSEC_RM_FQR_RX_CHANNEL, DTSEC_RM_FQR_RX_WQ,
461             false, 0, false, false, true, false, 0, 0, 0);
462         if (fqr == NULL) {
463                 device_printf(sc->sc_dev, "could not create default RX queue"
464                     "\n");
465                 return (EIO);
466         }
467
468         sc->sc_rx_fqr = fqr;
469         sc->sc_rx_fqid = qman_fqr_get_base_fqid(fqr);
470
471         error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_rx_callback, sc);
472         if (error != E_OK) {
473                 device_printf(sc->sc_dev, "could not register RX callback\n");
474                 dtsec_rm_fqr_rx_free(sc);
475                 return (EIO);
476         }
477
478         return (0);
479 }
480
481 void
482 dtsec_rm_fqr_tx_free(struct dtsec_softc *sc)
483 {
484
485         if (sc->sc_tx_fqr)
486                 qman_fqr_free(sc->sc_tx_fqr);
487
488         if (sc->sc_tx_conf_fqr)
489                 qman_fqr_free(sc->sc_tx_conf_fqr);
490 }
491
492 int
493 dtsec_rm_fqr_tx_init(struct dtsec_softc *sc)
494 {
495         t_Error error;
496         t_Handle fqr;
497
498         /* TX Frame Queue */
499         fqr = qman_fqr_create(1, sc->sc_port_tx_qman_chan,
500             DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0);
501         if (fqr == NULL) {
502                 device_printf(sc->sc_dev, "could not create default TX queue"
503                     "\n");
504                 return (EIO);
505         }
506
507         sc->sc_tx_fqr = fqr;
508
509         /* TX Confirmation Frame Queue */
510         fqr = qman_fqr_create(1, DTSEC_RM_FQR_TX_CONF_CHANNEL,
511             DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0,
512             0);
513         if (fqr == NULL) {
514                 device_printf(sc->sc_dev, "could not create TX confirmation "
515                     "queue\n");
516                 dtsec_rm_fqr_tx_free(sc);
517                 return (EIO);
518         }
519
520         sc->sc_tx_conf_fqr = fqr;
521         sc->sc_tx_conf_fqid = qman_fqr_get_base_fqid(fqr);
522
523         error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_tx_confirm_callback, sc);
524         if (error != E_OK) {
525                 device_printf(sc->sc_dev, "could not register TX confirmation "
526                     "callback\n");
527                 dtsec_rm_fqr_tx_free(sc);
528                 return (EIO);
529         }
530
531         return (0);
532 }
533 /** @} */
534
535
536 /**
537  * @group dTSEC IFnet routines.
538  * @{
539  */
540 void
541 dtsec_rm_if_start_locked(struct dtsec_softc *sc)
542 {
543         vm_size_t dsize, psize, ssize;
544         struct dtsec_rm_frame_info *fi;
545         unsigned int qlen, i;
546         struct mbuf *m0, *m;
547         vm_offset_t vaddr;
548         vm_paddr_t paddr;
549         t_DpaaFD fd;
550
551         DTSEC_LOCK_ASSERT(sc);
552         /* TODO: IFF_DRV_OACTIVE */
553
554         if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
555                 return;
556
557         if ((sc->sc_ifnet->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
558                 return;
559
560         while (!IFQ_DRV_IS_EMPTY(&sc->sc_ifnet->if_snd)) {
561                 /* Check length of the TX queue */
562                 qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0,
563                     e_QM_FQR_COUNTERS_FRAME);
564
565                 if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
566                         sc->sc_tx_fqr_full = 1;
567                         return;
568                 }
569
570                 fi = dtsec_rm_fi_alloc(sc);
571                 if (fi == NULL)
572                         return;
573
574                 IFQ_DRV_DEQUEUE(&sc->sc_ifnet->if_snd, m0);
575                 if (m0 == NULL) {
576                         dtsec_rm_fi_free(sc, fi);
577                         return;
578                 }
579
580                 i = 0;
581                 m = m0;
582                 psize = 0;
583                 dsize = 0;
584                 fi->fi_mbuf = m0;
585                 while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
586                         if (m->m_len == 0)
587                                 continue;
588
589                         /*
590                          * First entry in scatter-gather table is used to keep
591                          * pointer to frame info structure.
592                          */
593                         DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi);
594                         DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0);
595
596                         DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
597                         DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
598                         DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
599                         DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
600                         i++;
601
602                         dsize = m->m_len;
603                         vaddr = (vm_offset_t)m->m_data;
604                         while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
605                                 paddr = XX_VirtToPhys((void *)vaddr);
606                                 ssize = PAGE_SIZE - (paddr & 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 /** @} */