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 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kernel.h>
31 #include <sys/module.h>
32 #include <sys/bus.h>
33 #include <sys/rman.h>
34 #include <sys/malloc.h>
35 #include <sys/mbuf.h>
36 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 #include <sys/sockio.h>
39
40 #include <net/ethernet.h>
41 #include <net/if.h>
42 #include <net/if_dl.h>
43 #include <net/if_media.h>
44 #include <net/if_types.h>
45 #include <net/if_arp.h>
46
47 #include <dev/mii/mii.h>
48 #include <dev/mii/miivar.h>
49
50 #include "miibus_if.h"
51
52 #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
53 #include <contrib/ncsw/inc/Peripherals/fm_ext.h>
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 #define DTSEC_RM_FQR_RX_CHANNEL e_QM_FQ_CHANNEL_POOL1
88 #define DTSEC_RM_FQR_TX_CONF_CHANNEL e_QM_FQ_CHANNEL_SWPORTAL0
89 enum dtsec_rm_fqr_params {
90 DTSEC_RM_FQR_RX_WQ = 1,
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
dtsec_rm_fi_pool_free(struct dtsec_softc * sc)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
dtsec_rm_fi_pool_init(struct dtsec_softc * sc)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
120 return (0);
121 }
122
123 static struct dtsec_rm_frame_info *
dtsec_rm_fi_alloc(struct dtsec_softc * sc)124 dtsec_rm_fi_alloc(struct dtsec_softc *sc)
125 {
126 struct dtsec_rm_frame_info *fi;
127
128 fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT);
129
130 return (fi);
131 }
132
133 static void
dtsec_rm_fi_free(struct dtsec_softc * sc,struct dtsec_rm_frame_info * fi)134 dtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi)
135 {
136
137 uma_zfree(sc->sc_fi_zone, fi);
138 }
139 /** @} */
140
141
142 /**
143 * @group dTSEC FMan PORT routines.
144 * @{
145 */
146 int
dtsec_rm_fm_port_rx_init(struct dtsec_softc * sc,int unit)147 dtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit)
148 {
149 t_FmPortParams params;
150 t_FmPortRxParams *rx_params;
151 t_FmExtPools *pool_params;
152 t_Error error;
153
154 memset(¶ms, 0, sizeof(params));
155
156 params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
157 params.h_Fm = sc->sc_fmh;
158 params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
159 params.portId = sc->sc_eth_id;
160 params.independentModeEnable = false;
161 params.liodnBase = FM_PORT_LIODN_BASE;
162 params.f_Exception = dtsec_fm_port_rx_exception_callback;
163 params.h_App = sc;
164
165 rx_params = ¶ms.specificParams.rxParams;
166 rx_params->errFqid = sc->sc_rx_fqid;
167 rx_params->dfltFqid = sc->sc_rx_fqid;
168 rx_params->liodnOffset = 0;
169
170 pool_params = &rx_params->extBufPools;
171 pool_params->numOfPoolsUsed = DTSEC_BPOOLS_USED;
172 pool_params->extBufPool->id = sc->sc_rx_bpid;
173 pool_params->extBufPool->size = FM_PORT_BUFFER_SIZE;
174
175 sc->sc_rxph = FM_PORT_Config(¶ms);
176 if (sc->sc_rxph == NULL) {
177 device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
178 return (ENXIO);
179 }
180
181 error = FM_PORT_Init(sc->sc_rxph);
182 if (error != E_OK) {
183 device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
184 FM_PORT_Free(sc->sc_rxph);
185 return (ENXIO);
186 }
187
188 if (bootverbose)
189 device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
190 sc->sc_port_rx_hw_id);
191
192 return (0);
193 }
194
195 int
dtsec_rm_fm_port_tx_init(struct dtsec_softc * sc,int unit)196 dtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit)
197 {
198 t_FmPortParams params;
199 t_FmPortNonRxParams *tx_params;
200 t_Error error;
201
202 memset(¶ms, 0, sizeof(params));
203
204 params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
205 params.h_Fm = sc->sc_fmh;
206 params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
207 params.portId = sc->sc_eth_id;
208 params.independentModeEnable = false;
209 params.liodnBase = FM_PORT_LIODN_BASE;
210 params.f_Exception = dtsec_fm_port_tx_exception_callback;
211 params.h_App = sc;
212
213 tx_params = ¶ms.specificParams.nonRxParams;
214 tx_params->errFqid = sc->sc_tx_conf_fqid;
215 tx_params->dfltFqid = sc->sc_tx_conf_fqid;
216 tx_params->qmChannel = sc->sc_port_tx_qman_chan;
217 #ifdef FM_OP_PARTITION_ERRATA_FMANx8
218 tx_params->opLiodnOffset = 0;
219 #endif
220
221 sc->sc_txph = FM_PORT_Config(¶ms);
222 if (sc->sc_txph == NULL) {
223 device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
224 return (ENXIO);
225 }
226
227 error = FM_PORT_Init(sc->sc_txph);
228 if (error != E_OK) {
229 device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
230 FM_PORT_Free(sc->sc_txph);
231 return (ENXIO);
232 }
233
234 if (bootverbose)
235 device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
236 sc->sc_port_tx_hw_id);
237
238 return (0);
239 }
240 /** @} */
241
242
243 /**
244 * @group dTSEC buffer pools routines.
245 * @{
246 */
247 static t_Error
dtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool,uint8_t * buffer,t_Handle context)248 dtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool, uint8_t *buffer,
249 t_Handle context)
250 {
251 struct dtsec_softc *sc;
252
253 sc = h_BufferPool;
254 uma_zfree(sc->sc_rx_zone, buffer);
255
256 return (E_OK);
257 }
258
259 static uint8_t *
dtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool,t_Handle * context)260 dtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool, t_Handle *context)
261 {
262 struct dtsec_softc *sc;
263 uint8_t *buffer;
264
265 sc = h_BufferPool;
266 buffer = uma_zalloc(sc->sc_rx_zone, M_NOWAIT);
267
268 return (buffer);
269 }
270
271 static void
dtsec_rm_pool_rx_depleted(t_Handle h_App,bool in)272 dtsec_rm_pool_rx_depleted(t_Handle h_App, bool in)
273 {
274 struct dtsec_softc *sc;
275 unsigned int count;
276
277 sc = h_App;
278
279 if (!in)
280 return;
281
282 while (1) {
283 count = bman_count(sc->sc_rx_pool);
284 if (count > DTSEC_RM_POOL_RX_HIGH_MARK)
285 return;
286
287 bman_pool_fill(sc->sc_rx_pool, DTSEC_RM_POOL_RX_HIGH_MARK);
288 }
289 }
290
291 void
dtsec_rm_pool_rx_free(struct dtsec_softc * sc)292 dtsec_rm_pool_rx_free(struct dtsec_softc *sc)
293 {
294
295 if (sc->sc_rx_pool != NULL)
296 bman_pool_destroy(sc->sc_rx_pool);
297
298 if (sc->sc_rx_zone != NULL)
299 uma_zdestroy(sc->sc_rx_zone);
300 }
301
302 int
dtsec_rm_pool_rx_init(struct dtsec_softc * sc)303 dtsec_rm_pool_rx_init(struct dtsec_softc *sc)
304 {
305
306 /* FM_PORT_BUFFER_SIZE must be less than PAGE_SIZE */
307 CTASSERT(FM_PORT_BUFFER_SIZE < PAGE_SIZE);
308
309 snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers",
310 device_get_nameunit(sc->sc_dev));
311
312 sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, FM_PORT_BUFFER_SIZE, NULL,
313 NULL, NULL, NULL, FM_PORT_BUFFER_SIZE - 1, 0);
314
315 sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, FM_PORT_BUFFER_SIZE,
316 0, 0, DTSEC_RM_POOL_RX_MAX_SIZE, dtsec_rm_pool_rx_get_buffer,
317 dtsec_rm_pool_rx_put_buffer, DTSEC_RM_POOL_RX_LOW_MARK,
318 DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL,
319 NULL);
320 if (sc->sc_rx_pool == NULL) {
321 device_printf(sc->sc_dev, "NULL rx pool somehow\n");
322 dtsec_rm_pool_rx_free(sc);
323 return (EIO);
324 }
325
326 return (0);
327 }
328 /** @} */
329
330
331 /**
332 * @group dTSEC Frame Queue Range routines.
333 * @{
334 */
335 static void
dtsec_rm_fqr_mext_free(struct mbuf * m)336 dtsec_rm_fqr_mext_free(struct mbuf *m)
337 {
338 struct dtsec_softc *sc;
339 void *buffer;
340
341 buffer = m->m_ext.ext_arg1;
342 sc = m->m_ext.ext_arg2;
343 if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE)
344 bman_put_buffer(sc->sc_rx_pool, buffer);
345 else
346 dtsec_rm_pool_rx_put_buffer(sc, buffer, NULL);
347 }
348
349 static e_RxStoreResponse
dtsec_rm_fqr_rx_callback(t_Handle app,t_Handle fqr,t_Handle portal,uint32_t fqid_off,t_DpaaFD * frame)350 dtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal,
351 uint32_t fqid_off, t_DpaaFD *frame)
352 {
353 struct dtsec_softc *sc;
354 struct mbuf *m;
355 void *frame_va;
356
357 m = NULL;
358 sc = app;
359
360 frame_va = DPAA_FD_GET_ADDR(frame);
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, frame_va, FM_PORT_BUFFER_SIZE,
379 dtsec_rm_fqr_mext_free, frame_va, 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 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, frame_va);
392 if (m != NULL)
393 m_freem(m);
394
395 return (e_RX_STORE_RESPONSE_CONTINUE);
396 }
397
398 static e_RxStoreResponse
dtsec_rm_fqr_tx_confirm_callback(t_Handle app,t_Handle fqr,t_Handle portal,uint32_t fqid_off,t_DpaaFD * frame)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
dtsec_rm_fqr_rx_free(struct dtsec_softc * sc)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
dtsec_rm_fqr_rx_init(struct dtsec_softc * sc)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
dtsec_rm_fqr_tx_free(struct dtsec_softc * sc)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
dtsec_rm_fqr_tx_init(struct dtsec_softc * sc)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
dtsec_rm_if_start_locked(struct dtsec_softc * sc)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 t_DpaaFD fd;
545
546 DTSEC_LOCK_ASSERT(sc);
547 /* TODO: IFF_DRV_OACTIVE */
548
549 if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
550 return;
551
552 if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
553 return;
554
555 while (!if_sendq_empty(sc->sc_ifnet)) {
556 /* Check length of the TX queue */
557 qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0,
558 e_QM_FQR_COUNTERS_FRAME);
559
560 if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
561 sc->sc_tx_fqr_full = 1;
562 return;
563 }
564
565 fi = dtsec_rm_fi_alloc(sc);
566 if (fi == NULL)
567 return;
568
569 m0 = if_dequeue(sc->sc_ifnet);
570 if (m0 == NULL) {
571 dtsec_rm_fi_free(sc, fi);
572 return;
573 }
574
575 i = 0;
576 m = m0;
577 psize = 0;
578 dsize = 0;
579 fi->fi_mbuf = m0;
580 while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
581 if (m->m_len == 0)
582 continue;
583
584 /*
585 * First entry in scatter-gather table is used to keep
586 * pointer to frame info structure.
587 */
588 DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi);
589 DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0);
590
591 DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
592 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
593 DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
594 DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
595 i++;
596
597 dsize = m->m_len;
598 vaddr = (vm_offset_t)m->m_data;
599 while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
600 ssize = PAGE_SIZE - (vaddr & PAGE_MASK);
601 if (m->m_len < ssize)
602 ssize = m->m_len;
603
604 DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i],
605 (void *)vaddr);
606 DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], ssize);
607
608 DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
609 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
610 DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
611 DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
612
613 dsize -= ssize;
614 vaddr += ssize;
615 psize += ssize;
616 i++;
617 }
618
619 if (dsize > 0)
620 break;
621
622 m = m->m_next;
623 }
624
625 /* Check if SG table was constructed properly */
626 if (m != NULL || dsize != 0) {
627 dtsec_rm_fi_free(sc, fi);
628 m_freem(m0);
629 continue;
630 }
631
632 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i-1], 1);
633
634 DPAA_FD_SET_ADDR(&fd, fi->fi_sgt);
635 DPAA_FD_SET_LENGTH(&fd, psize);
636 DPAA_FD_SET_FORMAT(&fd, e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF);
637
638 fd.liodn = 0;
639 fd.bpid = 0;
640 fd.elion = 0;
641 DPAA_FD_SET_OFFSET(&fd, 0);
642 DPAA_FD_SET_STATUS(&fd, 0);
643
644 DTSEC_UNLOCK(sc);
645 if (qman_fqr_enqueue(sc->sc_tx_fqr, 0, &fd) != E_OK) {
646 dtsec_rm_fi_free(sc, fi);
647 m_freem(m0);
648 }
649 DTSEC_LOCK(sc);
650 }
651 }
652 /** @} */
653