1/************************************************************************** 2 3Copyright (c) 2007, 2008 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$FreeBSD$ 29 30***************************************************************************/ 31#ifndef __CXIO_HAL_H__ 32#define __CXIO_HAL_H__ 33#include <sys/condvar.h> 34#include <sys/ktr.h> 35 36#define T3_CTRL_QP_ID FW_RI_SGEEC_START 37#define T3_CTL_QP_TID FW_RI_TID_START 38#define T3_CTRL_QP_SIZE_LOG2 8 39#define T3_CTRL_CQ_ID 0 40 41/* TBD */ 42#define T3_MAX_NUM_RI (1<<15) 43#define T3_MAX_NUM_QP (1<<15) 44#define T3_MAX_NUM_CQ (1<<15) 45#define T3_MAX_NUM_PD (1<<15) 46#define T3_MAX_PBL_SIZE 256 47#define T3_MAX_RQ_SIZE 1024 48#define T3_MAX_QP_DEPTH (T3_MAX_RQ_SIZE-1) 49#define T3_MAX_CQ_DEPTH 65536 50#define T3_MAX_NUM_STAG (1<<15) 51#define T3_MAX_MR_SIZE 0x100000000ULL 52#define T3_PAGESIZE_MASK 0xffff000 /* 4KB-128MB */ 53 54#define T3_STAG_UNSET 0xffffffff 55 56#define T3_MAX_DEV_NAME_LEN 32 57 58struct cxio_hal_ctrl_qp { 59 u32 wptr; 60 u32 rptr; 61 struct mtx lock; /* for the wtpr, can sleep */ 62 union t3_wr *workq; /* the work request queue */ 63 bus_addr_t dma_addr; /* pci bus address of the workq */ 64 void *doorbell; 65}; 66 67struct cxio_hal_resource { 68 struct buf_ring *tpt_fifo; 69 struct mtx tpt_fifo_lock; 70 struct buf_ring *qpid_fifo; 71 struct mtx qpid_fifo_lock; 72 struct buf_ring *cqid_fifo; 73 struct mtx cqid_fifo_lock; 74 struct buf_ring *pdid_fifo; 75 struct mtx pdid_fifo_lock; 76}; 77 78struct cxio_qpid { 79 TAILQ_ENTRY(cxio_qpid) entry; 80 u32 qpid; 81}; 82 83struct cxio_ucontext { 84 TAILQ_HEAD(, cxio_qpid) qpids; 85 struct mtx lock; 86}; 87 88struct cxio_rdev { 89 struct adapter *adap; 90 struct rdma_info rnic_info; 91 struct cxio_hal_resource *rscp; 92 struct cxio_hal_ctrl_qp ctrl_qp; 93 unsigned long qpshift; 94 u32 qpnr; 95 u32 qpmask; 96 struct cxio_ucontext uctx; 97 struct gen_pool *pbl_pool; 98 struct gen_pool *rqt_pool; 99 struct ifnet *ifp; 100 TAILQ_ENTRY(cxio_rdev) entry; 101}; 102 103static __inline int 104cxio_num_stags(struct cxio_rdev *rdev_p) 105{ 106 return min((int)T3_MAX_NUM_STAG, (int)((rdev_p->rnic_info.tpt_top - rdev_p->rnic_info.tpt_base) >> 5)); 107} 108 109typedef void (*cxio_hal_ev_callback_func_t) (struct cxio_rdev * rdev_p, 110 struct mbuf * m); 111 112#define RSPQ_CQID(rsp) (be32toh(rsp->cq_ptrid) & 0xffff) 113#define RSPQ_CQPTR(rsp) ((be32toh(rsp->cq_ptrid) >> 16) & 0xffff) 114#define RSPQ_GENBIT(rsp) ((be32toh(rsp->flags) >> 16) & 1) 115#define RSPQ_OVERFLOW(rsp) ((be32toh(rsp->flags) >> 17) & 1) 116#define RSPQ_AN(rsp) ((be32toh(rsp->flags) >> 18) & 1) 117#define RSPQ_SE(rsp) ((be32toh(rsp->flags) >> 19) & 1) 118#define RSPQ_NOTIFY(rsp) ((be32toh(rsp->flags) >> 20) & 1) 119#define RSPQ_CQBRANCH(rsp) ((be32toh(rsp->flags) >> 21) & 1) 120#define RSPQ_CREDIT_THRESH(rsp) ((be32toh(rsp->flags) >> 22) & 1) 121 122struct respQ_msg_t { 123 __be32 flags; /* flit 0 */ 124 __be32 cq_ptrid; 125 __be64 rsvd; /* flit 1 */ 126 struct t3_cqe cqe; /* flits 2-3 */ 127}; 128 129enum t3_cq_opcode { 130 CQ_ARM_AN = 0x2, 131 CQ_ARM_SE = 0x6, 132 CQ_FORCE_AN = 0x3, 133 CQ_CREDIT_UPDATE = 0x7 134}; 135 136int cxio_rdev_open(struct cxio_rdev *rdev); 137void cxio_rdev_close(struct cxio_rdev *rdev); 138int cxio_hal_cq_op(struct cxio_rdev *rdev, struct t3_cq *cq, 139 enum t3_cq_opcode op, u32 credit); 140int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq, int kernel); 141int cxio_destroy_cq(struct cxio_rdev *rdev, struct t3_cq *cq); 142void cxio_release_ucontext(struct cxio_rdev *rdev, struct cxio_ucontext *uctx); 143void cxio_init_ucontext(struct cxio_rdev *rdev, struct cxio_ucontext *uctx); 144int cxio_create_qp(struct cxio_rdev *rdev, u32 kernel_domain, struct t3_wq *wq, 145 struct cxio_ucontext *uctx); 146int cxio_destroy_qp(struct cxio_rdev *rdev, struct t3_wq *wq, 147 struct cxio_ucontext *uctx); 148int cxio_peek_cq(struct t3_wq *wr, struct t3_cq *cq, int opcode); 149int cxio_write_pbl(struct cxio_rdev *rdev_p, __be64 *pbl, 150 u32 pbl_addr, u32 pbl_size); 151int cxio_register_phys_mem(struct cxio_rdev *rdev, u32 * stag, u32 pdid, 152 enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len, 153 u8 page_size, u32 pbl_size, u32 pbl_addr); 154int cxio_reregister_phys_mem(struct cxio_rdev *rdev, u32 * stag, u32 pdid, 155 enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len, 156 u8 page_size, u32 pbl_size, u32 pbl_addr); 157int cxio_dereg_mem(struct cxio_rdev *rdev, u32 stag, u32 pbl_size, 158 u32 pbl_addr); 159int cxio_allocate_window(struct cxio_rdev *rdev, u32 * stag, u32 pdid); 160int cxio_deallocate_window(struct cxio_rdev *rdev, u32 stag); 161int cxio_rdma_init(struct cxio_rdev *rdev, struct t3_rdma_init_attr *attr, 162 struct socket *so); 163u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp); 164void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid); 165int cxio_hal_init(struct adapter *); 166void cxio_hal_uninit(struct adapter *); 167void cxio_hal_exit(void); 168int cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count); 169int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count); 170void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count); 171void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count); 172void cxio_flush_hw_cq(struct t3_cq *cq); 173int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe, 174 u8 *cqe_flushed, u64 *cookie, u32 *credit); 175 176#define MOD "iw_cxgb: " 177 178#ifdef INVARIANTS 179void cxio_dump_tpt(struct cxio_rdev *rev, u32 stag); 180void cxio_dump_pbl(struct cxio_rdev *rev, u32 pbl_addr, uint32_t len, u8 shift); 181void cxio_dump_wqe(union t3_wr *wqe); 182void cxio_dump_wce(struct t3_cqe *wce); 183void cxio_dump_rqt(struct cxio_rdev *rdev, u32 hwtid, int nents); 184void cxio_dump_tcb(struct cxio_rdev *rdev, u32 hwtid); 185#endif 186 187#define cxfree(a) free((a), M_DEVBUF); 188 189#include <sys/blist.h> 190struct gen_pool { 191 blist_t gen_list; 192 daddr_t gen_base; 193 int gen_chunk_shift; 194 struct mtx gen_lock; 195}; 196 197static __inline struct gen_pool * 198gen_pool_create(daddr_t base, u_int chunk_shift, u_int len) 199{ 200 struct gen_pool *gp; 201 202 gp = malloc(sizeof(struct gen_pool), M_DEVBUF, M_NOWAIT); 203 if (gp == NULL) 204 return (NULL); 205 206 memset(gp, 0, sizeof(struct gen_pool)); 207 gp->gen_list = blist_create(len >> chunk_shift, M_NOWAIT); 208 if (gp->gen_list == NULL) { 209 free(gp, M_DEVBUF); 210 return (NULL); 211 } 212 blist_free(gp->gen_list, 0, len >> chunk_shift); 213 gp->gen_base = base; 214 gp->gen_chunk_shift = chunk_shift; 215 mtx_init(&gp->gen_lock, "genpool", NULL, MTX_DUPOK|MTX_DEF); 216 217 return (gp); 218} 219 220static __inline unsigned long 221gen_pool_alloc(struct gen_pool *gp, int size) 222{ 223 int chunks; 224 daddr_t blkno; 225 226 chunks = (size + (1<<gp->gen_chunk_shift) - 1) >> gp->gen_chunk_shift; 227 mtx_lock(&gp->gen_lock); 228 blkno = blist_alloc(gp->gen_list, chunks); 229 mtx_unlock(&gp->gen_lock); 230 231 if (blkno == SWAPBLK_NONE) 232 return (0); 233 234 return (gp->gen_base + ((1 << gp->gen_chunk_shift) * blkno)); 235} 236 237static __inline void 238gen_pool_free(struct gen_pool *gp, daddr_t address, int size) 239{ 240 int chunks; 241 daddr_t blkno; 242 243 chunks = (size + (1<<gp->gen_chunk_shift) - 1) >> gp->gen_chunk_shift; 244 blkno = (address - gp->gen_base) / (1 << gp->gen_chunk_shift); 245 mtx_lock(&gp->gen_lock); 246 blist_free(gp->gen_list, blkno, chunks); 247 mtx_unlock(&gp->gen_lock); 248} 249 250static __inline void 251gen_pool_destroy(struct gen_pool *gp) 252{ 253 blist_destroy(gp->gen_list); 254 free(gp, M_DEVBUF); 255} 256 257#define cxio_wait(ctx, lockp, cond) \ 258({ \ 259 int __ret = 0; \ 260 mtx_lock(lockp); \ 261 while (!cond) { \ 262 msleep(ctx, lockp, 0, "cxio_wait", hz); \ 263 if (SIGPENDING(curthread)) { \ 264 __ret = ERESTART; \ 265 break; \ 266 } \ 267 } \ 268 mtx_unlock(lockp); \ 269 __ret; \ 270}) 271 272#define KTR_IW_CXGB KTR_SPARE3 273 274#endif 275