1296177Sjhibbits/*-
2296177Sjhibbits * Copyright (c) 2011-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/bus.h>
34296177Sjhibbits#include <sys/lock.h>
35296177Sjhibbits#include <sys/module.h>
36296177Sjhibbits#include <sys/mutex.h>
37296177Sjhibbits#include <sys/proc.h>
38296177Sjhibbits#include <sys/pcpu.h>
39296177Sjhibbits#include <sys/rman.h>
40296177Sjhibbits#include <sys/sched.h>
41296177Sjhibbits
42296177Sjhibbits#include <machine/tlb.h>
43296177Sjhibbits
44296177Sjhibbits#include "bman.h"
45296177Sjhibbits
46296177Sjhibbitsdevclass_t bman_devclass;
47296177Sjhibbits
48296177Sjhibbitsstatic struct bman_softc *bman_sc;
49296177Sjhibbits
50296177Sjhibbitsextern t_Handle bman_portal_setup(struct bman_softc *bsc);
51296177Sjhibbits
52296177Sjhibbitsstatic void
53296177Sjhibbitsbman_exception(t_Handle h_App, e_BmExceptions exception)
54296177Sjhibbits{
55296177Sjhibbits	struct bman_softc *sc;
56296177Sjhibbits	const char *message;
57296177Sjhibbits
58296177Sjhibbits	sc = h_App;
59296177Sjhibbits
60296177Sjhibbits	switch (exception) {
61296177Sjhibbits    	case e_BM_EX_INVALID_COMMAND:
62296177Sjhibbits		message = "Invalid Command Verb";
63296177Sjhibbits		break;
64296177Sjhibbits	case e_BM_EX_FBPR_THRESHOLD:
65296177Sjhibbits		message = "FBPR pool exhaused. Consider increasing "
66296177Sjhibbits		    "BMAN_MAX_BUFFERS";
67296177Sjhibbits		break;
68296177Sjhibbits	case e_BM_EX_SINGLE_ECC:
69296177Sjhibbits		message = "Single bit ECC error";
70296177Sjhibbits		break;
71296177Sjhibbits	case e_BM_EX_MULTI_ECC:
72296177Sjhibbits		message = "Multi bit ECC error";
73296177Sjhibbits		break;
74296177Sjhibbits	default:
75296177Sjhibbits		message = "Unknown error";
76296177Sjhibbits	}
77296177Sjhibbits
78296177Sjhibbits	device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message);
79296177Sjhibbits}
80296177Sjhibbits
81296177Sjhibbitsint
82296177Sjhibbitsbman_attach(device_t dev)
83296177Sjhibbits{
84296177Sjhibbits	struct bman_softc *sc;
85296177Sjhibbits	t_BmRevisionInfo rev;
86296177Sjhibbits	t_Error error;
87296177Sjhibbits	t_BmParam bp;
88296177Sjhibbits
89296177Sjhibbits	sc = device_get_softc(dev);
90296177Sjhibbits	sc->sc_dev = dev;
91296177Sjhibbits	bman_sc = sc;
92296177Sjhibbits
93296177Sjhibbits	/* Check if MallocSmart allocator is ready */
94296177Sjhibbits	if (XX_MallocSmartInit() != E_OK)
95296177Sjhibbits		return (ENXIO);
96296177Sjhibbits
97296177Sjhibbits	/* Allocate resources */
98296177Sjhibbits	sc->sc_rrid = 0;
99296177Sjhibbits	sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY,
100296177Sjhibbits	    &sc->sc_rrid, 0, ~0, BMAN_CCSR_SIZE, RF_ACTIVE);
101296177Sjhibbits	if (sc->sc_rres == NULL)
102296177Sjhibbits		return (ENXIO);
103296177Sjhibbits
104296177Sjhibbits	sc->sc_irid = 0;
105296177Sjhibbits	sc->sc_ires = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
106296177Sjhibbits	    &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE);
107296177Sjhibbits	if (sc->sc_ires == NULL)
108296177Sjhibbits		goto err;
109296177Sjhibbits
110296177Sjhibbits	/* Initialize BMAN */
111296177Sjhibbits	memset(&bp, 0, sizeof(bp));
112296177Sjhibbits	bp.guestId = NCSW_MASTER_ID;
113296177Sjhibbits	bp.baseAddress = rman_get_bushandle(sc->sc_rres);
114296177Sjhibbits	bp.totalNumOfBuffers = BMAN_MAX_BUFFERS;
115296177Sjhibbits	bp.f_Exception = bman_exception;
116296177Sjhibbits	bp.h_App = sc;
117296177Sjhibbits	bp.errIrq = (int)sc->sc_ires;
118296177Sjhibbits	bp.partBpidBase = 0;
119296177Sjhibbits	bp.partNumOfPools = BM_MAX_NUM_OF_POOLS;
120296177Sjhibbits	printf("base address: %llx\n", (uint64_t)bp.baseAddress);
121296177Sjhibbits
122296177Sjhibbits	sc->sc_bh = BM_Config(&bp);
123296177Sjhibbits	if (sc->sc_bh == NULL)
124296177Sjhibbits		goto err;
125296177Sjhibbits
126296177Sjhibbits	/* Warn if there is less than 5% free FPBR's in pool */
127296177Sjhibbits	error = BM_ConfigFbprThreshold(sc->sc_bh, (BMAN_MAX_BUFFERS / 8) / 20);
128296177Sjhibbits	if (error != E_OK)
129296177Sjhibbits		goto err;
130296177Sjhibbits
131296177Sjhibbits	error = BM_Init(sc->sc_bh);
132296177Sjhibbits	if (error != E_OK)
133296177Sjhibbits		goto err;
134296177Sjhibbits
135296177Sjhibbits	error = BM_GetRevision(sc->sc_bh, &rev);
136296177Sjhibbits	if (error != E_OK)
137296177Sjhibbits		goto err;
138296177Sjhibbits
139296177Sjhibbits	device_printf(dev, "Hardware version: %d.%d.\n",
140296177Sjhibbits	    rev.majorRev, rev.minorRev);
141296177Sjhibbits
142296177Sjhibbits	return (0);
143296177Sjhibbits
144296177Sjhibbitserr:
145296177Sjhibbits	bman_detach(dev);
146296177Sjhibbits	return (ENXIO);
147296177Sjhibbits}
148296177Sjhibbits
149296177Sjhibbitsint
150296177Sjhibbitsbman_detach(device_t dev)
151296177Sjhibbits{
152296177Sjhibbits	struct bman_softc *sc;
153296177Sjhibbits
154296177Sjhibbits	sc = device_get_softc(dev);
155296177Sjhibbits
156296177Sjhibbits	if (sc->sc_bh != NULL)
157296177Sjhibbits		BM_Free(sc->sc_bh);
158296177Sjhibbits
159296177Sjhibbits	if (sc->sc_ires != NULL)
160296177Sjhibbits		bus_release_resource(dev, SYS_RES_IRQ,
161296177Sjhibbits		    sc->sc_irid, sc->sc_ires);
162296177Sjhibbits
163296177Sjhibbits	if (sc->sc_rres != NULL)
164296177Sjhibbits		bus_release_resource(dev, SYS_RES_MEMORY,
165296177Sjhibbits		    sc->sc_rrid, sc->sc_rres);
166296177Sjhibbits
167296177Sjhibbits	return (0);
168296177Sjhibbits}
169296177Sjhibbits
170296177Sjhibbitsint
171296177Sjhibbitsbman_suspend(device_t dev)
172296177Sjhibbits{
173296177Sjhibbits
174296177Sjhibbits	return (0);
175296177Sjhibbits}
176296177Sjhibbits
177296177Sjhibbitsint
178296177Sjhibbitsbman_resume(device_t dev)
179296177Sjhibbits{
180296177Sjhibbits
181296177Sjhibbits	return (0);
182296177Sjhibbits}
183296177Sjhibbits
184296177Sjhibbitsint
185296177Sjhibbitsbman_shutdown(device_t dev)
186296177Sjhibbits{
187296177Sjhibbits
188296177Sjhibbits	return (0);
189296177Sjhibbits}
190296177Sjhibbits
191296177Sjhibbits/*
192296177Sjhibbits * BMAN API
193296177Sjhibbits */
194296177Sjhibbits
195296177Sjhibbitst_Handle
196296177Sjhibbitsbman_pool_create(uint8_t *bpid, uint16_t bufferSize, uint16_t maxBuffers,
197296177Sjhibbits    uint16_t minBuffers, uint16_t allocBuffers, t_GetBufFunction *f_GetBuf,
198296177Sjhibbits    t_PutBufFunction *f_PutBuf, uint32_t dep_sw_entry, uint32_t dep_sw_exit,
199296177Sjhibbits    uint32_t dep_hw_entry, uint32_t dep_hw_exit,
200296177Sjhibbits    t_BmDepletionCallback *f_Depletion, t_Handle h_BufferPool,
201296177Sjhibbits    t_PhysToVirt *f_PhysToVirt, t_VirtToPhys *f_VirtToPhys)
202296177Sjhibbits{
203296177Sjhibbits	uint32_t thresholds[MAX_DEPLETION_THRESHOLDS];
204296177Sjhibbits	struct bman_softc *sc;
205296177Sjhibbits	t_Handle pool, portal;
206296177Sjhibbits	t_BmPoolParam bpp;
207296177Sjhibbits	int error;
208296177Sjhibbits
209296177Sjhibbits	sc = bman_sc;
210296177Sjhibbits	pool = NULL;
211296177Sjhibbits
212296177Sjhibbits	sched_pin();
213296177Sjhibbits
214296177Sjhibbits	portal = bman_portal_setup(sc);
215296177Sjhibbits	if (portal == NULL)
216296177Sjhibbits		goto err;
217296177Sjhibbits
218296177Sjhibbits	memset(&bpp, 0, sizeof(bpp));
219296177Sjhibbits	bpp.h_Bm = sc->sc_bh;
220296177Sjhibbits	bpp.h_BmPortal = portal;
221296177Sjhibbits	bpp.h_App = h_BufferPool;
222296177Sjhibbits	bpp.numOfBuffers = allocBuffers;
223296177Sjhibbits
224296177Sjhibbits	bpp.bufferPoolInfo.h_BufferPool = h_BufferPool;
225296177Sjhibbits	bpp.bufferPoolInfo.f_GetBuf = f_GetBuf;
226296177Sjhibbits	bpp.bufferPoolInfo.f_PutBuf = f_PutBuf;
227296177Sjhibbits	bpp.bufferPoolInfo.f_PhysToVirt = f_PhysToVirt;
228296177Sjhibbits	bpp.bufferPoolInfo.f_VirtToPhys = f_VirtToPhys;
229296177Sjhibbits	bpp.bufferPoolInfo.bufferSize = bufferSize;
230296177Sjhibbits
231296177Sjhibbits	pool = BM_POOL_Config(&bpp);
232296177Sjhibbits	if (pool == NULL)
233296177Sjhibbits		goto err;
234296177Sjhibbits
235296177Sjhibbits	/*
236296177Sjhibbits	 * Buffer context must be disabled on FreeBSD
237296177Sjhibbits	 * as it could cause memory corruption.
238296177Sjhibbits	 */
239296177Sjhibbits	BM_POOL_ConfigBuffContextMode(pool, 0);
240296177Sjhibbits
241296177Sjhibbits	if (minBuffers != 0 || maxBuffers != 0) {
242296177Sjhibbits		error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers);
243296177Sjhibbits		if (error != E_OK)
244296177Sjhibbits			goto err;
245296177Sjhibbits	}
246296177Sjhibbits
247296177Sjhibbits	if (f_Depletion != NULL) {
248296177Sjhibbits		thresholds[BM_POOL_DEP_THRESH_SW_ENTRY] = dep_sw_entry;
249296177Sjhibbits		thresholds[BM_POOL_DEP_THRESH_SW_EXIT] = dep_sw_exit;
250296177Sjhibbits		thresholds[BM_POOL_DEP_THRESH_HW_ENTRY] = dep_hw_entry;
251296177Sjhibbits		thresholds[BM_POOL_DEP_THRESH_HW_EXIT] = dep_hw_exit;
252296177Sjhibbits		error = BM_POOL_ConfigDepletion(pool, f_Depletion, thresholds);
253296177Sjhibbits		if (error != E_OK)
254296177Sjhibbits			goto err;
255296177Sjhibbits	}
256296177Sjhibbits
257296177Sjhibbits	error = BM_POOL_Init(pool);
258296177Sjhibbits	if (error != E_OK)
259296177Sjhibbits		goto err;
260296177Sjhibbits
261296177Sjhibbits	*bpid = BM_POOL_GetId(pool);
262296177Sjhibbits	sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid);
263296177Sjhibbits
264296177Sjhibbits	sched_unpin();
265296177Sjhibbits
266296177Sjhibbits	return (pool);
267296177Sjhibbits
268296177Sjhibbitserr:
269296177Sjhibbits	if (pool != NULL)
270296177Sjhibbits		BM_POOL_Free(pool);
271296177Sjhibbits
272296177Sjhibbits	sched_unpin();
273296177Sjhibbits
274296177Sjhibbits	return (NULL);
275296177Sjhibbits}
276296177Sjhibbits
277296177Sjhibbitsint
278296177Sjhibbitsbman_pool_destroy(t_Handle pool)
279296177Sjhibbits{
280296177Sjhibbits	struct bman_softc *sc;
281296177Sjhibbits
282296177Sjhibbits	sc = bman_sc;
283296177Sjhibbits	thread_lock(curthread);
284296177Sjhibbits	sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]);
285296177Sjhibbits	thread_unlock(curthread);
286296177Sjhibbits
287296177Sjhibbits	BM_POOL_Free(pool);
288296177Sjhibbits
289296177Sjhibbits	thread_lock(curthread);
290296177Sjhibbits	sched_unbind(curthread);
291296177Sjhibbits	thread_unlock(curthread);
292296177Sjhibbits
293296177Sjhibbits	return (0);
294296177Sjhibbits}
295296177Sjhibbits
296296177Sjhibbitsint
297296177Sjhibbitsbman_pool_fill(t_Handle pool, uint16_t nbufs)
298296177Sjhibbits{
299296177Sjhibbits	struct bman_softc *sc;
300296177Sjhibbits	t_Handle portal;
301296177Sjhibbits	int error;
302296177Sjhibbits
303296177Sjhibbits	sc = bman_sc;
304296177Sjhibbits	sched_pin();
305296177Sjhibbits
306296177Sjhibbits	portal = bman_portal_setup(sc);
307296177Sjhibbits	if (portal == NULL) {
308296177Sjhibbits		sched_unpin();
309296177Sjhibbits		return (EIO);
310296177Sjhibbits	}
311296177Sjhibbits
312296177Sjhibbits	error = BM_POOL_FillBufs(pool, portal, nbufs);
313296177Sjhibbits
314296177Sjhibbits	sched_unpin();
315296177Sjhibbits
316296177Sjhibbits	return ((error == E_OK) ? 0 : EIO);
317296177Sjhibbits}
318296177Sjhibbits
319296177Sjhibbitsvoid *
320296177Sjhibbitsbman_get_buffer(t_Handle pool)
321296177Sjhibbits{
322296177Sjhibbits	struct bman_softc *sc;
323296177Sjhibbits	t_Handle portal;
324296177Sjhibbits	void *buffer;
325296177Sjhibbits
326296177Sjhibbits	sc = bman_sc;
327296177Sjhibbits	sched_pin();
328296177Sjhibbits
329296177Sjhibbits	portal = bman_portal_setup(sc);
330296177Sjhibbits	if (portal == NULL) {
331296177Sjhibbits		sched_unpin();
332296177Sjhibbits		return (NULL);
333296177Sjhibbits	}
334296177Sjhibbits
335296177Sjhibbits	buffer = BM_POOL_GetBuf(pool, portal);
336296177Sjhibbits
337296177Sjhibbits	sched_unpin();
338296177Sjhibbits
339296177Sjhibbits	return (buffer);
340296177Sjhibbits}
341296177Sjhibbits
342296177Sjhibbitsint
343296177Sjhibbitsbman_put_buffer(t_Handle pool, void *buffer)
344296177Sjhibbits{
345296177Sjhibbits	struct bman_softc *sc;
346296177Sjhibbits	t_Handle portal;
347296177Sjhibbits	int error;
348296177Sjhibbits
349296177Sjhibbits	sc = bman_sc;
350296177Sjhibbits	sched_pin();
351296177Sjhibbits
352296177Sjhibbits	portal = bman_portal_setup(sc);
353296177Sjhibbits	if (portal == NULL) {
354296177Sjhibbits		sched_unpin();
355296177Sjhibbits		return (EIO);
356296177Sjhibbits	}
357296177Sjhibbits
358296177Sjhibbits	error = BM_POOL_PutBuf(pool, portal, buffer);
359296177Sjhibbits
360296177Sjhibbits	sched_unpin();
361296177Sjhibbits
362296177Sjhibbits	return ((error == E_OK) ? 0 : EIO);
363296177Sjhibbits}
364296177Sjhibbits
365296177Sjhibbitsuint32_t
366296177Sjhibbitsbman_count(t_Handle pool)
367296177Sjhibbits{
368296177Sjhibbits
369296177Sjhibbits	return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT));
370296177Sjhibbits}
371