]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/dpaa/if_dtsec_rm.c
MFV r323530,r323533,r323534: 7431 ZFS Channel Programs, and followups
[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/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(&params, 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 = &params.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(&params);
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(&params, 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 = &params.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(&params);
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, 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
351 static e_RxStoreResponse
352 dtsec_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
390 err:
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
398 static e_RxStoreResponse
399 dtsec_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
441 void
442 dtsec_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
449 int
450 dtsec_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
477 void
478 dtsec_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
488 int
489 dtsec_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  */
536 void
537 dtsec_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 /** @} */