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