1296177Sjhibbits/*-
2296177Sjhibbits * Copyright (c) 2012 Semihalf.
3296177Sjhibbits * All rights reserved.
4296177Sjhibbits *
5296177Sjhibbits * Redistribution and use in source and binary forms, with or without
6296177Sjhibbits * modification, are permitted provided that the following conditions
7296177Sjhibbits * are met:
8296177Sjhibbits * 1. Redistributions of source code must retain the above copyright
9296177Sjhibbits *    notice, this list of conditions and the following disclaimer.
10296177Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright
11296177Sjhibbits *    notice, this list of conditions and the following disclaimer in the
12296177Sjhibbits *    documentation and/or other materials provided with the distribution.
13296177Sjhibbits *
14296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15296177Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16296177Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17296177Sjhibbits * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18296177Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19296177Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20296177Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21296177Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22296177Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23296177Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24296177Sjhibbits * SUCH DAMAGE.
25296177Sjhibbits */
26296177Sjhibbits
27296177Sjhibbits#include <sys/cdefs.h>
28296177Sjhibbits__FBSDID("$FreeBSD$");
29296177Sjhibbits
30296177Sjhibbits#include <sys/param.h>
31296177Sjhibbits#include <sys/systm.h>
32296177Sjhibbits#include <sys/kernel.h>
33296177Sjhibbits#include <sys/module.h>
34296177Sjhibbits#include <sys/bus.h>
35296177Sjhibbits#include <sys/rman.h>
36296177Sjhibbits#include <sys/malloc.h>
37296177Sjhibbits#include <sys/mbuf.h>
38296177Sjhibbits#include <sys/socket.h>
39296177Sjhibbits#include <sys/sysctl.h>
40296177Sjhibbits#include <sys/sockio.h>
41296177Sjhibbits
42296177Sjhibbits#include <net/ethernet.h>
43296177Sjhibbits#include <net/if.h>
44296177Sjhibbits#include <net/if_dl.h>
45296177Sjhibbits#include <net/if_media.h>
46296177Sjhibbits#include <net/if_types.h>
47296177Sjhibbits#include <net/if_arp.h>
48296177Sjhibbits
49296177Sjhibbits#include <dev/mii/mii.h>
50296177Sjhibbits#include <dev/mii/miivar.h>
51296177Sjhibbits
52296177Sjhibbits#include "miibus_if.h"
53296177Sjhibbits
54296177Sjhibbits#include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
55296177Sjhibbits#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
56296177Sjhibbits#include <contrib/ncsw/inc/xx_ext.h>
57296177Sjhibbits
58296177Sjhibbits#include "fman.h"
59296177Sjhibbits#include "bman.h"
60296177Sjhibbits#include "qman.h"
61296177Sjhibbits#include "if_dtsec.h"
62296177Sjhibbits#include "if_dtsec_rm.h"
63296177Sjhibbits
64296177Sjhibbits
65296177Sjhibbits/**
66296177Sjhibbits * @group dTSEC RM private defines.
67296177Sjhibbits * @{
68296177Sjhibbits */
69296177Sjhibbits#define	DTSEC_BPOOLS_USED	(1)
70296177Sjhibbits#define	DTSEC_MAX_TX_QUEUE_LEN	256
71296177Sjhibbits
72296177Sjhibbitsstruct dtsec_rm_frame_info {
73296177Sjhibbits	struct mbuf			*fi_mbuf;
74296177Sjhibbits	t_DpaaSGTE			fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY];
75296177Sjhibbits};
76296177Sjhibbits
77296177Sjhibbitsenum dtsec_rm_pool_params {
78296177Sjhibbits	DTSEC_RM_POOL_RX_LOW_MARK	= 16,
79296177Sjhibbits	DTSEC_RM_POOL_RX_HIGH_MARK	= 64,
80296177Sjhibbits	DTSEC_RM_POOL_RX_MAX_SIZE	= 256,
81296177Sjhibbits
82296177Sjhibbits	DTSEC_RM_POOL_FI_LOW_MARK	= 16,
83296177Sjhibbits	DTSEC_RM_POOL_FI_HIGH_MARK	= 64,
84296177Sjhibbits	DTSEC_RM_POOL_FI_MAX_SIZE	= 256,
85296177Sjhibbits};
86296177Sjhibbits
87296177Sjhibbitsenum dtsec_rm_fqr_params {
88296177Sjhibbits	DTSEC_RM_FQR_RX_CHANNEL		= e_QM_FQ_CHANNEL_POOL1,
89296177Sjhibbits	DTSEC_RM_FQR_RX_WQ		= 1,
90296177Sjhibbits	DTSEC_RM_FQR_TX_CONF_CHANNEL	= e_QM_FQ_CHANNEL_SWPORTAL0,
91296177Sjhibbits	DTSEC_RM_FQR_TX_WQ		= 1,
92296177Sjhibbits	DTSEC_RM_FQR_TX_CONF_WQ		= 1
93296177Sjhibbits};
94296177Sjhibbits/** @} */
95296177Sjhibbits
96296177Sjhibbits
97296177Sjhibbits/**
98296177Sjhibbits * @group dTSEC Frame Info routines.
99296177Sjhibbits * @{
100296177Sjhibbits */
101296177Sjhibbitsvoid
102296177Sjhibbitsdtsec_rm_fi_pool_free(struct dtsec_softc *sc)
103296177Sjhibbits{
104296177Sjhibbits
105296177Sjhibbits	if (sc->sc_fi_zone != NULL)
106296177Sjhibbits		uma_zdestroy(sc->sc_fi_zone);
107296177Sjhibbits}
108296177Sjhibbits
109296177Sjhibbitsint
110296177Sjhibbitsdtsec_rm_fi_pool_init(struct dtsec_softc *sc)
111296177Sjhibbits{
112296177Sjhibbits
113296177Sjhibbits	snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info",
114296177Sjhibbits	    device_get_nameunit(sc->sc_dev));
115296177Sjhibbits
116296177Sjhibbits	sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname,
117296177Sjhibbits	    sizeof(struct dtsec_rm_frame_info), NULL, NULL, NULL, NULL,
118296177Sjhibbits	    sizeof(void *), 0);
119296177Sjhibbits	if (sc->sc_fi_zone == NULL)
120296177Sjhibbits		return (EIO);
121296177Sjhibbits
122296177Sjhibbits	return (0);
123296177Sjhibbits}
124296177Sjhibbits
125296177Sjhibbitsstatic struct dtsec_rm_frame_info *
126296177Sjhibbitsdtsec_rm_fi_alloc(struct dtsec_softc *sc)
127296177Sjhibbits{
128296177Sjhibbits	struct dtsec_rm_frame_info *fi;
129296177Sjhibbits
130296177Sjhibbits	fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT);
131296177Sjhibbits
132296177Sjhibbits	return (fi);
133296177Sjhibbits}
134296177Sjhibbits
135296177Sjhibbitsstatic void
136296177Sjhibbitsdtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi)
137296177Sjhibbits{
138296177Sjhibbits
139296177Sjhibbits	XX_UntrackAddress(fi);
140296177Sjhibbits	uma_zfree(sc->sc_fi_zone, fi);
141296177Sjhibbits}
142296177Sjhibbits/** @} */
143296177Sjhibbits
144296177Sjhibbits
145296177Sjhibbits/**
146296177Sjhibbits * @group dTSEC FMan PORT routines.
147296177Sjhibbits * @{
148296177Sjhibbits */
149296177Sjhibbitsint
150296177Sjhibbitsdtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit)
151296177Sjhibbits{
152296177Sjhibbits	t_FmPortParams params;
153296177Sjhibbits	t_FmPortRxParams *rx_params;
154296177Sjhibbits	t_FmPortExtPools *pool_params;
155296177Sjhibbits	t_Error error;
156296177Sjhibbits
157296177Sjhibbits	memset(&params, 0, sizeof(params));
158296177Sjhibbits
159296177Sjhibbits	params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
160296177Sjhibbits	params.h_Fm = sc->sc_fmh;
161296177Sjhibbits	params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
162296177Sjhibbits	params.portId = sc->sc_eth_id;
163296177Sjhibbits	params.independentModeEnable = FALSE;
164296177Sjhibbits	params.liodnBase = FM_PORT_LIODN_BASE;
165296177Sjhibbits	params.f_Exception = dtsec_fm_port_rx_exception_callback;
166296177Sjhibbits	params.h_App = sc;
167296177Sjhibbits
168296177Sjhibbits	rx_params = &params.specificParams.rxParams;
169296177Sjhibbits	rx_params->errFqid = sc->sc_rx_fqid;
170296177Sjhibbits	rx_params->dfltFqid = sc->sc_rx_fqid;
171296177Sjhibbits	rx_params->liodnOffset = 0;
172296177Sjhibbits
173296177Sjhibbits	pool_params = &rx_params->extBufPools;
174296177Sjhibbits	pool_params->numOfPoolsUsed = DTSEC_BPOOLS_USED;
175296177Sjhibbits	pool_params->extBufPool->id = sc->sc_rx_bpid;
176296177Sjhibbits	pool_params->extBufPool->size = FM_PORT_BUFFER_SIZE;
177296177Sjhibbits
178296177Sjhibbits	sc->sc_rxph = FM_PORT_Config(&params);
179296177Sjhibbits	if (sc->sc_rxph == NULL) {
180296177Sjhibbits		device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
181296177Sjhibbits		return (ENXIO);
182296177Sjhibbits	}
183296177Sjhibbits
184296177Sjhibbits	error = FM_PORT_Init(sc->sc_rxph);
185296177Sjhibbits	if (error != E_OK) {
186296177Sjhibbits		device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
187296177Sjhibbits		FM_PORT_Free(sc->sc_rxph);
188296177Sjhibbits		return (ENXIO);
189296177Sjhibbits	}
190296177Sjhibbits
191296177Sjhibbits	if (bootverbose)
192296177Sjhibbits		device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
193296177Sjhibbits		    sc->sc_port_rx_hw_id);
194296177Sjhibbits
195296177Sjhibbits	return (0);
196296177Sjhibbits}
197296177Sjhibbits
198296177Sjhibbitsint
199296177Sjhibbitsdtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit)
200296177Sjhibbits{
201296177Sjhibbits	t_FmPortParams params;
202296177Sjhibbits	t_FmPortNonRxParams *tx_params;
203296177Sjhibbits	t_Error error;
204296177Sjhibbits
205296177Sjhibbits	memset(&params, 0, sizeof(params));
206296177Sjhibbits
207296177Sjhibbits	params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
208296177Sjhibbits	params.h_Fm = sc->sc_fmh;
209296177Sjhibbits	params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
210296177Sjhibbits	params.portId = sc->sc_eth_id;
211296177Sjhibbits	params.independentModeEnable = FALSE;
212296177Sjhibbits	params.liodnBase = FM_PORT_LIODN_BASE;
213296177Sjhibbits	params.f_Exception = dtsec_fm_port_tx_exception_callback;
214296177Sjhibbits	params.h_App = sc;
215296177Sjhibbits
216296177Sjhibbits	tx_params = &params.specificParams.nonRxParams;
217296177Sjhibbits	tx_params->errFqid = sc->sc_tx_conf_fqid;
218296177Sjhibbits	tx_params->dfltFqid = sc->sc_tx_conf_fqid;
219296177Sjhibbits	tx_params->qmChannel = sc->sc_port_tx_qman_chan;
220296177Sjhibbits#ifdef FM_OP_PARTITION_ERRATA_FMANx8
221296177Sjhibbits	tx_params->opLiodnOffset = 0;
222296177Sjhibbits#endif
223296177Sjhibbits
224296177Sjhibbits	sc->sc_txph = FM_PORT_Config(&params);
225296177Sjhibbits	if (sc->sc_txph == NULL) {
226296177Sjhibbits		device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
227296177Sjhibbits		return (ENXIO);
228296177Sjhibbits	}
229296177Sjhibbits
230296177Sjhibbits	error = FM_PORT_Init(sc->sc_txph);
231296177Sjhibbits	if (error != E_OK) {
232296177Sjhibbits		device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
233296177Sjhibbits		FM_PORT_Free(sc->sc_txph);
234296177Sjhibbits		return (ENXIO);
235296177Sjhibbits	}
236296177Sjhibbits
237296177Sjhibbits	if (bootverbose)
238296177Sjhibbits		device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
239296177Sjhibbits		    sc->sc_port_tx_hw_id);
240296177Sjhibbits
241296177Sjhibbits	return (0);
242296177Sjhibbits}
243296177Sjhibbits/** @} */
244296177Sjhibbits
245296177Sjhibbits
246296177Sjhibbits/**
247296177Sjhibbits * @group dTSEC buffer pools routines.
248296177Sjhibbits * @{
249296177Sjhibbits */
250296177Sjhibbitsstatic t_Error
251296177Sjhibbitsdtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool, uint8_t *buffer,
252296177Sjhibbits    t_Handle context)
253296177Sjhibbits{
254296177Sjhibbits	struct dtsec_softc *sc;
255296177Sjhibbits
256296177Sjhibbits	sc = h_BufferPool;
257296177Sjhibbits	uma_zfree(sc->sc_rx_zone, buffer);
258296177Sjhibbits
259296177Sjhibbits	return (E_OK);
260296177Sjhibbits}
261296177Sjhibbits
262296177Sjhibbitsstatic uint8_t *
263296177Sjhibbitsdtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool, t_Handle *context)
264296177Sjhibbits{
265296177Sjhibbits	struct dtsec_softc *sc;
266296177Sjhibbits	uint8_t *buffer;
267296177Sjhibbits
268296177Sjhibbits	sc = h_BufferPool;
269296177Sjhibbits	buffer = uma_zalloc(sc->sc_rx_zone, M_NOWAIT);
270296177Sjhibbits
271296177Sjhibbits	return (buffer);
272296177Sjhibbits}
273296177Sjhibbits
274296177Sjhibbitsstatic void
275296177Sjhibbitsdtsec_rm_pool_rx_depleted(t_Handle h_App, bool in)
276296177Sjhibbits{
277296177Sjhibbits	struct dtsec_softc *sc;
278296177Sjhibbits	unsigned int count;
279296177Sjhibbits
280296177Sjhibbits	sc = h_App;
281296177Sjhibbits
282296177Sjhibbits	if (!in)
283296177Sjhibbits		return;
284296177Sjhibbits
285296177Sjhibbits	while (1) {
286296177Sjhibbits		count = bman_count(sc->sc_rx_pool);
287296177Sjhibbits		if (count > DTSEC_RM_POOL_RX_HIGH_MARK)
288296177Sjhibbits			return;
289296177Sjhibbits
290296177Sjhibbits		bman_pool_fill(sc->sc_rx_pool, DTSEC_RM_POOL_RX_HIGH_MARK);
291296177Sjhibbits	}
292296177Sjhibbits}
293296177Sjhibbits
294296177Sjhibbitsvoid
295296177Sjhibbitsdtsec_rm_pool_rx_free(struct dtsec_softc *sc)
296296177Sjhibbits{
297296177Sjhibbits
298296177Sjhibbits	if (sc->sc_rx_pool != NULL)
299296177Sjhibbits		bman_pool_destroy(sc->sc_rx_pool);
300296177Sjhibbits
301296177Sjhibbits	if (sc->sc_rx_zone != NULL)
302296177Sjhibbits		uma_zdestroy(sc->sc_rx_zone);
303296177Sjhibbits}
304296177Sjhibbits
305296177Sjhibbitsint
306296177Sjhibbitsdtsec_rm_pool_rx_init(struct dtsec_softc *sc)
307296177Sjhibbits{
308296177Sjhibbits
309296177Sjhibbits	/* FM_PORT_BUFFER_SIZE must be less than PAGE_SIZE */
310296177Sjhibbits	CTASSERT(FM_PORT_BUFFER_SIZE < PAGE_SIZE);
311296177Sjhibbits
312296177Sjhibbits	snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers",
313296177Sjhibbits	    device_get_nameunit(sc->sc_dev));
314296177Sjhibbits
315296177Sjhibbits	sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, FM_PORT_BUFFER_SIZE, NULL,
316296177Sjhibbits	    NULL, NULL, NULL, FM_PORT_BUFFER_SIZE, 0);
317296177Sjhibbits	if (sc->sc_rx_zone == NULL)
318296177Sjhibbits		return (EIO);
319296177Sjhibbits
320296177Sjhibbits	sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, FM_PORT_BUFFER_SIZE,
321296177Sjhibbits	    0, 0, DTSEC_RM_POOL_RX_MAX_SIZE, dtsec_rm_pool_rx_get_buffer,
322296177Sjhibbits	    dtsec_rm_pool_rx_put_buffer, DTSEC_RM_POOL_RX_LOW_MARK,
323296177Sjhibbits	    DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL,
324296177Sjhibbits	    NULL);
325296177Sjhibbits	if (sc->sc_rx_pool == NULL) {
326296177Sjhibbits		dtsec_rm_pool_rx_free(sc);
327296177Sjhibbits		return (EIO);
328296177Sjhibbits	}
329296177Sjhibbits
330296177Sjhibbits	return (0);
331296177Sjhibbits}
332296177Sjhibbits/** @} */
333296177Sjhibbits
334296177Sjhibbits
335296177Sjhibbits/**
336296177Sjhibbits * @group dTSEC Frame Queue Range routines.
337296177Sjhibbits * @{
338296177Sjhibbits */
339296177Sjhibbitsstatic void
340296177Sjhibbitsdtsec_rm_fqr_mext_free(struct mbuf *m, void *buffer, void *arg)
341296177Sjhibbits{
342296177Sjhibbits	struct dtsec_softc *sc;
343296177Sjhibbits
344296177Sjhibbits	sc = arg;
345296177Sjhibbits	if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE)
346296177Sjhibbits		bman_put_buffer(sc->sc_rx_pool, buffer);
347296177Sjhibbits	else
348296177Sjhibbits		dtsec_rm_pool_rx_put_buffer(arg, buffer, NULL);
349296177Sjhibbits}
350296177Sjhibbits
351296177Sjhibbitsstatic e_RxStoreResponse
352296177Sjhibbitsdtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal,
353296177Sjhibbits    uint32_t fqid_off, t_DpaaFD *frame)
354296177Sjhibbits{
355296177Sjhibbits	struct dtsec_softc *sc;
356296177Sjhibbits	struct mbuf *m;
357296177Sjhibbits
358296177Sjhibbits	m = NULL;
359296177Sjhibbits	sc = app;
360296177Sjhibbits
361296177Sjhibbits	KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF,
362296177Sjhibbits	    ("%s(): Got unsupported frame format 0x%02X!", __func__,
363296177Sjhibbits	    DPAA_FD_GET_FORMAT(frame)));
364296177Sjhibbits
365296177Sjhibbits	KASSERT(DPAA_FD_GET_OFFSET(frame) == 0,
366296177Sjhibbits	    ("%s(): Only offset 0 is supported!", __func__));
367296177Sjhibbits
368296177Sjhibbits	if (DPAA_FD_GET_STATUS(frame) != 0) {
369296177Sjhibbits		device_printf(sc->sc_dev, "RX error: 0x%08X\n",
370296177Sjhibbits		    DPAA_FD_GET_STATUS(frame));
371296177Sjhibbits		goto err;
372296177Sjhibbits	}
373296177Sjhibbits
374296177Sjhibbits	m = m_gethdr(M_NOWAIT, MT_HEADER);
375296177Sjhibbits	if (m == NULL)
376296177Sjhibbits		goto err;
377296177Sjhibbits
378296295Sjhibbits	m_extadd(m, DPAA_FD_GET_ADDR(frame), FM_PORT_BUFFER_SIZE,
379296177Sjhibbits	    dtsec_rm_fqr_mext_free, DPAA_FD_GET_ADDR(frame), sc, 0,
380296177Sjhibbits	    EXT_NET_DRV);
381296177Sjhibbits
382296177Sjhibbits	m->m_pkthdr.rcvif = sc->sc_ifnet;
383296177Sjhibbits	m->m_len = DPAA_FD_GET_LENGTH(frame);
384296177Sjhibbits	m_fixhdr(m);
385296177Sjhibbits
386296177Sjhibbits	(*sc->sc_ifnet->if_input)(sc->sc_ifnet, m);
387296177Sjhibbits
388296177Sjhibbits	return (e_RX_STORE_RESPONSE_CONTINUE);
389296177Sjhibbits
390296177Sjhibbitserr:
391296177Sjhibbits	bman_put_buffer(sc->sc_rx_pool, DPAA_FD_GET_ADDR(frame));
392296177Sjhibbits	if (m != NULL)
393296177Sjhibbits		m_freem(m);
394296177Sjhibbits
395296177Sjhibbits	return (e_RX_STORE_RESPONSE_CONTINUE);
396296177Sjhibbits}
397296177Sjhibbits
398296177Sjhibbitsstatic e_RxStoreResponse
399296177Sjhibbitsdtsec_rm_fqr_tx_confirm_callback(t_Handle app, t_Handle fqr, t_Handle portal,
400296177Sjhibbits    uint32_t fqid_off, t_DpaaFD *frame)
401296177Sjhibbits{
402296177Sjhibbits	struct dtsec_rm_frame_info *fi;
403296177Sjhibbits	struct dtsec_softc *sc;
404296177Sjhibbits	unsigned int qlen;
405296177Sjhibbits	t_DpaaSGTE *sgt0;
406296177Sjhibbits
407296177Sjhibbits	sc = app;
408296177Sjhibbits
409296177Sjhibbits	if (DPAA_FD_GET_STATUS(frame) != 0)
410296177Sjhibbits		device_printf(sc->sc_dev, "TX error: 0x%08X\n",
411296177Sjhibbits		    DPAA_FD_GET_STATUS(frame));
412296177Sjhibbits
413296177Sjhibbits	/*
414296177Sjhibbits	 * We are storing struct dtsec_rm_frame_info in first entry
415296177Sjhibbits	 * of scatter-gather table.
416296177Sjhibbits	 */
417296177Sjhibbits	sgt0 = DPAA_FD_GET_ADDR(frame);
418296177Sjhibbits	fi = DPAA_SGTE_GET_ADDR(sgt0);
419296177Sjhibbits
420296177Sjhibbits	/* Free transmitted frame */
421296177Sjhibbits	m_freem(fi->fi_mbuf);
422296177Sjhibbits	dtsec_rm_fi_free(sc, fi);
423296177Sjhibbits
424296177Sjhibbits	qlen = qman_fqr_get_counter(sc->sc_tx_conf_fqr, 0,
425296177Sjhibbits	    e_QM_FQR_COUNTERS_FRAME);
426296177Sjhibbits
427296177Sjhibbits	if (qlen == 0) {
428296177Sjhibbits		DTSEC_LOCK(sc);
429296177Sjhibbits
430296177Sjhibbits		if (sc->sc_tx_fqr_full) {
431296177Sjhibbits			sc->sc_tx_fqr_full = 0;
432296177Sjhibbits			dtsec_rm_if_start_locked(sc);
433296177Sjhibbits		}
434296177Sjhibbits
435296177Sjhibbits		DTSEC_UNLOCK(sc);
436296177Sjhibbits	}
437296177Sjhibbits
438296177Sjhibbits	return (e_RX_STORE_RESPONSE_CONTINUE);
439296177Sjhibbits}
440296177Sjhibbits
441296177Sjhibbitsvoid
442296177Sjhibbitsdtsec_rm_fqr_rx_free(struct dtsec_softc *sc)
443296177Sjhibbits{
444296177Sjhibbits
445296177Sjhibbits	if (sc->sc_rx_fqr)
446296177Sjhibbits		qman_fqr_free(sc->sc_rx_fqr);
447296177Sjhibbits}
448296177Sjhibbits
449296177Sjhibbitsint
450296177Sjhibbitsdtsec_rm_fqr_rx_init(struct dtsec_softc *sc)
451296177Sjhibbits{
452296177Sjhibbits	t_Error error;
453296177Sjhibbits	t_Handle fqr;
454296177Sjhibbits
455296177Sjhibbits	/* Default Frame Queue */
456296177Sjhibbits	fqr = qman_fqr_create(1, DTSEC_RM_FQR_RX_CHANNEL, DTSEC_RM_FQR_RX_WQ,
457296177Sjhibbits	    FALSE, 0, FALSE, FALSE, TRUE, FALSE, 0, 0, 0);
458296177Sjhibbits	if (fqr == NULL) {
459296177Sjhibbits		device_printf(sc->sc_dev, "could not create default RX queue"
460296177Sjhibbits		    "\n");
461296177Sjhibbits		return (EIO);
462296177Sjhibbits	}
463296177Sjhibbits
464296177Sjhibbits	sc->sc_rx_fqr = fqr;
465296177Sjhibbits	sc->sc_rx_fqid = qman_fqr_get_base_fqid(fqr);
466296177Sjhibbits
467296177Sjhibbits	error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_rx_callback, sc);
468296177Sjhibbits	if (error != E_OK) {
469296177Sjhibbits		device_printf(sc->sc_dev, "could not register RX callback\n");
470296177Sjhibbits		dtsec_rm_fqr_rx_free(sc);
471296177Sjhibbits		return (EIO);
472296177Sjhibbits	}
473296177Sjhibbits
474296177Sjhibbits	return (0);
475296177Sjhibbits}
476296177Sjhibbits
477296177Sjhibbitsvoid
478296177Sjhibbitsdtsec_rm_fqr_tx_free(struct dtsec_softc *sc)
479296177Sjhibbits{
480296177Sjhibbits
481296177Sjhibbits	if (sc->sc_tx_fqr)
482296177Sjhibbits		qman_fqr_free(sc->sc_tx_fqr);
483296177Sjhibbits
484296177Sjhibbits	if (sc->sc_tx_conf_fqr)
485296177Sjhibbits		qman_fqr_free(sc->sc_tx_conf_fqr);
486296177Sjhibbits}
487296177Sjhibbits
488296177Sjhibbitsint
489296177Sjhibbitsdtsec_rm_fqr_tx_init(struct dtsec_softc *sc)
490296177Sjhibbits{
491296177Sjhibbits	t_Error error;
492296177Sjhibbits	t_Handle fqr;
493296177Sjhibbits
494296177Sjhibbits	/* TX Frame Queue */
495296177Sjhibbits	fqr = qman_fqr_create(1, sc->sc_port_tx_qman_chan,
496296177Sjhibbits	    DTSEC_RM_FQR_TX_WQ, FALSE, 0, FALSE, FALSE, TRUE, FALSE, 0, 0, 0);
497296177Sjhibbits	if (fqr == NULL) {
498296177Sjhibbits		device_printf(sc->sc_dev, "could not create default TX queue"
499296177Sjhibbits		    "\n");
500296177Sjhibbits		return (EIO);
501296177Sjhibbits	}
502296177Sjhibbits
503296177Sjhibbits	sc->sc_tx_fqr = fqr;
504296177Sjhibbits
505296177Sjhibbits	/* TX Confirmation Frame Queue */
506296177Sjhibbits	fqr = qman_fqr_create(1, DTSEC_RM_FQR_TX_CONF_CHANNEL,
507296177Sjhibbits	    DTSEC_RM_FQR_TX_CONF_WQ, FALSE, 0, FALSE, FALSE, TRUE, FALSE, 0, 0,
508296177Sjhibbits	    0);
509296177Sjhibbits	if (fqr == NULL) {
510296177Sjhibbits		device_printf(sc->sc_dev, "could not create TX confirmation "
511296177Sjhibbits		    "queue\n");
512296177Sjhibbits		dtsec_rm_fqr_tx_free(sc);
513296177Sjhibbits		return (EIO);
514296177Sjhibbits	}
515296177Sjhibbits
516296177Sjhibbits	sc->sc_tx_conf_fqr = fqr;
517296177Sjhibbits	sc->sc_tx_conf_fqid = qman_fqr_get_base_fqid(fqr);
518296177Sjhibbits
519296177Sjhibbits	error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_tx_confirm_callback, sc);
520296177Sjhibbits	if (error != E_OK) {
521296177Sjhibbits		device_printf(sc->sc_dev, "could not register TX confirmation "
522296177Sjhibbits		    "callback\n");
523296177Sjhibbits		dtsec_rm_fqr_tx_free(sc);
524296177Sjhibbits		return (EIO);
525296177Sjhibbits	}
526296177Sjhibbits
527296177Sjhibbits	return (0);
528296177Sjhibbits}
529296177Sjhibbits/** @} */
530296177Sjhibbits
531296177Sjhibbits
532296177Sjhibbits/**
533296177Sjhibbits * @group dTSEC IFnet routines.
534296177Sjhibbits * @{
535296177Sjhibbits */
536296177Sjhibbitsvoid
537296177Sjhibbitsdtsec_rm_if_start_locked(struct dtsec_softc *sc)
538296177Sjhibbits{
539296177Sjhibbits	vm_size_t dsize, psize, ssize;
540296177Sjhibbits	struct dtsec_rm_frame_info *fi;
541296177Sjhibbits	unsigned int qlen, i;
542296177Sjhibbits	struct mbuf *m0, *m;
543296177Sjhibbits	vm_offset_t vaddr;
544296177Sjhibbits	vm_paddr_t paddr;
545296177Sjhibbits	t_DpaaFD fd;
546296177Sjhibbits
547296177Sjhibbits	DTSEC_LOCK_ASSERT(sc);
548296177Sjhibbits	/* TODO: IFF_DRV_OACTIVE */
549296177Sjhibbits
550296177Sjhibbits	if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
551296177Sjhibbits		return;
552296177Sjhibbits
553296177Sjhibbits	if ((sc->sc_ifnet->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
554296177Sjhibbits		return;
555296177Sjhibbits
556296177Sjhibbits	while (!IFQ_DRV_IS_EMPTY(&sc->sc_ifnet->if_snd)) {
557296177Sjhibbits		/* Check length of the TX queue */
558296177Sjhibbits		qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0,
559296177Sjhibbits		    e_QM_FQR_COUNTERS_FRAME);
560296177Sjhibbits
561296177Sjhibbits		if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
562296177Sjhibbits			sc->sc_tx_fqr_full = 1;
563296177Sjhibbits			return;
564296177Sjhibbits		}
565296177Sjhibbits
566296177Sjhibbits		fi = dtsec_rm_fi_alloc(sc);
567296177Sjhibbits		if (fi == NULL)
568296177Sjhibbits			return;
569296177Sjhibbits
570296177Sjhibbits		IFQ_DRV_DEQUEUE(&sc->sc_ifnet->if_snd, m0);
571296177Sjhibbits		if (m0 == NULL) {
572296177Sjhibbits			dtsec_rm_fi_free(sc, fi);
573296177Sjhibbits			return;
574296177Sjhibbits		}
575296177Sjhibbits
576296177Sjhibbits		i = 0;
577296177Sjhibbits		m = m0;
578296177Sjhibbits		psize = 0;
579296177Sjhibbits		dsize = 0;
580296177Sjhibbits		fi->fi_mbuf = m0;
581296177Sjhibbits		while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
582296177Sjhibbits			if (m->m_len == 0)
583296177Sjhibbits				continue;
584296177Sjhibbits
585296177Sjhibbits			/*
586296177Sjhibbits			 * First entry in scatter-gather table is used to keep
587296177Sjhibbits			 * pointer to frame info structure.
588296177Sjhibbits			 */
589296177Sjhibbits			DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi);
590296177Sjhibbits			DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0);
591296177Sjhibbits
592296177Sjhibbits			DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
593296177Sjhibbits			DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
594296177Sjhibbits			DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
595296177Sjhibbits			DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
596296177Sjhibbits			i++;
597296177Sjhibbits
598296177Sjhibbits			dsize = m->m_len;
599296177Sjhibbits			vaddr = (vm_offset_t)m->m_data;
600296177Sjhibbits			while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
601296177Sjhibbits				paddr = XX_VirtToPhys((void *)vaddr);
602296177Sjhibbits				ssize = PAGE_SIZE - (paddr & PAGE_MASK);
603296177Sjhibbits				if (m->m_len < ssize)
604296177Sjhibbits					ssize = m->m_len;
605296177Sjhibbits
606296177Sjhibbits				DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i],
607296177Sjhibbits				    (void *)vaddr);
608296177Sjhibbits				DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], ssize);
609296177Sjhibbits
610296177Sjhibbits				DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
611296177Sjhibbits				DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
612296177Sjhibbits				DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
613296177Sjhibbits				DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
614296177Sjhibbits
615296177Sjhibbits				dsize -= ssize;
616296177Sjhibbits				vaddr += ssize;
617296177Sjhibbits				psize += ssize;
618296177Sjhibbits				i++;
619296177Sjhibbits			}
620296177Sjhibbits
621296177Sjhibbits			if (dsize > 0)
622296177Sjhibbits				break;
623296177Sjhibbits
624296177Sjhibbits			m = m->m_next;
625296177Sjhibbits		}
626296177Sjhibbits
627296177Sjhibbits		/* Check if SG table was constructed properly */
628296177Sjhibbits		if (m != NULL || dsize != 0) {
629296177Sjhibbits			dtsec_rm_fi_free(sc, fi);
630296177Sjhibbits			m_freem(m0);
631296177Sjhibbits			continue;
632296177Sjhibbits		}
633296177Sjhibbits
634296177Sjhibbits		DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i-1], 1);
635296177Sjhibbits
636296177Sjhibbits		DPAA_FD_SET_ADDR(&fd, fi->fi_sgt);
637296177Sjhibbits		DPAA_FD_SET_LENGTH(&fd, psize);
638296177Sjhibbits		DPAA_FD_SET_FORMAT(&fd, e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF);
639296177Sjhibbits
640296177Sjhibbits		DPAA_FD_SET_DD(&fd, 0);
641296177Sjhibbits		DPAA_FD_SET_PID(&fd, 0);
642296177Sjhibbits		DPAA_FD_SET_BPID(&fd, 0);
643296177Sjhibbits		DPAA_FD_SET_OFFSET(&fd, 0);
644296177Sjhibbits		DPAA_FD_SET_STATUS(&fd, 0);
645296177Sjhibbits
646296177Sjhibbits		DTSEC_UNLOCK(sc);
647296177Sjhibbits		if (qman_fqr_enqueue(sc->sc_tx_fqr, 0, &fd) != E_OK) {
648296177Sjhibbits			dtsec_rm_fi_free(sc, fi);
649296177Sjhibbits			m_freem(m0);
650296177Sjhibbits		}
651296177Sjhibbits		DTSEC_LOCK(sc);
652296177Sjhibbits	}
653296177Sjhibbits}
654296177Sjhibbits/** @} */
655