iw_cxgb_resource.c revision 183292
1/************************************************************************** 2 3Copyright (c) 2007, Chelsio Inc. 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, 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 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26POSSIBILITY OF SUCH DAMAGE. 27 28***************************************************************************/ 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.c 183292 2008-09-23 03:16:54Z kmacy $"); 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 76static struct buf_ring *rhdl_fifo; 77static struct mtx rhdl_fifo_lock; 78#endif 79 80#define RANDOM_SIZE 16 81 82static 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_NOWAIT); 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(*fifo); 126#endif 127 return 0; 128} 129 130static 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 137static 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 146static 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_NOWAIT); 153 if (rdev_p->rscp->qpid_fifo == NULL) 154 return (-ENOMEM); 155 156 for (i = 16; i < T3_MAX_NUM_QP; i++) 157 if (!(i & rdev_p->qpmask)) 158 buf_ring_enqueue(rdev_p->rscp->qpid_fifo, (void *) (uintptr_t)i); 159 return 0; 160} 161 162#ifdef needed 163int cxio_hal_init_rhdl_resource(u32 nr_rhdl) 164{ 165 return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1, 166 0); 167} 168 169void cxio_hal_destroy_rhdl_resource(void) 170{ 171 buf_ring_free(rhdl_fifo); 172} 173#endif 174 175/* nr_* must be power of 2 */ 176int cxio_hal_init_resource(struct cxio_rdev *rdev_p, 177 u32 nr_tpt, u32 nr_pbl, 178 u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid) 179{ 180 int err = 0; 181 struct cxio_hal_resource *rscp; 182 183 rscp = malloc(sizeof(*rscp), M_DEVBUF, M_NOWAIT|M_ZERO); 184 if (!rscp) 185 return (-ENOMEM); 186 rdev_p->rscp = rscp; 187 err = cxio_init_resource_fifo_random(&rscp->tpt_fifo, 188 &rscp->tpt_fifo_lock, 189 nr_tpt, 1, 0); 190 if (err) 191 goto tpt_err; 192 err = cxio_init_qpid_fifo(rdev_p); 193 if (err) 194 goto qpid_err; 195 err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock, 196 nr_cqid, 1, 0); 197 if (err) 198 goto cqid_err; 199 err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock, 200 nr_pdid, 1, 0); 201 if (err) 202 goto pdid_err; 203 return 0; 204pdid_err: 205 buf_ring_free(rscp->cqid_fifo); 206cqid_err: 207 buf_ring_free(rscp->qpid_fifo); 208qpid_err: 209 buf_ring_free(rscp->tpt_fifo); 210tpt_err: 211 return (-ENOMEM); 212} 213 214/* 215 * returns 0 if no resource available 216 */ 217static u32 cxio_hal_get_resource(struct buf_ring *fifo, struct mtx *lock) 218{ 219 u32 entry; 220 221 mtx_lock(lock); 222 entry = (u32)(uintptr_t)buf_ring_dequeue(fifo); 223 mtx_unlock(lock); 224 return entry; 225} 226 227static void cxio_hal_put_resource(struct buf_ring *fifo, u32 entry, struct mtx *lock) 228{ 229 mtx_lock(lock); 230 buf_ring_enqueue(fifo, (void *) (uintptr_t)entry); 231 mtx_unlock(lock); 232} 233 234u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) 235{ 236 return cxio_hal_get_resource(rscp->tpt_fifo, &rscp->tpt_fifo_lock); 237} 238 239void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) 240{ 241 cxio_hal_put_resource(rscp->tpt_fifo, stag, &rscp->tpt_fifo_lock); 242} 243 244u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) 245{ 246 u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo, &rscp->qpid_fifo_lock); 247 CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid); 248 return qpid; 249} 250 251void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) 252{ 253 CTR2(KTR_IW_CXGB, "%s qpid 0x%x", __FUNCTION__, qpid); 254 cxio_hal_put_resource(rscp->qpid_fifo, qpid, &rscp->qpid_fifo_lock); 255} 256 257u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) 258{ 259 return cxio_hal_get_resource(rscp->cqid_fifo, &rscp->cqid_fifo_lock); 260} 261 262void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) 263{ 264 cxio_hal_put_resource(rscp->cqid_fifo, cqid, &rscp->cqid_fifo_lock); 265} 266 267u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) 268{ 269 return cxio_hal_get_resource(rscp->pdid_fifo, &rscp->pdid_fifo_lock); 270} 271 272void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) 273{ 274 cxio_hal_put_resource(rscp->pdid_fifo, pdid, &rscp->pdid_fifo_lock); 275} 276 277void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) 278{ 279 buf_ring_free(rscp->tpt_fifo); 280 buf_ring_free(rscp->cqid_fifo); 281 buf_ring_free(rscp->qpid_fifo); 282 buf_ring_free(rscp->pdid_fifo); 283 free(rscp, M_DEVBUF); 284} 285 286/* 287 * PBL Memory Manager. Uses Linux generic allocator. 288 */ 289 290#define MIN_PBL_SHIFT 8 /* 256B == min PBL size (32 entries) */ 291#define PBL_CHUNK 2*1024*1024 292 293u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size) 294{ 295 unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size); 296 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size); 297 return (u32)addr; 298} 299 300void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size) 301{ 302 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size); 303 gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size); 304} 305 306int cxio_hal_pblpool_create(struct cxio_rdev *rdev_p) 307{ 308 309 rdev_p->pbl_pool = gen_pool_create(rdev_p->rnic_info.pbl_base, MIN_PBL_SHIFT, 310 rdev_p->rnic_info.pbl_top - rdev_p->rnic_info.pbl_base); 311#if 0 312 if (rdev_p->pbl_pool) { 313 314 unsigned long i; 315 for (i = rdev_p->rnic_info.pbl_base; 316 i <= rdev_p->rnic_info.pbl_top - PBL_CHUNK + 1; 317 i += PBL_CHUNK) 318 gen_pool_add(rdev_p->pbl_pool, i, PBL_CHUNK, -1); 319 } 320#endif 321 return rdev_p->pbl_pool ? 0 : (-ENOMEM); 322} 323 324void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p) 325{ 326 gen_pool_destroy(rdev_p->pbl_pool); 327} 328 329/* 330 * RQT Memory Manager. Uses Linux generic allocator. 331 */ 332 333#define MIN_RQT_SHIFT 10 /* 1KB == mini RQT size (16 entries) */ 334#define RQT_CHUNK 2*1024*1024 335 336u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size) 337{ 338 unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6); 339 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, (u32)addr, size << 6); 340 return (u32)addr; 341} 342 343void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size) 344{ 345 CTR3(KTR_IW_CXGB, "%s addr 0x%x size %d", __FUNCTION__, addr, size << 6); 346 gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6); 347} 348 349int cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p) 350{ 351 352 rdev_p->rqt_pool = gen_pool_create(rdev_p->rnic_info.rqt_base, 353 MIN_RQT_SHIFT, rdev_p->rnic_info.rqt_top - rdev_p->rnic_info.rqt_base); 354#if 0 355 if (rdev_p->rqt_pool) { 356 unsigned long i; 357 358 for (i = rdev_p->rnic_info.rqt_base; 359 i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1; 360 i += RQT_CHUNK) 361 gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1); 362 } 363#endif 364 return rdev_p->rqt_pool ? 0 : (-ENOMEM); 365} 366 367void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p) 368{ 369 gen_pool_destroy(rdev_p->rqt_pool); 370} 371