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 __IWCH_PROVIDER_H__ 32#define __IWCH_PROVIDER_H__ 33 34#include <rdma/ib_verbs.h> 35 36struct iwch_pd { 37 struct ib_pd ibpd; 38 u32 pdid; 39 struct iwch_dev *rhp; 40}; 41 42#ifndef container_of 43#define container_of(p, stype, field) ((stype *)(((uint8_t *)(p)) - offsetof(stype, field))) 44#endif 45static __inline struct iwch_pd * 46to_iwch_pd(struct ib_pd *ibpd) 47{ 48 return container_of(ibpd, struct iwch_pd, ibpd); 49} 50 51struct tpt_attributes { 52 u32 stag; 53 u32 state:1; 54 u32 type:2; 55 u32 rsvd:1; 56 enum tpt_mem_perm perms; 57 u32 remote_invaliate_disable:1; 58 u32 zbva:1; 59 u32 mw_bind_enable:1; 60 u32 page_size:5; 61 62 u32 pdid; 63 u32 qpid; 64 u32 pbl_addr; 65 u32 len; 66 u64 va_fbo; 67 u32 pbl_size; 68}; 69 70struct iwch_mr { 71 struct ib_mr ibmr; 72 struct ib_umem *umem; 73 struct iwch_dev *rhp; 74 u64 kva; 75 struct tpt_attributes attr; 76}; 77 78typedef struct iwch_mw iwch_mw_handle; 79 80static __inline struct iwch_mr * 81to_iwch_mr(struct ib_mr *ibmr) 82{ 83 return container_of(ibmr, struct iwch_mr, ibmr); 84} 85 86struct iwch_mw { 87 struct ib_mw ibmw; 88 struct iwch_dev *rhp; 89 u64 kva; 90 struct tpt_attributes attr; 91}; 92 93static __inline struct iwch_mw * 94to_iwch_mw(struct ib_mw *ibmw) 95{ 96 return container_of(ibmw, struct iwch_mw, ibmw); 97} 98 99struct iwch_cq { 100 struct ib_cq ibcq; 101 struct iwch_dev *rhp; 102 struct t3_cq cq; 103 struct mtx lock; 104 int refcnt; 105 u32 /* __user */ *user_rptr_addr; 106}; 107 108static __inline struct iwch_cq * 109to_iwch_cq(struct ib_cq *ibcq) 110{ 111 return container_of(ibcq, struct iwch_cq, ibcq); 112} 113 114enum IWCH_QP_FLAGS { 115 QP_QUIESCED = 0x01 116}; 117 118struct iwch_mpa_attributes { 119 u8 initiator; 120 u8 recv_marker_enabled; 121 u8 xmit_marker_enabled; /* iWARP: enable inbound Read Resp. */ 122 u8 crc_enabled; 123 u8 version; /* 0 or 1 */ 124}; 125 126struct iwch_qp_attributes { 127 u32 scq; 128 u32 rcq; 129 u32 sq_num_entries; 130 u32 rq_num_entries; 131 u32 sq_max_sges; 132 u32 sq_max_sges_rdma_write; 133 u32 rq_max_sges; 134 u32 state; 135 u8 enable_rdma_read; 136 u8 enable_rdma_write; /* enable inbound Read Resp. */ 137 u8 enable_bind; 138 u8 enable_mmid0_fastreg; /* Enable STAG0 + Fast-register */ 139 /* 140 * Next QP state. If specify the current state, only the 141 * QP attributes will be modified. 142 */ 143 u32 max_ord; 144 u32 max_ird; 145 u32 pd; /* IN */ 146 u32 next_state; 147 char terminate_buffer[52]; 148 u32 terminate_msg_len; 149 u8 is_terminate_local; 150 struct iwch_mpa_attributes mpa_attr; /* IN-OUT */ 151 struct iwch_ep *llp_stream_handle; 152 char *stream_msg_buf; /* Last stream msg. before Idle -> RTS */ 153 u32 stream_msg_buf_len; /* Only on Idle -> RTS */ 154}; 155 156struct iwch_qp { 157 struct ib_qp ibqp; 158 struct iwch_dev *rhp; 159 struct iwch_ep *ep; 160 struct iwch_qp_attributes attr; 161 struct t3_wq wq; 162 struct mtx lock; 163 int refcnt; 164 enum IWCH_QP_FLAGS flags; 165 struct callout timer; 166}; 167 168static __inline int 169qp_quiesced(struct iwch_qp *qhp) 170{ 171 return qhp->flags & QP_QUIESCED; 172} 173 174static __inline struct iwch_qp * 175to_iwch_qp(struct ib_qp *ibqp) 176{ 177 return container_of(ibqp, struct iwch_qp, ibqp); 178} 179 180void iwch_qp_add_ref(struct ib_qp *qp); 181void iwch_qp_rem_ref(struct ib_qp *qp); 182 183struct iwch_ucontext { 184 struct ib_ucontext ibucontext; 185 struct cxio_ucontext uctx; 186 u32 key; 187 struct mtx mmap_lock; 188 TAILQ_HEAD( ,iwch_mm_entry) mmaps; 189}; 190 191static __inline struct iwch_ucontext * 192to_iwch_ucontext(struct ib_ucontext *c) 193{ 194 return container_of(c, struct iwch_ucontext, ibucontext); 195} 196 197struct iwch_mm_entry { 198 TAILQ_ENTRY(iwch_mm_entry) entry; 199 u64 addr; 200 u32 key; 201 unsigned len; 202}; 203 204static __inline struct iwch_mm_entry * 205remove_mmap(struct iwch_ucontext *ucontext, 206 u32 key, unsigned len) 207{ 208 struct iwch_mm_entry *tmp, *mm; 209 210 mtx_lock(&ucontext->mmap_lock); 211 TAILQ_FOREACH_SAFE(mm, &ucontext->mmaps, entry, tmp) { 212 if (mm->key == key && mm->len == len) { 213 TAILQ_REMOVE(&ucontext->mmaps, mm, entry); 214 mtx_unlock(&ucontext->mmap_lock); 215 CTR4(KTR_IW_CXGB, "%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__, 216 key, (unsigned long long) mm->addr, mm->len); 217 return mm; 218 } 219 } 220 mtx_unlock(&ucontext->mmap_lock); 221 222 return NULL; 223} 224 225static __inline void 226insert_mmap(struct iwch_ucontext *ucontext, 227 struct iwch_mm_entry *mm) 228{ 229 mtx_lock(&ucontext->mmap_lock); 230 CTR4(KTR_IW_CXGB, "%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__, 231 mm->key, (unsigned long long) mm->addr, mm->len); 232 TAILQ_INSERT_TAIL(&ucontext->mmaps, mm, entry); 233 mtx_unlock(&ucontext->mmap_lock); 234} 235 236enum iwch_qp_attr_mask { 237 IWCH_QP_ATTR_NEXT_STATE = 1 << 0, 238 IWCH_QP_ATTR_ENABLE_RDMA_READ = 1 << 7, 239 IWCH_QP_ATTR_ENABLE_RDMA_WRITE = 1 << 8, 240 IWCH_QP_ATTR_ENABLE_RDMA_BIND = 1 << 9, 241 IWCH_QP_ATTR_MAX_ORD = 1 << 11, 242 IWCH_QP_ATTR_MAX_IRD = 1 << 12, 243 IWCH_QP_ATTR_LLP_STREAM_HANDLE = 1 << 22, 244 IWCH_QP_ATTR_STREAM_MSG_BUFFER = 1 << 23, 245 IWCH_QP_ATTR_MPA_ATTR = 1 << 24, 246 IWCH_QP_ATTR_QP_CONTEXT_ACTIVATE = 1 << 25, 247 IWCH_QP_ATTR_VALID_MODIFY = (IWCH_QP_ATTR_ENABLE_RDMA_READ | 248 IWCH_QP_ATTR_ENABLE_RDMA_WRITE | 249 IWCH_QP_ATTR_MAX_ORD | 250 IWCH_QP_ATTR_MAX_IRD | 251 IWCH_QP_ATTR_LLP_STREAM_HANDLE | 252 IWCH_QP_ATTR_STREAM_MSG_BUFFER | 253 IWCH_QP_ATTR_MPA_ATTR | 254 IWCH_QP_ATTR_QP_CONTEXT_ACTIVATE) 255}; 256 257int iwch_modify_qp(struct iwch_dev *rhp, 258 struct iwch_qp *qhp, 259 enum iwch_qp_attr_mask mask, 260 struct iwch_qp_attributes *attrs, 261 int internal); 262 263enum iwch_qp_state { 264 IWCH_QP_STATE_IDLE, 265 IWCH_QP_STATE_RTS, 266 IWCH_QP_STATE_ERROR, 267 IWCH_QP_STATE_TERMINATE, 268 IWCH_QP_STATE_CLOSING, 269 IWCH_QP_STATE_TOT 270}; 271 272static __inline int 273iwch_convert_state(enum ib_qp_state ib_state) 274{ 275 switch (ib_state) { 276 case IB_QPS_RESET: 277 case IB_QPS_INIT: 278 return IWCH_QP_STATE_IDLE; 279 case IB_QPS_RTS: 280 return IWCH_QP_STATE_RTS; 281 case IB_QPS_SQD: 282 return IWCH_QP_STATE_CLOSING; 283 case IB_QPS_SQE: 284 return IWCH_QP_STATE_TERMINATE; 285 case IB_QPS_ERR: 286 return IWCH_QP_STATE_ERROR; 287 default: 288 return -1; 289 } 290} 291 292static __inline u32 293iwch_ib_to_tpt_access(int acc) 294{ 295 return (acc & IB_ACCESS_REMOTE_WRITE ? TPT_REMOTE_WRITE : 0) | 296 (acc & IB_ACCESS_REMOTE_READ ? TPT_REMOTE_READ : 0) | 297 (acc & IB_ACCESS_LOCAL_WRITE ? TPT_LOCAL_WRITE : 0) | 298 TPT_LOCAL_READ; 299} 300 301static __inline u32 302iwch_ib_to_mwbind_access(int acc) 303{ 304 return (acc & IB_ACCESS_REMOTE_WRITE ? T3_MEM_ACCESS_REM_WRITE : 0) | 305 (acc & IB_ACCESS_REMOTE_READ ? T3_MEM_ACCESS_REM_READ : 0) | 306 (acc & IB_ACCESS_LOCAL_WRITE ? T3_MEM_ACCESS_LOCAL_WRITE : 0) | 307 T3_MEM_ACCESS_LOCAL_READ; 308} 309 310enum iwch_mmid_state { 311 IWCH_STAG_STATE_VALID, 312 IWCH_STAG_STATE_INVALID 313}; 314 315enum iwch_qp_query_flags { 316 IWCH_QP_QUERY_CONTEXT_NONE = 0x0, /* No ctx; Only attrs */ 317 IWCH_QP_QUERY_CONTEXT_GET = 0x1, /* Get ctx + attrs */ 318 IWCH_QP_QUERY_CONTEXT_SUSPEND = 0x2, /* Not Supported */ 319 320 /* 321 * Quiesce QP context; Consumer 322 * will NOT replay outstanding WR 323 */ 324 IWCH_QP_QUERY_CONTEXT_QUIESCE = 0x4, 325 IWCH_QP_QUERY_CONTEXT_REMOVE = 0x8, 326 IWCH_QP_QUERY_TEST_USERWRITE = 0x32 /* Test special */ 327}; 328 329int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, 330 struct ib_send_wr **bad_wr); 331int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, 332 struct ib_recv_wr **bad_wr); 333int iwch_bind_mw(struct ib_qp *qp, 334 struct ib_mw *mw, 335 struct ib_mw_bind *mw_bind); 336int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); 337int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg); 338int iwch_register_device(struct iwch_dev *dev); 339void iwch_unregister_device(struct iwch_dev *dev); 340void stop_read_rep_timer(struct iwch_qp *qhp); 341int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php, 342 struct iwch_mr *mhp, 343 int shift); 344int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php, 345 struct iwch_mr *mhp, 346 int shift, 347 int npages); 348int iwch_alloc_pbl(struct iwch_mr *mhp, int npages); 349void iwch_free_pbl(struct iwch_mr *mhp); 350int iwch_write_pbl(struct iwch_mr *mhp, __be64 *pages, int npages, int offset); 351int build_phys_page_list(struct ib_phys_buf *buffer_list, 352 int num_phys_buf, 353 u64 *iova_start, 354 u64 *total_size, 355 int *npages, 356 int *shift, 357 __be64 **page_list); 358 359 360#define IWCH_NODE_DESC "cxgb3 Chelsio Communications" 361 362#endif 363