iw_cxgb_resource.c revision 185162
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 185162 2008-11-22 05:55:56Z 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_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 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_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 164int 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 170void 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 */ 177int 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; 205pdid_err: 206 buf_ring_free(rscp->cqid_fifo, M_DEVBUF); 207cqid_err: 208 buf_ring_free(rscp->qpid_fifo, M_DEVBUF); 209qpid_err: 210 buf_ring_free(rscp->tpt_fifo, M_DEVBUF); 211tpt_err: 212 return (-ENOMEM); 213} 214 215/* 216 * returns 0 if no resource available 217 */ 218static 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 228static 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 235u32 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 240void 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 245u32 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 252void 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 258u32 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 263void 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 268u32 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 273void 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 278void 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 294u32 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 301void 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 307int 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 325void 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 337u32 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 344void 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 350int 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 368void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p) 369{ 370 gen_pool_destroy(rdev_p->rqt_pool); 371} 372