iw_cxgb_resource.c revision 178786
1178786Skmacy/**************************************************************************
2178786Skmacy
3178786SkmacyCopyright (c) 2007, Chelsio Inc.
4178786SkmacyAll rights reserved.
5178786Skmacy
6178786SkmacyRedistribution and use in source and binary forms, with or without
7178786Skmacymodification, are permitted provided that the following conditions are met:
8178786Skmacy
9178786Skmacy 1. Redistributions of source code must retain the above copyright notice,
10178786Skmacy    this list of conditions and the following disclaimer.
11178786Skmacy
12178786Skmacy 2. Neither the name of the Chelsio Corporation nor the names of its
13178786Skmacy    contributors may be used to endorse or promote products derived from
14178786Skmacy    this software without specific prior written permission.
15178786Skmacy
16178786SkmacyTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17178786SkmacyAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18178786SkmacyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19178786SkmacyARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20178786SkmacyLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21178786SkmacyCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22178786SkmacySUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23178786SkmacyINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24178786SkmacyCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25178786SkmacyARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26178786SkmacyPOSSIBILITY OF SUCH DAMAGE.
27178786Skmacy
28178786Skmacy***************************************************************************/
29178786Skmacy#include <sys/cdefs.h>
30178786Skmacy__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.c 178786 2008-05-05 18:46:18Z kmacy $");
31178786Skmacy
32178786Skmacy#include <sys/param.h>
33178786Skmacy#include <sys/systm.h>
34178786Skmacy#include <sys/kernel.h>
35178786Skmacy#include <sys/bus.h>
36178786Skmacy#include <sys/module.h>
37178786Skmacy#include <sys/pciio.h>
38178786Skmacy#include <sys/conf.h>
39178786Skmacy#include <machine/bus.h>
40178786Skmacy#include <machine/resource.h>
41178786Skmacy#include <sys/bus_dma.h>
42178786Skmacy#include <sys/rman.h>
43178786Skmacy#include <sys/ioccom.h>
44178786Skmacy#include <sys/mbuf.h>
45178786Skmacy#include <sys/mutex.h>
46178786Skmacy#include <sys/rwlock.h>
47178786Skmacy#include <sys/linker.h>
48178786Skmacy#include <sys/firmware.h>
49178786Skmacy#include <sys/socket.h>
50178786Skmacy#include <sys/sockio.h>
51178786Skmacy#include <sys/smp.h>
52178786Skmacy#include <sys/sysctl.h>
53178786Skmacy#include <sys/syslog.h>
54178786Skmacy#include <sys/queue.h>
55178786Skmacy#include <sys/taskqueue.h>
56178786Skmacy#include <sys/proc.h>
57178786Skmacy#include <sys/queue.h>
58178786Skmacy#include <sys/libkern.h>
59178786Skmacy
60178786Skmacy#include <netinet/in.h>
61178786Skmacy
62178786Skmacy#include <contrib/rdma/ib_verbs.h>
63178786Skmacy#include <contrib/rdma/ib_umem.h>
64178786Skmacy#include <contrib/rdma/ib_user_verbs.h>
65178786Skmacy
66178786Skmacy
67178786Skmacy#ifdef CONFIG_DEFINED
68178786Skmacy#include <cxgb_include.h>
69178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_wr.h>
70178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_hal.h>
71178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_provider.h>
72178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_cm.h>
73178786Skmacy#include <ulp/iw_cxgb/iw_cxgb.h>
74178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_resource.h>
75178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_user.h>
76178786Skmacy#else
77178786Skmacy#include <dev/cxgb/cxgb_include.h>
78178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_wr.h>
79178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_hal.h>
80178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_provider.h>
81178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.h>
82178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb.h>
83178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.h>
84178786Skmacy#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_user.h>
85178786Skmacy#endif
86178786Skmacy
87178786Skmacy#ifdef needed
88178786Skmacystatic struct buf_ring *rhdl_fifo;
89178786Skmacystatic struct mtx rhdl_fifo_lock;
90178786Skmacy#endif
91178786Skmacy
92178786Skmacy#define RANDOM_SIZE 16
93178786Skmacy
94178786Skmacystatic int __cxio_init_resource_fifo(struct buf_ring **fifo,
95178786Skmacy				   struct mtx *fifo_lock,
96178786Skmacy				   u32 nr, u32 skip_low,
97178786Skmacy				   u32 skip_high,
98178786Skmacy				   int randomize)
99178786Skmacy{
100178786Skmacy	u32 i, j, idx;
101178786Skmacy	u32 random_bytes;
102178786Skmacy	u32 rarray[16];
103178786Skmacy	mtx_init(fifo_lock, "cxio fifo", NULL, MTX_DEF|MTX_DUPOK);
104178786Skmacy
105178786Skmacy	*fifo = buf_ring_alloc(nr, M_NOWAIT);
106178786Skmacy	if (*fifo == NULL)
107178786Skmacy		return (-ENOMEM);
108178786Skmacy#if 0
109178786Skmacy	for (i = 0; i < skip_low + skip_high; i++) {
110178786Skmacy		u32 entry = 0;
111178786Skmacy
112178786Skmacy		buf_ring_enqueue(*fifo, (uintptr_t) entry);
113178786Skmacy	}
114178786Skmacy#endif
115178786Skmacy	if (randomize) {
116178786Skmacy		j = 0;
117178786Skmacy		random_bytes = random();
118178786Skmacy		for (i = 0; i < RANDOM_SIZE; i++)
119178786Skmacy			rarray[i] = i + skip_low;
120178786Skmacy		for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
121178786Skmacy			if (j >= RANDOM_SIZE) {
122178786Skmacy				j = 0;
123178786Skmacy				random_bytes = random();
124178786Skmacy			}
125178786Skmacy			idx = (random_bytes >> (j * 2)) & 0xF;
126178786Skmacy			buf_ring_enqueue(*fifo, (void *)(uintptr_t)rarray[idx]);
127178786Skmacy			rarray[idx] = i;
128178786Skmacy			j++;
129178786Skmacy		}
130178786Skmacy		for (i = 0; i < RANDOM_SIZE; i++)
131178786Skmacy			buf_ring_enqueue(*fifo, (void *) (uintptr_t)rarray[i]);
132178786Skmacy	} else
133178786Skmacy		for (i = skip_low; i < nr - skip_high; i++)
134178786Skmacy			buf_ring_enqueue(*fifo, (void *) (uintptr_t)i);
135178786Skmacy#if 0
136178786Skmacy	for (i = 0; i < skip_low + skip_high; i++)
137178786Skmacy		buf_ring_dequeue(*fifo);
138178786Skmacy#endif
139178786Skmacy	return 0;
140178786Skmacy}
141178786Skmacy
142178786Skmacystatic int cxio_init_resource_fifo(struct buf_ring **fifo, struct mtx * fifo_lock,
143178786Skmacy				   u32 nr, u32 skip_low, u32 skip_high)
144178786Skmacy{
145178786Skmacy	return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
146178786Skmacy					  skip_high, 0));
147178786Skmacy}
148178786Skmacy
149178786Skmacystatic int cxio_init_resource_fifo_random(struct buf_ring **fifo,
150178786Skmacy				  struct mtx * fifo_lock,
151178786Skmacy				   u32 nr, u32 skip_low, u32 skip_high)
152178786Skmacy{
153178786Skmacy
154178786Skmacy	return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
155178786Skmacy					  skip_high, 1));
156178786Skmacy}
157178786Skmacy
158178786Skmacystatic int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p)
159178786Skmacy{
160178786Skmacy	u32 i;
161178786Skmacy
162178786Skmacy	mtx_init(&rdev_p->rscp->qpid_fifo_lock, "qpid fifo", NULL, MTX_DEF);
163178786Skmacy
164178786Skmacy	rdev_p->rscp->qpid_fifo = buf_ring_alloc(T3_MAX_NUM_QP, M_NOWAIT);
165178786Skmacy	if (rdev_p->rscp->qpid_fifo == NULL)
166178786Skmacy		return (-ENOMEM);
167178786Skmacy
168178786Skmacy	for (i = 16; i < T3_MAX_NUM_QP; i++)
169178786Skmacy		if (!(i & rdev_p->qpmask))
170178786Skmacy			buf_ring_enqueue(rdev_p->rscp->qpid_fifo, (void *) (uintptr_t)i);
171178786Skmacy	return 0;
172178786Skmacy}
173178786Skmacy
174178786Skmacy#ifdef needed
175178786Skmacyint cxio_hal_init_rhdl_resource(u32 nr_rhdl)
176178786Skmacy{
177178786Skmacy	return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1,
178178786Skmacy				       0);
179178786Skmacy}
180178786Skmacy
181178786Skmacyvoid cxio_hal_destroy_rhdl_resource(void)
182178786Skmacy{
183178786Skmacy	buf_ring_free(rhdl_fifo);
184178786Skmacy}
185178786Skmacy#endif
186178786Skmacy
187178786Skmacy/* nr_* must be power of 2 */
188178786Skmacyint cxio_hal_init_resource(struct cxio_rdev *rdev_p,
189178786Skmacy			   u32 nr_tpt, u32 nr_pbl,
190178786Skmacy			   u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid)
191178786Skmacy{
192178786Skmacy	int err = 0;
193178786Skmacy	struct cxio_hal_resource *rscp;
194178786Skmacy
195178786Skmacy	rscp = malloc(sizeof(*rscp), M_DEVBUF, M_NOWAIT|M_ZERO);
196178786Skmacy	if (!rscp)
197178786Skmacy		return (-ENOMEM);
198178786Skmacy	rdev_p->rscp = rscp;
199178786Skmacy	err = cxio_init_resource_fifo_random(&rscp->tpt_fifo,
200178786Skmacy				      &rscp->tpt_fifo_lock,
201178786Skmacy				      nr_tpt, 1, 0);
202178786Skmacy	if (err)
203178786Skmacy		goto tpt_err;
204178786Skmacy	err = cxio_init_qpid_fifo(rdev_p);
205178786Skmacy	if (err)
206178786Skmacy		goto qpid_err;
207178786Skmacy	err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock,
208178786Skmacy				      nr_cqid, 1, 0);
209178786Skmacy	if (err)
210178786Skmacy		goto cqid_err;
211178786Skmacy	err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock,
212178786Skmacy				      nr_pdid, 1, 0);
213178786Skmacy	if (err)
214178786Skmacy		goto pdid_err;
215178786Skmacy	return 0;
216178786Skmacypdid_err:
217178786Skmacy	buf_ring_free(rscp->cqid_fifo);
218178786Skmacycqid_err:
219178786Skmacy	buf_ring_free(rscp->qpid_fifo);
220178786Skmacyqpid_err:
221178786Skmacy	buf_ring_free(rscp->tpt_fifo);
222178786Skmacytpt_err:
223178786Skmacy	return (-ENOMEM);
224178786Skmacy}
225178786Skmacy
226178786Skmacy/*
227178786Skmacy * returns 0 if no resource available
228178786Skmacy */
229178786Skmacystatic u32 cxio_hal_get_resource(struct buf_ring *fifo, struct mtx *lock)
230178786Skmacy{
231178786Skmacy	u32 entry;
232178786Skmacy
233178786Skmacy	mtx_lock(lock);
234178786Skmacy	entry = (u32)(uintptr_t)buf_ring_dequeue(fifo);
235178786Skmacy	mtx_unlock(lock);
236178786Skmacy	return entry;
237178786Skmacy}
238178786Skmacy
239178786Skmacystatic void cxio_hal_put_resource(struct buf_ring *fifo, u32 entry, struct mtx *lock)
240178786Skmacy{
241178786Skmacy	mtx_lock(lock);
242178786Skmacy	buf_ring_enqueue(fifo, (void *) (uintptr_t)entry);
243178786Skmacy	mtx_unlock(lock);
244178786Skmacy}
245178786Skmacy
246178786Skmacyu32 cxio_hal_get_stag(struct cxio_hal_resource *rscp)
247178786Skmacy{
248178786Skmacy	return cxio_hal_get_resource(rscp->tpt_fifo, &rscp->tpt_fifo_lock);
249178786Skmacy}
250178786Skmacy
251178786Skmacyvoid cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
252178786Skmacy{
253178786Skmacy	cxio_hal_put_resource(rscp->tpt_fifo, stag, &rscp->tpt_fifo_lock);
254178786Skmacy}
255178786Skmacy
256178786Skmacyu32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
257178786Skmacy{
258178786Skmacy	u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo, &rscp->qpid_fifo_lock);
259178786Skmacy	CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid);
260178786Skmacy	return qpid;
261178786Skmacy}
262178786Skmacy
263178786Skmacyvoid cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
264178786Skmacy{
265178786Skmacy	CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid);
266178786Skmacy	cxio_hal_put_resource(rscp->qpid_fifo, qpid, &rscp->qpid_fifo_lock);
267178786Skmacy}
268178786Skmacy
269178786Skmacyu32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp)
270178786Skmacy{
271178786Skmacy	return cxio_hal_get_resource(rscp->cqid_fifo, &rscp->cqid_fifo_lock);
272178786Skmacy}
273178786Skmacy
274178786Skmacyvoid cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid)
275178786Skmacy{
276178786Skmacy	cxio_hal_put_resource(rscp->cqid_fifo, cqid, &rscp->cqid_fifo_lock);
277178786Skmacy}
278178786Skmacy
279178786Skmacyu32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp)
280178786Skmacy{
281178786Skmacy	return cxio_hal_get_resource(rscp->pdid_fifo, &rscp->pdid_fifo_lock);
282178786Skmacy}
283178786Skmacy
284178786Skmacyvoid cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid)
285178786Skmacy{
286178786Skmacy	cxio_hal_put_resource(rscp->pdid_fifo, pdid, &rscp->pdid_fifo_lock);
287178786Skmacy}
288178786Skmacy
289178786Skmacyvoid cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
290178786Skmacy{
291178786Skmacy	buf_ring_free(rscp->tpt_fifo);
292178786Skmacy	buf_ring_free(rscp->cqid_fifo);
293178786Skmacy	buf_ring_free(rscp->qpid_fifo);
294178786Skmacy	buf_ring_free(rscp->pdid_fifo);
295178786Skmacy	free(rscp, M_DEVBUF);
296178786Skmacy}
297178786Skmacy
298178786Skmacy/*
299178786Skmacy * PBL Memory Manager.  Uses Linux generic allocator.
300178786Skmacy */
301178786Skmacy
302178786Skmacy#define MIN_PBL_SHIFT 8			/* 256B == min PBL size (32 entries) */
303178786Skmacy#define PBL_CHUNK 2*1024*1024
304178786Skmacy
305178786Skmacyu32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size)
306178786Skmacy{
307178786Skmacy	unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);
308178786Skmacy	CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size);
309178786Skmacy	return (u32)addr;
310178786Skmacy}
311178786Skmacy
312178786Skmacyvoid cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
313178786Skmacy{
314178786Skmacy	CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size);
315178786Skmacy	gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);
316178786Skmacy}
317178786Skmacy
318178786Skmacyint cxio_hal_pblpool_create(struct cxio_rdev *rdev_p)
319178786Skmacy{
320178786Skmacy
321178786Skmacy	rdev_p->pbl_pool = gen_pool_create(rdev_p->rnic_info.pbl_base, MIN_PBL_SHIFT,
322178786Skmacy	    rdev_p->rnic_info.pbl_top - rdev_p->rnic_info.pbl_base);
323178786Skmacy#if 0
324178786Skmacy	if (rdev_p->pbl_pool) {
325178786Skmacy
326178786Skmacy		unsigned long i;
327178786Skmacy		for (i = rdev_p->rnic_info.pbl_base;
328178786Skmacy		     i <= rdev_p->rnic_info.pbl_top - PBL_CHUNK + 1;
329178786Skmacy		     i += PBL_CHUNK)
330178786Skmacy			gen_pool_add(rdev_p->pbl_pool, i, PBL_CHUNK, -1);
331178786Skmacy	}
332178786Skmacy#endif
333178786Skmacy	return rdev_p->pbl_pool ? 0 : (-ENOMEM);
334178786Skmacy}
335178786Skmacy
336178786Skmacyvoid cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p)
337178786Skmacy{
338178786Skmacy	gen_pool_destroy(rdev_p->pbl_pool);
339178786Skmacy}
340178786Skmacy
341178786Skmacy/*
342178786Skmacy * RQT Memory Manager.  Uses Linux generic allocator.
343178786Skmacy */
344178786Skmacy
345178786Skmacy#define MIN_RQT_SHIFT 10	/* 1KB == mini RQT size (16 entries) */
346178786Skmacy#define RQT_CHUNK 2*1024*1024
347178786Skmacy
348178786Skmacyu32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size)
349178786Skmacy{
350178786Skmacy	unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);
351178786Skmacy	CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size << 6);
352178786Skmacy	return (u32)addr;
353178786Skmacy}
354178786Skmacy
355178786Skmacyvoid cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
356178786Skmacy{
357178786Skmacy	CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size << 6);
358178786Skmacy	gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);
359178786Skmacy}
360178786Skmacy
361178786Skmacyint cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p)
362178786Skmacy{
363178786Skmacy
364178786Skmacy	rdev_p->rqt_pool = gen_pool_create(rdev_p->rnic_info.rqt_base,
365178786Skmacy	    MIN_RQT_SHIFT, rdev_p->rnic_info.rqt_top - rdev_p->rnic_info.rqt_base);
366178786Skmacy#if 0
367178786Skmacy	if (rdev_p->rqt_pool) {
368178786Skmacy		unsigned long i;
369178786Skmacy
370178786Skmacy		for (i = rdev_p->rnic_info.rqt_base;
371178786Skmacy		     i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1;
372178786Skmacy		     i += RQT_CHUNK)
373178786Skmacy			gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1);
374178786Skmacy	}
375178786Skmacy#endif
376178786Skmacy	return rdev_p->rqt_pool ? 0 : (-ENOMEM);
377178786Skmacy}
378178786Skmacy
379178786Skmacyvoid cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p)
380178786Skmacy{
381178786Skmacy	gen_pool_destroy(rdev_p->rqt_pool);
382178786Skmacy}
383