2 * Copyright (c) 2011-2012 Semihalf.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
40 #include <sys/sched.h>
42 #include <machine/tlb.h>
46 devclass_t bman_devclass;
48 static struct bman_softc *bman_sc;
50 extern t_Handle bman_portal_setup(struct bman_softc *bsc);
53 bman_exception(t_Handle h_App, e_BmExceptions exception)
55 struct bman_softc *sc;
61 case e_BM_EX_INVALID_COMMAND:
62 message = "Invalid Command Verb";
64 case e_BM_EX_FBPR_THRESHOLD:
65 message = "FBPR pool exhaused. Consider increasing "
68 case e_BM_EX_SINGLE_ECC:
69 message = "Single bit ECC error";
71 case e_BM_EX_MULTI_ECC:
72 message = "Multi bit ECC error";
75 message = "Unknown error";
78 device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message);
82 bman_attach(device_t dev)
84 struct bman_softc *sc;
89 sc = device_get_softc(dev);
93 /* Check if MallocSmart allocator is ready */
94 if (XX_MallocSmartInit() != E_OK)
97 /* Allocate resources */
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)
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)
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;
117 bp.errIrq = (uintptr_t)sc->sc_ires;
119 bp.partNumOfPools = BM_MAX_NUM_OF_POOLS;
121 sc->sc_bh = BM_Config(&bp);
122 if (sc->sc_bh == NULL)
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);
130 error = BM_Init(sc->sc_bh);
134 error = BM_GetRevision(sc->sc_bh, &rev);
138 device_printf(dev, "Hardware version: %d.%d.\n",
139 rev.majorRev, rev.minorRev);
149 bman_detach(device_t dev)
151 struct bman_softc *sc;
153 sc = device_get_softc(dev);
155 if (sc->sc_bh != NULL)
158 if (sc->sc_ires != NULL)
159 bus_release_resource(dev, SYS_RES_IRQ,
160 sc->sc_irid, sc->sc_ires);
162 if (sc->sc_rres != NULL)
163 bus_release_resource(dev, SYS_RES_MEMORY,
164 sc->sc_rrid, sc->sc_rres);
170 bman_suspend(device_t dev)
177 bman_resume(device_t dev)
184 bman_shutdown(device_t dev)
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)
202 uint32_t thresholds[MAX_DEPLETION_THRESHOLDS];
203 struct bman_softc *sc;
204 t_Handle pool, portal;
213 portal = bman_portal_setup(sc);
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;
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;
230 pool = BM_POOL_Config(&bpp);
235 * Buffer context must be disabled on FreeBSD
236 * as it could cause memory corruption.
238 BM_POOL_ConfigBuffContextMode(pool, 0);
240 if (minBuffers != 0 || maxBuffers != 0) {
241 error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers);
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);
256 error = BM_POOL_Init(pool);
260 *bpid = BM_POOL_GetId(pool);
261 sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid);
277 bman_pool_destroy(t_Handle pool)
279 struct bman_softc *sc;
282 thread_lock(curthread);
283 sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]);
284 thread_unlock(curthread);
288 thread_lock(curthread);
289 sched_unbind(curthread);
290 thread_unlock(curthread);
296 bman_pool_fill(t_Handle pool, uint16_t nbufs)
298 struct bman_softc *sc;
305 portal = bman_portal_setup(sc);
306 if (portal == NULL) {
311 error = BM_POOL_FillBufs(pool, portal, nbufs);
315 return ((error == E_OK) ? 0 : EIO);
319 bman_get_buffer(t_Handle pool)
321 struct bman_softc *sc;
328 portal = bman_portal_setup(sc);
329 if (portal == NULL) {
334 buffer = BM_POOL_GetBuf(pool, portal);
342 bman_put_buffer(t_Handle pool, void *buffer)
344 struct bman_softc *sc;
351 portal = bman_portal_setup(sc);
352 if (portal == NULL) {
357 error = BM_POOL_PutBuf(pool, portal, buffer);
361 return ((error == E_OK) ? 0 : EIO);
365 bman_count(t_Handle pool)
368 return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT));