FreeBSD/Linux Kernel Cross Reference
sys/dev/dpaa/bman.c
1 /*-
2 * Copyright (c) 2011-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: releng/12.0/sys/dev/dpaa/bman.c 325118 2017-10-30 03:41:04Z jhibbits $");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34 #include <sys/lock.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/proc.h>
38 #include <sys/pcpu.h>
39 #include <sys/rman.h>
40 #include <sys/sched.h>
41
42 #include <machine/tlb.h>
43
44 #include "bman.h"
45
46 devclass_t bman_devclass;
47
48 static struct bman_softc *bman_sc;
49
50 extern t_Handle bman_portal_setup(struct bman_softc *bsc);
51
52 static void
53 bman_exception(t_Handle h_App, e_BmExceptions exception)
54 {
55 struct bman_softc *sc;
56 const char *message;
57
58 sc = h_App;
59
60 switch (exception) {
61 case e_BM_EX_INVALID_COMMAND:
62 message = "Invalid Command Verb";
63 break;
64 case e_BM_EX_FBPR_THRESHOLD:
65 message = "FBPR pool exhaused. Consider increasing "
66 "BMAN_MAX_BUFFERS";
67 break;
68 case e_BM_EX_SINGLE_ECC:
69 message = "Single bit ECC error";
70 break;
71 case e_BM_EX_MULTI_ECC:
72 message = "Multi bit ECC error";
73 break;
74 default:
75 message = "Unknown error";
76 }
77
78 device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message);
79 }
80
81 int
82 bman_attach(device_t dev)
83 {
84 struct bman_softc *sc;
85 t_BmRevisionInfo rev;
86 t_Error error;
87 t_BmParam bp;
88
89 sc = device_get_softc(dev);
90 sc->sc_dev = dev;
91 bman_sc = sc;
92
93 /* Check if MallocSmart allocator is ready */
94 if (XX_MallocSmartInit() != E_OK)
95 return (ENXIO);
96
97 /* Allocate resources */
98 sc->sc_rrid = 0;
99 sc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY,
100 &sc->sc_rrid, BMAN_CCSR_SIZE, RF_ACTIVE);
101 if (sc->sc_rres == NULL)
102 return (ENXIO);
103
104 sc->sc_irid = 0;
105 sc->sc_ires = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
106 &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE);
107 if (sc->sc_ires == NULL)
108 goto err;
109
110 /* Initialize BMAN */
111 memset(&bp, 0, sizeof(bp));
112 bp.guestId = NCSW_MASTER_ID;
113 bp.baseAddress = rman_get_bushandle(sc->sc_rres);
114 bp.totalNumOfBuffers = BMAN_MAX_BUFFERS;
115 bp.f_Exception = bman_exception;
116 bp.h_App = sc;
117 bp.errIrq = (uintptr_t)sc->sc_ires;
118 bp.partBpidBase = 0;
119 bp.partNumOfPools = BM_MAX_NUM_OF_POOLS;
120
121 sc->sc_bh = BM_Config(&bp);
122 if (sc->sc_bh == NULL)
123 goto err;
124
125 /* Warn if there is less than 5% free FPBR's in pool */
126 error = BM_ConfigFbprThreshold(sc->sc_bh, (BMAN_MAX_BUFFERS / 8) / 20);
127 if (error != E_OK)
128 goto err;
129
130 error = BM_Init(sc->sc_bh);
131 if (error != E_OK)
132 goto err;
133
134 error = BM_GetRevision(sc->sc_bh, &rev);
135 if (error != E_OK)
136 goto err;
137
138 device_printf(dev, "Hardware version: %d.%d.\n",
139 rev.majorRev, rev.minorRev);
140
141 return (0);
142
143 err:
144 bman_detach(dev);
145 return (ENXIO);
146 }
147
148 int
149 bman_detach(device_t dev)
150 {
151 struct bman_softc *sc;
152
153 sc = device_get_softc(dev);
154
155 if (sc->sc_bh != NULL)
156 BM_Free(sc->sc_bh);
157
158 if (sc->sc_ires != NULL)
159 bus_release_resource(dev, SYS_RES_IRQ,
160 sc->sc_irid, sc->sc_ires);
161
162 if (sc->sc_rres != NULL)
163 bus_release_resource(dev, SYS_RES_MEMORY,
164 sc->sc_rrid, sc->sc_rres);
165
166 return (0);
167 }
168
169 int
170 bman_suspend(device_t dev)
171 {
172
173 return (0);
174 }
175
176 int
177 bman_resume(device_t dev)
178 {
179
180 return (0);
181 }
182
183 int
184 bman_shutdown(device_t dev)
185 {
186
187 return (0);
188 }
189
190 /*
191 * BMAN API
192 */
193
194 t_Handle
195 bman_pool_create(uint8_t *bpid, uint16_t bufferSize, uint16_t maxBuffers,
196 uint16_t minBuffers, uint16_t allocBuffers, t_GetBufFunction *f_GetBuf,
197 t_PutBufFunction *f_PutBuf, uint32_t dep_sw_entry, uint32_t dep_sw_exit,
198 uint32_t dep_hw_entry, uint32_t dep_hw_exit,
199 t_BmDepletionCallback *f_Depletion, t_Handle h_BufferPool,
200 t_PhysToVirt *f_PhysToVirt, t_VirtToPhys *f_VirtToPhys)
201 {
202 uint32_t thresholds[MAX_DEPLETION_THRESHOLDS];
203 struct bman_softc *sc;
204 t_Handle pool, portal;
205 t_BmPoolParam bpp;
206 int error;
207
208 sc = bman_sc;
209 pool = NULL;
210
211 sched_pin();
212
213 portal = bman_portal_setup(sc);
214 if (portal == NULL)
215 goto err;
216
217 memset(&bpp, 0, sizeof(bpp));
218 bpp.h_Bm = sc->sc_bh;
219 bpp.h_BmPortal = portal;
220 bpp.h_App = h_BufferPool;
221 bpp.numOfBuffers = allocBuffers;
222
223 bpp.bufferPoolInfo.h_BufferPool = h_BufferPool;
224 bpp.bufferPoolInfo.f_GetBuf = f_GetBuf;
225 bpp.bufferPoolInfo.f_PutBuf = f_PutBuf;
226 bpp.bufferPoolInfo.f_PhysToVirt = f_PhysToVirt;
227 bpp.bufferPoolInfo.f_VirtToPhys = f_VirtToPhys;
228 bpp.bufferPoolInfo.bufferSize = bufferSize;
229
230 pool = BM_POOL_Config(&bpp);
231 if (pool == NULL)
232 goto err;
233
234 /*
235 * Buffer context must be disabled on FreeBSD
236 * as it could cause memory corruption.
237 */
238 BM_POOL_ConfigBuffContextMode(pool, 0);
239
240 if (minBuffers != 0 || maxBuffers != 0) {
241 error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers);
242 if (error != E_OK)
243 goto err;
244 }
245
246 if (f_Depletion != NULL) {
247 thresholds[BM_POOL_DEP_THRESH_SW_ENTRY] = dep_sw_entry;
248 thresholds[BM_POOL_DEP_THRESH_SW_EXIT] = dep_sw_exit;
249 thresholds[BM_POOL_DEP_THRESH_HW_ENTRY] = dep_hw_entry;
250 thresholds[BM_POOL_DEP_THRESH_HW_EXIT] = dep_hw_exit;
251 error = BM_POOL_ConfigDepletion(pool, f_Depletion, thresholds);
252 if (error != E_OK)
253 goto err;
254 }
255
256 error = BM_POOL_Init(pool);
257 if (error != E_OK)
258 goto err;
259
260 *bpid = BM_POOL_GetId(pool);
261 sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid);
262
263 sched_unpin();
264
265 return (pool);
266
267 err:
268 if (pool != NULL)
269 BM_POOL_Free(pool);
270
271 sched_unpin();
272
273 return (NULL);
274 }
275
276 int
277 bman_pool_destroy(t_Handle pool)
278 {
279 struct bman_softc *sc;
280
281 sc = bman_sc;
282 thread_lock(curthread);
283 sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]);
284 thread_unlock(curthread);
285
286 BM_POOL_Free(pool);
287
288 thread_lock(curthread);
289 sched_unbind(curthread);
290 thread_unlock(curthread);
291
292 return (0);
293 }
294
295 int
296 bman_pool_fill(t_Handle pool, uint16_t nbufs)
297 {
298 struct bman_softc *sc;
299 t_Handle portal;
300 int error;
301
302 sc = bman_sc;
303 sched_pin();
304
305 portal = bman_portal_setup(sc);
306 if (portal == NULL) {
307 sched_unpin();
308 return (EIO);
309 }
310
311 error = BM_POOL_FillBufs(pool, portal, nbufs);
312
313 sched_unpin();
314
315 return ((error == E_OK) ? 0 : EIO);
316 }
317
318 void *
319 bman_get_buffer(t_Handle pool)
320 {
321 struct bman_softc *sc;
322 t_Handle portal;
323 void *buffer;
324
325 sc = bman_sc;
326 sched_pin();
327
328 portal = bman_portal_setup(sc);
329 if (portal == NULL) {
330 sched_unpin();
331 return (NULL);
332 }
333
334 buffer = BM_POOL_GetBuf(pool, portal);
335
336 sched_unpin();
337
338 return (buffer);
339 }
340
341 int
342 bman_put_buffer(t_Handle pool, void *buffer)
343 {
344 struct bman_softc *sc;
345 t_Handle portal;
346 int error;
347
348 sc = bman_sc;
349 sched_pin();
350
351 portal = bman_portal_setup(sc);
352 if (portal == NULL) {
353 sched_unpin();
354 return (EIO);
355 }
356
357 error = BM_POOL_PutBuf(pool, portal, buffer);
358
359 sched_unpin();
360
361 return ((error == E_OK) ? 0 : EIO);
362 }
363
364 uint32_t
365 bman_count(t_Handle pool)
366 {
367
368 return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT));
369 }
Cache object: e9286941ff17536c3735d0ac9926765e
|