1 /**************************************************************************
3 Copyright (c) 2007, Chelsio Inc.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Neither the name of the Chelsio Corporation nor the names of its
13 contributors may be used to endorse or promote products derived from
14 this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
43 #include <sys/ioccom.h>
45 #include <sys/mutex.h>
46 #include <sys/rwlock.h>
47 #include <sys/linker.h>
48 #include <sys/firmware.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
52 #include <sys/sysctl.h>
53 #include <sys/syslog.h>
54 #include <sys/queue.h>
55 #include <sys/taskqueue.h>
57 #include <sys/queue.h>
58 #include <sys/libkern.h>
60 #include <netinet/in.h>
62 #include <contrib/rdma/ib_verbs.h>
63 #include <contrib/rdma/ib_umem.h>
64 #include <contrib/rdma/ib_user_verbs.h>
68 #include <cxgb_include.h>
69 #include <ulp/iw_cxgb/iw_cxgb_wr.h>
70 #include <ulp/iw_cxgb/iw_cxgb_hal.h>
71 #include <ulp/iw_cxgb/iw_cxgb_provider.h>
72 #include <ulp/iw_cxgb/iw_cxgb_cm.h>
73 #include <ulp/iw_cxgb/iw_cxgb.h>
74 #include <ulp/iw_cxgb/iw_cxgb_resource.h>
75 #include <ulp/iw_cxgb/iw_cxgb_user.h>
77 #include <dev/cxgb/cxgb_include.h>
78 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_wr.h>
79 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_hal.h>
80 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_provider.h>
81 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.h>
82 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb.h>
83 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.h>
84 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_user.h>
88 static struct buf_ring *rhdl_fifo;
89 static struct mtx rhdl_fifo_lock;
92 #define RANDOM_SIZE 16
94 static int __cxio_init_resource_fifo(struct buf_ring **fifo,
95 struct mtx *fifo_lock,
103 mtx_init(fifo_lock, "cxio fifo", NULL, MTX_DEF|MTX_DUPOK);
105 *fifo = buf_ring_alloc(nr, M_NOWAIT);
109 for (i = 0; i < skip_low + skip_high; i++) {
112 buf_ring_enqueue(*fifo, (uintptr_t) entry);
117 random_bytes = random();
118 for (i = 0; i < RANDOM_SIZE; i++)
119 rarray[i] = i + skip_low;
120 for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
121 if (j >= RANDOM_SIZE) {
123 random_bytes = random();
125 idx = (random_bytes >> (j * 2)) & 0xF;
126 buf_ring_enqueue(*fifo, (void *)(uintptr_t)rarray[idx]);
130 for (i = 0; i < RANDOM_SIZE; i++)
131 buf_ring_enqueue(*fifo, (void *) (uintptr_t)rarray[i]);
133 for (i = skip_low; i < nr - skip_high; i++)
134 buf_ring_enqueue(*fifo, (void *) (uintptr_t)i);
136 for (i = 0; i < skip_low + skip_high; i++)
137 buf_ring_dequeue(*fifo);
142 static int cxio_init_resource_fifo(struct buf_ring **fifo, struct mtx * fifo_lock,
143 u32 nr, u32 skip_low, u32 skip_high)
145 return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
149 static int cxio_init_resource_fifo_random(struct buf_ring **fifo,
150 struct mtx * fifo_lock,
151 u32 nr, u32 skip_low, u32 skip_high)
154 return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
158 static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p)
162 mtx_init(&rdev_p->rscp->qpid_fifo_lock, "qpid fifo", NULL, MTX_DEF);
164 rdev_p->rscp->qpid_fifo = buf_ring_alloc(T3_MAX_NUM_QP, M_NOWAIT);
165 if (rdev_p->rscp->qpid_fifo == NULL)
168 for (i = 16; i < T3_MAX_NUM_QP; i++)
169 if (!(i & rdev_p->qpmask))
170 buf_ring_enqueue(rdev_p->rscp->qpid_fifo, (void *) (uintptr_t)i);
175 int cxio_hal_init_rhdl_resource(u32 nr_rhdl)
177 return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1,
181 void cxio_hal_destroy_rhdl_resource(void)
183 buf_ring_free(rhdl_fifo);
187 /* nr_* must be power of 2 */
188 int cxio_hal_init_resource(struct cxio_rdev *rdev_p,
189 u32 nr_tpt, u32 nr_pbl,
190 u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid)
193 struct cxio_hal_resource *rscp;
195 rscp = malloc(sizeof(*rscp), M_DEVBUF, M_NOWAIT|M_ZERO);
199 err = cxio_init_resource_fifo_random(&rscp->tpt_fifo,
200 &rscp->tpt_fifo_lock,
204 err = cxio_init_qpid_fifo(rdev_p);
207 err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock,
211 err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock,
217 buf_ring_free(rscp->cqid_fifo);
219 buf_ring_free(rscp->qpid_fifo);
221 buf_ring_free(rscp->tpt_fifo);
227 * returns 0 if no resource available
229 static u32 cxio_hal_get_resource(struct buf_ring *fifo, struct mtx *lock)
234 entry = (u32)(uintptr_t)buf_ring_dequeue(fifo);
239 static void cxio_hal_put_resource(struct buf_ring *fifo, u32 entry, struct mtx *lock)
242 buf_ring_enqueue(fifo, (void *) (uintptr_t)entry);
246 u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp)
248 return cxio_hal_get_resource(rscp->tpt_fifo, &rscp->tpt_fifo_lock);
251 void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
253 cxio_hal_put_resource(rscp->tpt_fifo, stag, &rscp->tpt_fifo_lock);
256 u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
258 u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo, &rscp->qpid_fifo_lock);
259 CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid);
263 void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
265 CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid);
266 cxio_hal_put_resource(rscp->qpid_fifo, qpid, &rscp->qpid_fifo_lock);
269 u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp)
271 return cxio_hal_get_resource(rscp->cqid_fifo, &rscp->cqid_fifo_lock);
274 void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid)
276 cxio_hal_put_resource(rscp->cqid_fifo, cqid, &rscp->cqid_fifo_lock);
279 u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp)
281 return cxio_hal_get_resource(rscp->pdid_fifo, &rscp->pdid_fifo_lock);
284 void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid)
286 cxio_hal_put_resource(rscp->pdid_fifo, pdid, &rscp->pdid_fifo_lock);
289 void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
291 buf_ring_free(rscp->tpt_fifo);
292 buf_ring_free(rscp->cqid_fifo);
293 buf_ring_free(rscp->qpid_fifo);
294 buf_ring_free(rscp->pdid_fifo);
295 free(rscp, M_DEVBUF);
299 * PBL Memory Manager. Uses Linux generic allocator.
302 #define MIN_PBL_SHIFT 8 /* 256B == min PBL size (32 entries) */
303 #define PBL_CHUNK 2*1024*1024
305 u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size)
307 unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);
308 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size);
312 void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
314 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size);
315 gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);
318 int cxio_hal_pblpool_create(struct cxio_rdev *rdev_p)
321 rdev_p->pbl_pool = gen_pool_create(rdev_p->rnic_info.pbl_base, MIN_PBL_SHIFT,
322 rdev_p->rnic_info.pbl_top - rdev_p->rnic_info.pbl_base);
324 if (rdev_p->pbl_pool) {
327 for (i = rdev_p->rnic_info.pbl_base;
328 i <= rdev_p->rnic_info.pbl_top - PBL_CHUNK + 1;
330 gen_pool_add(rdev_p->pbl_pool, i, PBL_CHUNK, -1);
333 return rdev_p->pbl_pool ? 0 : (-ENOMEM);
336 void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p)
338 gen_pool_destroy(rdev_p->pbl_pool);
342 * RQT Memory Manager. Uses Linux generic allocator.
345 #define MIN_RQT_SHIFT 10 /* 1KB == mini RQT size (16 entries) */
346 #define RQT_CHUNK 2*1024*1024
348 u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size)
350 unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);
351 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size << 6);
355 void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
357 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size << 6);
358 gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);
361 int cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p)
364 rdev_p->rqt_pool = gen_pool_create(rdev_p->rnic_info.rqt_base,
365 MIN_RQT_SHIFT, rdev_p->rnic_info.rqt_top - rdev_p->rnic_info.rqt_base);
367 if (rdev_p->rqt_pool) {
370 for (i = rdev_p->rnic_info.rqt_base;
371 i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1;
373 gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1);
376 return rdev_p->rqt_pool ? 0 : (-ENOMEM);
379 void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p)
381 gen_pool_destroy(rdev_p->rqt_pool);