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