]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / cxgb / ulp / iw_cxgb / iw_cxgb_resource.c
1 /**************************************************************************
2
3 Copyright (c) 2007, Chelsio Inc.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11
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.
15
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.
27
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/bus.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
38 #include <sys/conf.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
42 #include <sys/rman.h>
43 #include <sys/ioccom.h>
44 #include <sys/mbuf.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>
51 #include <sys/smp.h>
52 #include <sys/sysctl.h>
53 #include <sys/syslog.h>
54 #include <sys/queue.h>
55 #include <sys/taskqueue.h>
56 #include <sys/proc.h>
57 #include <sys/queue.h>
58 #include <sys/libkern.h>
59
60 #include <netinet/in.h>
61
62 #include <contrib/rdma/ib_verbs.h>
63 #include <contrib/rdma/ib_umem.h>
64 #include <contrib/rdma/ib_user_verbs.h>
65
66 #include <cxgb_include.h>
67 #include <ulp/iw_cxgb/iw_cxgb_wr.h>
68 #include <ulp/iw_cxgb/iw_cxgb_hal.h>
69 #include <ulp/iw_cxgb/iw_cxgb_provider.h>
70 #include <ulp/iw_cxgb/iw_cxgb_cm.h>
71 #include <ulp/iw_cxgb/iw_cxgb.h>
72 #include <ulp/iw_cxgb/iw_cxgb_resource.h>
73 #include <ulp/iw_cxgb/iw_cxgb_user.h>
74
75 #ifdef needed
76 static struct buf_ring *rhdl_fifo;
77 static struct mtx rhdl_fifo_lock;
78 #endif
79
80 #define RANDOM_SIZE 16
81
82 static int __cxio_init_resource_fifo(struct buf_ring **fifo,
83                                    struct mtx *fifo_lock,
84                                    u32 nr, u32 skip_low,
85                                    u32 skip_high,
86                                    int randomize)
87 {
88         u32 i, j, idx;
89         u32 random_bytes;
90         u32 rarray[16];
91         mtx_init(fifo_lock, "cxio fifo", NULL, MTX_DEF|MTX_DUPOK);
92
93         *fifo = buf_ring_alloc(nr, M_DEVBUF, M_NOWAIT, fifo_lock);
94         if (*fifo == NULL)
95                 return (-ENOMEM);
96 #if 0
97         for (i = 0; i < skip_low + skip_high; i++) {
98                 u32 entry = 0;
99                 
100                 buf_ring_enqueue(*fifo, (uintptr_t) entry);
101         }
102 #endif  
103         if (randomize) {
104                 j = 0;
105                 random_bytes = random();
106                 for (i = 0; i < RANDOM_SIZE; i++)
107                         rarray[i] = i + skip_low;
108                 for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
109                         if (j >= RANDOM_SIZE) {
110                                 j = 0;
111                                 random_bytes = random();
112                         }
113                         idx = (random_bytes >> (j * 2)) & 0xF;
114                         buf_ring_enqueue(*fifo, (void *)(uintptr_t)rarray[idx]);
115                         rarray[idx] = i;
116                         j++;
117                 }
118                 for (i = 0; i < RANDOM_SIZE; i++)
119                         buf_ring_enqueue(*fifo, (void *) (uintptr_t)rarray[i]);
120         } else
121                 for (i = skip_low; i < nr - skip_high; i++)
122                         buf_ring_enqueue(*fifo, (void *) (uintptr_t)i);
123 #if 0
124         for (i = 0; i < skip_low + skip_high; i++)
125                 buf_ring_dequeue_sc(*fifo);
126 #endif  
127         return 0;
128 }
129
130 static int cxio_init_resource_fifo(struct buf_ring **fifo, struct mtx * fifo_lock,
131                                    u32 nr, u32 skip_low, u32 skip_high)
132 {
133         return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
134                                           skip_high, 0));
135 }
136
137 static int cxio_init_resource_fifo_random(struct buf_ring **fifo,
138                                   struct mtx * fifo_lock,
139                                    u32 nr, u32 skip_low, u32 skip_high)
140 {
141
142         return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
143                                           skip_high, 1));
144 }
145
146 static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p)
147 {
148         u32 i;
149
150         mtx_init(&rdev_p->rscp->qpid_fifo_lock, "qpid fifo", NULL, MTX_DEF);
151
152         rdev_p->rscp->qpid_fifo = buf_ring_alloc(T3_MAX_NUM_QP, M_DEVBUF,
153             M_NOWAIT, &rdev_p->rscp->qpid_fifo_lock);
154         if (rdev_p->rscp->qpid_fifo == NULL)
155                 return (-ENOMEM);
156
157         for (i = 16; i < T3_MAX_NUM_QP; i++)
158                 if (!(i & rdev_p->qpmask))
159                         buf_ring_enqueue(rdev_p->rscp->qpid_fifo, (void *) (uintptr_t)i);
160         return 0;
161 }
162
163 #ifdef needed
164 int cxio_hal_init_rhdl_resource(u32 nr_rhdl)
165 {
166         return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1,
167                                        0);
168 }
169
170 void cxio_hal_destroy_rhdl_resource(void)
171 {
172         buf_ring_free(rhdl_fifo, M_DEVBUF);
173 }
174 #endif
175
176 /* nr_* must be power of 2 */
177 int cxio_hal_init_resource(struct cxio_rdev *rdev_p,
178                            u32 nr_tpt, u32 nr_pbl,
179                            u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid)
180 {
181         int err = 0;
182         struct cxio_hal_resource *rscp;
183
184         rscp = malloc(sizeof(*rscp), M_DEVBUF, M_NOWAIT|M_ZERO);
185         if (!rscp)
186                 return (-ENOMEM);
187         rdev_p->rscp = rscp;
188         err = cxio_init_resource_fifo_random(&rscp->tpt_fifo,
189                                       &rscp->tpt_fifo_lock,
190                                       nr_tpt, 1, 0);
191         if (err)
192                 goto tpt_err;
193         err = cxio_init_qpid_fifo(rdev_p);
194         if (err)
195                 goto qpid_err;
196         err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock,
197                                       nr_cqid, 1, 0);
198         if (err)
199                 goto cqid_err;
200         err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock,
201                                       nr_pdid, 1, 0);
202         if (err)
203                 goto pdid_err;
204         return 0;
205 pdid_err:
206         buf_ring_free(rscp->cqid_fifo, M_DEVBUF);
207 cqid_err:
208         buf_ring_free(rscp->qpid_fifo, M_DEVBUF);
209 qpid_err:
210         buf_ring_free(rscp->tpt_fifo, M_DEVBUF);
211 tpt_err:
212         return (-ENOMEM);
213 }
214
215 /*
216  * returns 0 if no resource available
217  */
218 static u32 cxio_hal_get_resource(struct buf_ring *fifo, struct mtx *lock)
219 {
220         u32 entry;
221         
222         mtx_lock(lock);
223         entry = (u32)(uintptr_t)buf_ring_dequeue_sc(fifo);
224         mtx_unlock(lock);
225         return entry;
226 }
227
228 static void cxio_hal_put_resource(struct buf_ring *fifo, u32 entry, struct mtx *lock)
229 {
230         mtx_lock(lock);
231         buf_ring_enqueue(fifo, (void *) (uintptr_t)entry);
232         mtx_unlock(lock);
233 }
234
235 u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp)
236 {
237         return cxio_hal_get_resource(rscp->tpt_fifo, &rscp->tpt_fifo_lock);
238 }
239
240 void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
241 {
242         cxio_hal_put_resource(rscp->tpt_fifo, stag, &rscp->tpt_fifo_lock);
243 }
244
245 u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
246 {
247         u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo, &rscp->qpid_fifo_lock);
248         CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid);
249         return qpid;
250 }
251
252 void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
253 {
254         CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid);
255         cxio_hal_put_resource(rscp->qpid_fifo, qpid, &rscp->qpid_fifo_lock);
256 }
257
258 u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp)
259 {
260         return cxio_hal_get_resource(rscp->cqid_fifo, &rscp->cqid_fifo_lock);
261 }
262
263 void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid)
264 {
265         cxio_hal_put_resource(rscp->cqid_fifo, cqid, &rscp->cqid_fifo_lock);
266 }
267
268 u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp)
269 {
270         return cxio_hal_get_resource(rscp->pdid_fifo, &rscp->pdid_fifo_lock);
271 }
272
273 void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid)
274 {
275         cxio_hal_put_resource(rscp->pdid_fifo, pdid, &rscp->pdid_fifo_lock);
276 }
277
278 void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
279 {
280         buf_ring_free(rscp->tpt_fifo, M_DEVBUF);
281         buf_ring_free(rscp->cqid_fifo, M_DEVBUF);
282         buf_ring_free(rscp->qpid_fifo, M_DEVBUF);
283         buf_ring_free(rscp->pdid_fifo, M_DEVBUF);
284         free(rscp, M_DEVBUF);
285 }
286
287 /*
288  * PBL Memory Manager.  Uses Linux generic allocator.
289  */
290
291 #define MIN_PBL_SHIFT 8                 /* 256B == min PBL size (32 entries) */
292 #define PBL_CHUNK 2*1024*1024
293
294 u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size)
295 {
296         unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);
297         CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size);
298         return (u32)addr;
299 }
300
301 void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
302 {
303         CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size);
304         gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);
305 }
306
307 int cxio_hal_pblpool_create(struct cxio_rdev *rdev_p)
308 {
309
310         rdev_p->pbl_pool = gen_pool_create(rdev_p->rnic_info.pbl_base, MIN_PBL_SHIFT,
311             rdev_p->rnic_info.pbl_top - rdev_p->rnic_info.pbl_base);
312 #if 0   
313         if (rdev_p->pbl_pool) {
314                 
315                 unsigned long i;
316                 for (i = rdev_p->rnic_info.pbl_base;
317                      i <= rdev_p->rnic_info.pbl_top - PBL_CHUNK + 1;
318                      i += PBL_CHUNK)
319                         gen_pool_add(rdev_p->pbl_pool, i, PBL_CHUNK, -1);
320         }
321 #endif  
322         return rdev_p->pbl_pool ? 0 : (-ENOMEM);
323 }
324
325 void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p)
326 {
327         gen_pool_destroy(rdev_p->pbl_pool);
328 }
329
330 /*
331  * RQT Memory Manager.  Uses Linux generic allocator.
332  */
333
334 #define MIN_RQT_SHIFT 10        /* 1KB == mini RQT size (16 entries) */
335 #define RQT_CHUNK 2*1024*1024
336
337 u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size)
338 {
339         unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);
340         CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size << 6);
341         return (u32)addr;
342 }
343
344 void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
345 {
346         CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size << 6);
347         gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);
348 }
349
350 int cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p)
351 {
352         
353         rdev_p->rqt_pool = gen_pool_create(rdev_p->rnic_info.rqt_base,
354             MIN_RQT_SHIFT, rdev_p->rnic_info.rqt_top - rdev_p->rnic_info.rqt_base);
355 #if 0
356         if (rdev_p->rqt_pool) {
357                 unsigned long i;
358
359                 for (i = rdev_p->rnic_info.rqt_base;
360                      i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1;
361                      i += RQT_CHUNK)
362                         gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1);
363         }
364 #endif  
365         return rdev_p->rqt_pool ? 0 : (-ENOMEM);
366 }
367
368 void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p)
369 {
370         gen_pool_destroy(rdev_p->rqt_pool);
371 }