xref: /freebsd/sys/dev/dpaa/if_dtsec_im.c (revision 1d386b48)
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_mac_ext.h>
54 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
55 #include <contrib/ncsw/inc/xx_ext.h>
56 
57 #include "fman.h"
58 #include "if_dtsec.h"
59 #include "if_dtsec_im.h"
60 
61 
62 /**
63  * @group dTSEC FMan PORT routines.
64  * @{
65  */
66 static e_RxStoreResponse
67 dtsec_im_fm_port_rx_callback(t_Handle app, uint8_t *data, uint16_t length,
68     uint16_t status, uint8_t position, t_Handle buf_context)
69 {
70 	struct dtsec_softc *sc;
71 	struct mbuf *m;
72 
73 	/* TODO STATUS / Position checking */
74 	sc = app;
75 
76 	m = m_devget(data, length, 0, sc->sc_ifnet, NULL);
77 	if (m)
78 		if_input(sc->sc_ifnet, m);
79 
80 	XX_FreeSmart(data);
81 
82 	return (e_RX_STORE_RESPONSE_CONTINUE);
83 }
84 
85 static void
86 dtsec_im_fm_port_tx_conf_callback(t_Handle app, uint8_t *data, uint16_t status,
87     t_Handle buf_context)
88 {
89 
90 	/* TODO: Check status */
91 	XX_FreeSmart(data);
92 }
93 
94 static uint8_t *
95 dtsec_im_fm_port_rx_get_buf(t_Handle buffer_pool, t_Handle *buf_context_handle)
96 {
97 	struct dtsec_softc *sc;
98 	uint8_t *buffer;
99 
100 	sc = buffer_pool;
101 
102 	buffer = XX_MallocSmart(FM_PORT_BUFFER_SIZE, 0, sizeof(void *));
103 	if (!buffer)
104 		device_printf(sc->sc_dev, "couldn't allocate RX buffer.\n");
105 
106 	return (buffer);
107 }
108 
109 static t_Error
110 dtsec_im_fm_port_rx_put_buf(t_Handle buffer_pool, uint8_t *buffer,
111     t_Handle buf_context)
112 {
113 
114 	XX_FreeSmart(buffer);
115 	return (E_OK);
116 }
117 
118 int
119 dtsec_im_fm_port_rx_init(struct dtsec_softc *sc, int unit)
120 {
121 	t_FmPortParams params;
122 	t_BufferPoolInfo *pool_params;
123 	t_FmPortImRxTxParams *im_params;
124 	t_Error error;
125 
126 	memset(&params, 0, sizeof(params));
127 
128 	params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
129 	params.h_Fm = sc->sc_fmh;
130 	params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
131 	params.portId = sc->sc_eth_id;
132 	params.independentModeEnable = TRUE;
133 	params.liodnBase = FM_PORT_LIODN_BASE;
134 	params.f_Exception = dtsec_fm_port_rx_exception_callback;
135 	params.h_App = sc;
136 
137 	im_params = &params.specificParams.imRxTxParams;
138 	im_params->h_FmMuram = sc->sc_muramh;
139 	im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
140 	im_params->dataMemId = FM_PORT_MEM_ID;
141 	im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
142 	im_params->f_RxStore = dtsec_im_fm_port_rx_callback;
143 
144 	pool_params = &params.specificParams.imRxTxParams.rxPoolParams;
145 	pool_params->h_BufferPool = sc;
146 	pool_params->f_GetBuf = dtsec_im_fm_port_rx_get_buf;
147 	pool_params->f_PutBuf = dtsec_im_fm_port_rx_put_buf;
148 	pool_params->bufferSize = FM_PORT_BUFFER_SIZE;
149 
150 	sc->sc_rxph = FM_PORT_Config(&params);
151 	if (sc->sc_rxph == NULL) {
152 		device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
153 		return (ENXIO);
154 	}
155 
156 	error = FM_PORT_Init(sc->sc_rxph);
157 	if (error != E_OK) {
158 		device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
159 		FM_PORT_Free(sc->sc_rxph);
160 		return (ENXIO);
161 	}
162 
163 	if (bootverbose)
164 		device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
165 		    sc->sc_port_rx_hw_id);
166 
167 	return (0);
168 }
169 
170 int
171 dtsec_im_fm_port_tx_init(struct dtsec_softc *sc, int unit)
172 {
173 	t_FmPortParams params;
174 	t_FmPortImRxTxParams *im_params;
175 	t_Error error;
176 
177 	memset(&params, 0, sizeof(params));
178 
179 	params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
180 	params.h_Fm = sc->sc_fmh;
181 	params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
182 	params.portId = unit;
183 	params.independentModeEnable = TRUE;
184 	params.liodnBase = FM_PORT_LIODN_BASE;
185 	params.f_Exception = dtsec_fm_port_tx_exception_callback;
186 	params.h_App = sc;
187 
188 	im_params = &params.specificParams.imRxTxParams;
189 	im_params->h_FmMuram = sc->sc_muramh;
190 	im_params->liodnOffset = FM_PORT_LIODN_OFFSET;
191 	im_params->dataMemId = FM_PORT_MEM_ID;
192 	im_params->dataMemAttributes = FM_PORT_MEM_ATTR;
193 	im_params->f_TxConf = dtsec_im_fm_port_tx_conf_callback;
194 
195 	sc->sc_txph = FM_PORT_Config(&params);
196 	if (sc->sc_txph == NULL) {
197 		device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
198 		return (ENXIO);
199 	}
200 
201 	error = FM_PORT_Init(sc->sc_txph);
202 	if (error != E_OK) {
203 		device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
204 		FM_PORT_Free(sc->sc_txph);
205 		return (ENXIO);
206 	}
207 
208 	if (bootverbose)
209 		device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
210 		    sc->sc_port_tx_hw_id);
211 
212 	return (0);
213 }
214 /** @} */
215 
216 
217 /**
218  * @group dTSEC IFnet routines.
219  * @{
220  */
221 void
222 dtsec_im_if_start_locked(struct dtsec_softc *sc)
223 {
224 	uint8_t *buffer;
225 	uint16_t length;
226 	struct mbuf *m;
227 	int error;
228 
229 	DTSEC_LOCK_ASSERT(sc);
230 	/* TODO: IFF_DRV_OACTIVE */
231 
232 	if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
233 		return;
234 
235 	if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
236 		return;
237 
238 	while (!if_sendq_empty(sc->sc_ifnet)) {
239 		m = if_dequeue(sc->sc_ifnet);
240 		if (m == NULL)
241 			break;
242 
243 		length = m_length(m, NULL);
244 		buffer = XX_MallocSmart(length, 0, sizeof(void *));
245 		if (!buffer) {
246 			m_freem(m);
247 			break;
248 		}
249 
250 		m_copydata(m, 0, length, buffer);
251 		m_freem(m);
252 
253 		error = FM_PORT_ImTx(sc->sc_txph, buffer, length, TRUE, buffer);
254 		if (error != E_OK) {
255 			/* TODO: Ring full */
256 			XX_FreeSmart(buffer);
257 			break;
258 		}
259 	}
260 }
261 /** @} */
262