1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _SYS_IB_ADAPTERS_TAVOR_QP_H 28 #define _SYS_IB_ADAPTERS_TAVOR_QP_H 29 30 /* 31 * tavor_qp.h 32 * Contains all of the prototypes, #defines, and structures necessary 33 * for all of the Queue Pair Processing routines. 34 * Specifically it contains the various flags, structures used for managing 35 * Tavor queue pairs, and prototypes for many of the functions consumed by 36 * other parts of the Tavor driver (including those routines directly 37 * exposed through the IBTF CI interface). 38 */ 39 40 #include <sys/types.h> 41 #include <sys/conf.h> 42 #include <sys/ddi.h> 43 #include <sys/sunddi.h> 44 45 #ifdef __cplusplus 46 extern "C" { 47 #endif 48 49 50 /* 51 * The following defines specify the default number of Queue Pairs (QP) and 52 * their maximum size. Settings exist for the supported DDR DIMM sizes of 53 * 128MB and 256MB. If a DIMM greater than 256 is found, then the 256MB 54 * profile is used. See tavor_cfg.c for more discussion on config profiles. 55 * 56 * For manual configuration (not using config profiles), these values are 57 * controllable through the "tavor_log_max_qp_sz" and "tavor_log_num_qp" 58 * configuration variables, respectively. To override config profile settings 59 * the 'tavor_alt_config_enable' configuration variable must first be set. 60 * 61 * Note: We also have a define for the minimum size of a QP. QPs allocated 62 * with size 0, 1, 2, or 3 will always get back a QP of size 4. This is the 63 * smallest size that Tavor hardware and software can correctly handle. 64 */ 65 #define TAVOR_NUM_QP_SHIFT_128 0x10 66 #define TAVOR_NUM_QP_SHIFT_256 0x11 67 #define TAVOR_QP_SZ_SHIFT 0x10 68 #define TAVOR_QP_SZ (1 << TAVOR_QP_SZ_SHIFT) 69 #define TAVOR_QP_MIN_SIZE 0x4 70 71 /* 72 * Minimal configuration values. 73 */ 74 #define TAVOR_NUM_QP_SHIFT_MIN 0xD 75 #define TAVOR_QP_SZ_SHIFT_MIN 0x9 76 77 /* 78 * The following macro determines whether the contents of QP memory (WQEs) 79 * need to be sync'd (with ddi_dma_sync()). This decision is based on whether 80 * the QP memory is in DDR memory (no sync) or system memory (sync required). 81 * And it also supports the possibility that if a CQ in system memory is mapped 82 * DDI_DMA_CONSISTENT, it can be configured to not be sync'd because of the 83 * "sync override" parameter in the config profile. 84 */ 85 #define TAVOR_QP_IS_SYNC_REQ(state, wqinfo) \ 86 ((((((state)->ts_cfg_profile->cp_streaming_consistent) && \ 87 ((state)->ts_cfg_profile->cp_consistent_syncoverride))) || \ 88 ((wqinfo).qa_location == TAVOR_QUEUE_LOCATION_INDDR)) \ 89 ? 0 : 1) 90 91 /* 92 * The following defines specify the size of the individual Queue Pair 93 * Context (QPC) entries. Below we also specify the size of the "Extended 94 * QPC entries as well. 95 */ 96 #define TAVOR_QPC_SIZE_SHIFT 0x8 97 #define TAVOR_QPC_SIZE (1 << TAVOR_QPC_SIZE_SHIFT) 98 #define TAVOR_EQPC_SIZE_SHIFT 0x5 99 #define TAVOR_EQPC_SIZE (1 << TAVOR_EQPC_SIZE_SHIFT) 100 101 /* 102 * The following defines specify the default number of Tavor RDMA Backing 103 * entries (RDB). Settings exist for the supported DDR DIMM sizes of 128MB and 104 * 256MB. If a DIMM greater than 256 is found, then the 256MB profile is used. 105 * See tavor_cfg.c for more discussion on config profiles. 106 * 107 * For manual configuration (not using config profiles), this value is 108 * controllable through the "tavor_log_num_rdb" configuration variable. To 109 * override config profile settings the 'tavor_alt_config_enable' configuration 110 * variable must first be set. 111 * 112 * Below we also include the defines that are used to specify four (4) 113 * outstanding RDMA Reads/Atomics per QP. 114 */ 115 116 #define TAVOR_NUM_RDB_SHIFT_128 0x12 117 #define TAVOR_NUM_RDB_SHIFT_256 0x13 118 119 #define TAVOR_HCA_MAX_RDMA_IN_QP 0x4 120 #define TAVOR_HCA_MAX_RDMA_OUT_QP 0x4 121 122 /* 123 * Minimal configuration value. 124 */ 125 #define TAVOR_NUM_RDB_SHIFT_MIN 0xC 126 127 /* 128 * The following defines specify the size of the individual RDMA Backing 129 * entries (RDB). 130 */ 131 #define TAVOR_RDB_SIZE_SHIFT 0x5 132 #define TAVOR_RDB_SIZE (1 << TAVOR_RDB_SIZE_SHIFT) 133 134 /* 135 * This defines the maximum number of SGLs per WQE. This value is 136 * controllable through the "tavor_wqe_max_sgl" configuration variable (but 137 * should not be set larger than this value). 138 */ 139 #define TAVOR_NUM_WQE_SGL 0x10 140 141 /* Define for maximum QP number mask (QP number is 24 bits) */ 142 #define TAVOR_QP_MAXNUMBER_MSK 0xFFFFFF 143 144 /* 145 * This define and the following macro are used to find a schedule queue for 146 * a new QP based on its queue pair number. Note: This is a rather simple 147 * method that we use today. We simply choose from the schedule queue based 148 * on the 4 least significant bits of the QP number. 149 */ 150 #define TAVOR_QP_TO_SCHEDQ_MASK 0xF 151 #define TAVOR_QP_SCHEDQ_GET(qpnum) ((qpnum) & TAVOR_QP_TO_SCHEDQ_MASK) 152 153 /* 154 * This define determines the frequency with which the AckReq bit will be 155 * set in outgoing RC packets. By default it is set to five (5) or 2^5 = 32. 156 * So AckReq will be set once every 32 packets sent. This value is 157 * controllable through the "tavor_qp_ackreq_freq" configuration variable. 158 */ 159 #define TAVOR_QP_ACKREQ_FREQ 0x5 160 161 /* 162 * Define the maximum message size (log 2). Note: This value corresponds 163 * to the maximum allowable message sized as defined by the IBA spec. 164 */ 165 #define TAVOR_QP_LOG_MAX_MSGSZ 0x1F 166 167 /* 168 * This macro is used to determine the appropriate alignment for a Tavor 169 * work queue (see tavor_qp_alloc() and tavor_special_qp_alloc()). Note: 170 * Tavor work queues are aligned on their combined size (i.e. combined size 171 * of send queue and receive queue) because of certain hardware limitations 172 * (i.e. work queue memory cannot cross a 32-bit boundary). 173 */ 174 #define TAVOR_QP_WQ_ALIGN(qp_size) \ 175 (1 << ((((qp_size) & ((qp_size) - 1)) == 0) ? \ 176 highbit((qp_size)) - 1 : highbit((qp_size)))) 177 178 /* 179 * This macro is used to determine if the tavor known QP type (qp_serv) is the 180 * same as the caller passed in IBT type (qp_trans). This is used in QP modify 181 * to ensure the types match. 182 */ 183 #define TAVOR_QP_TYPE_VALID(qp_trans, qp_serv) \ 184 ((qp_trans == IBT_UD_SRV && qp_serv == TAVOR_QP_UD) || \ 185 (qp_trans == IBT_RC_SRV && qp_serv == TAVOR_QP_RC) || \ 186 (qp_trans == IBT_UC_SRV && qp_serv == TAVOR_QP_UC)) 187 188 /* 189 * The following enumerated type is used to capture all the various types 190 * of Tavor work queue types. Note: It is specifically used as an argument 191 * to the tavor_qp_sgl_to_logwqesz() routine. 192 * The defines below are also used by the tavor_qp_sgl_to_logwqesz() routine 193 * they indicate the amount of overhead (in WQE header size) consumed by 194 * each of the following types of WQEs. This information is used to round 195 * the WQE size to the next largest power-of-2 (and to determine the number 196 * of SGLs that are supported for the given WQE type). There is also a define 197 * below used to specify the minimum size for a WQE. The minimum size is set 198 * to 64 bytes (a single cacheline). 199 */ 200 typedef enum { 201 TAVOR_QP_WQ_TYPE_SENDQ, 202 TAVOR_QP_WQ_TYPE_RECVQ, 203 TAVOR_QP_WQ_TYPE_SENDMLX_QP0, 204 TAVOR_QP_WQ_TYPE_SENDMLX_QP1 205 } tavor_qp_wq_type_t; 206 #define TAVOR_QP_WQE_MAX_SIZE 0x3F0 207 #define TAVOR_QP_WQE_MLX_SND_HDRS 0x40 208 #define TAVOR_QP_WQE_MLX_RCV_HDRS 0x10 209 #define TAVOR_QP_WQE_MLX_QP0_HDRS 0x40 210 #define TAVOR_QP_WQE_MLX_QP1_HDRS 0x70 211 #define TAVOR_QP_WQE_LOG_MINIMUM 0x6 212 213 214 /* 215 * The tavor_qp_info_t structure is used internally by the Tavor driver to 216 * pass information to and from the tavor_qp_alloc() and 217 * tavor_special_qp_alloc() routines. It contains placeholders for all of the 218 * potential inputs and outputs that either routine can take. 219 */ 220 typedef struct tavor_qp_info_s { 221 ibt_qp_alloc_attr_t *qpi_attrp; 222 uint_t qpi_type; 223 uint_t qpi_port; 224 ibtl_qp_hdl_t qpi_ibt_qphdl; 225 ibt_chan_sizes_t *qpi_queueszp; 226 ib_qpn_t *qpi_qpn; 227 tavor_qphdl_t qpi_qphdl; 228 } tavor_qp_info_t; 229 230 /* 231 * The QPN entry which is stored in the AVL tree 232 */ 233 typedef struct tavor_qpn_entry_s { 234 avl_node_t qpn_avlnode; 235 uint_t qpn_refcnt; 236 uint_t qpn_counter; 237 uint_t qpn_indx; 238 tavor_rsrc_t *qpn_qpc; 239 } tavor_qpn_entry_t; 240 #define TAVOR_QPN_NOFLAG 0x0 241 #define TAVOR_QPN_RELEASE 0x1 242 #define TAVOR_QPN_FREE_ONLY 0x2 243 244 /* 245 * The tavor_sw_qp_s structure is also referred to using the "tavor_qphdl_t" 246 * typedef (see tavor_typedef.h). It encodes all the information necessary 247 * to track the various resources needed to allocate, query, modify, and 248 * (later) free both normal QP and special QP. 249 * 250 * Specifically, it has a lock to ensure single threaded access to the QP. 251 * It has QP state, type, and number, pointers to the PD, MR, and CQ handles 252 * associated with the QP, and pointers to the buffer where the work queues 253 * come from. 254 * 255 * It has two pointers (one per work queue) to the workQ headers for the WRID 256 * list, as well as pointers to the last WQE on each chain (used when 257 * connecting a new chain of WQEs to a previously executing chain - see 258 * tavor_wr.c). It's also got the real WQE size, real number of SGL per WQE, 259 * and the size of each of the work queues (in number of WQEs). 260 * 261 * Additionally, it has pointers to the resources associated with the QP 262 * (including the obligatory backpointer to the resource for the QP handle 263 * itself. But it also has some flags, like "qp_forward_sqd_event" and 264 * "qp_sqd_still_draining" (which are used to indicate whether a Send Queue 265 * Drained Event should be forwarded to the IBTF) or "qp_is_special", 266 * "qp_portnum", and "qp_pkeyindx" (which are used by special QP to store 267 * necessary information about the type of the QP, which port it's connected 268 * to, and what its current PKey index is set to). 269 */ 270 struct tavor_sw_qp_s { 271 kmutex_t qp_lock; 272 uint_t qp_state; 273 uint32_t qp_qpnum; 274 tavor_pdhdl_t qp_pdhdl; 275 uint_t qp_serv_type; 276 uint_t qp_sync; 277 tavor_mrhdl_t qp_mrhdl; 278 uint_t qp_sq_sigtype; 279 uint_t qp_is_special; 280 uint_t qp_is_umap; 281 uint32_t qp_uarpg; 282 devmap_cookie_t qp_umap_dhp; 283 uint_t qp_portnum; 284 uint_t qp_pkeyindx; 285 286 /* Send Work Queue */ 287 tavor_cqhdl_t qp_sq_cqhdl; 288 uint64_t *qp_sq_lastwqeaddr; 289 tavor_workq_hdr_t *qp_sq_wqhdr; 290 uint32_t *qp_sq_buf; 291 uint32_t qp_sq_bufsz; 292 uint32_t qp_sq_log_wqesz; 293 uint32_t qp_sq_sgl; 294 295 /* Receive Work Queue */ 296 tavor_cqhdl_t qp_rq_cqhdl; 297 uint64_t *qp_rq_lastwqeaddr; 298 tavor_workq_hdr_t *qp_rq_wqhdr; 299 uint32_t *qp_rq_buf; 300 uint32_t qp_rq_bufsz; 301 uint32_t qp_rq_log_wqesz; 302 uint32_t qp_rq_sgl; 303 304 uint64_t qp_desc_off; 305 306 tavor_rsrc_t *qp_qpcrsrcp; 307 tavor_rsrc_t *qp_rsrcp; 308 void *qp_hdlrarg; 309 tavor_rsrc_t *qp_rdbrsrcp; 310 uint64_t qp_rdb_ddraddr; 311 uint_t qp_forward_sqd_event; 312 uint_t qp_sqd_still_draining; 313 314 /* Shared Receive Queue */ 315 tavor_srqhdl_t qp_srqhdl; 316 uint_t qp_srq_en; 317 318 /* Refcnt of QP belongs to an MCG */ 319 uint_t qp_mcg_refcnt; 320 321 /* save the mtu & srate from init2rtr for future use */ 322 uint_t qp_save_mtu; 323 ibt_srate_t qp_save_srate; 324 tavor_qpn_entry_t *qp_qpn_hdl; 325 326 struct tavor_qalloc_info_s qp_wqinfo; 327 328 struct tavor_hw_qpc_s qpc; 329 }; 330 _NOTE(READ_ONLY_DATA(tavor_sw_qp_s::qp_qpnum 331 tavor_sw_qp_s::qp_sync 332 tavor_sw_qp_s::qp_sq_buf 333 tavor_sw_qp_s::qp_sq_log_wqesz 334 tavor_sw_qp_s::qp_sq_bufsz 335 tavor_sw_qp_s::qp_sq_sgl 336 tavor_sw_qp_s::qp_rq_buf 337 tavor_sw_qp_s::qp_rq_log_wqesz 338 tavor_sw_qp_s::qp_rq_bufsz 339 tavor_sw_qp_s::qp_rq_sgl 340 tavor_sw_qp_s::qp_desc_off 341 tavor_sw_qp_s::qp_mrhdl 342 tavor_sw_qp_s::qp_wqinfo 343 tavor_sw_qp_s::qp_qpcrsrcp 344 tavor_sw_qp_s::qp_rsrcp 345 tavor_sw_qp_s::qp_hdlrarg 346 tavor_sw_qp_s::qp_pdhdl 347 tavor_sw_qp_s::qp_sq_cqhdl 348 tavor_sw_qp_s::qp_rq_cqhdl 349 tavor_sw_qp_s::qp_sq_sigtype 350 tavor_sw_qp_s::qp_serv_type 351 tavor_sw_qp_s::qp_is_special 352 tavor_sw_qp_s::qp_is_umap 353 tavor_sw_qp_s::qp_uarpg 354 tavor_sw_qp_s::qp_portnum 355 tavor_sw_qp_s::qp_qpn_hdl)) 356 _NOTE(MUTEX_PROTECTS_DATA(tavor_sw_qp_s::qp_lock, 357 tavor_sw_qp_s::qp_sq_wqhdr 358 tavor_sw_qp_s::qp_sq_lastwqeaddr 359 tavor_sw_qp_s::qp_rq_wqhdr 360 tavor_sw_qp_s::qp_rq_lastwqeaddr 361 tavor_sw_qp_s::qp_state 362 tavor_sw_qp_s::qp_rdbrsrcp 363 tavor_sw_qp_s::qp_rdb_ddraddr 364 tavor_sw_qp_s::qpc 365 tavor_sw_qp_s::qp_forward_sqd_event 366 tavor_sw_qp_s::qp_sqd_still_draining 367 tavor_sw_qp_s::qp_mcg_refcnt 368 tavor_sw_qp_s::qp_save_mtu 369 tavor_sw_qp_s::qp_umap_dhp)) 370 371 /* 372 * The following defines are used to indicate whether a QP is special or 373 * not (and what type it is). They are used in the "qp_is_special" field 374 * above. 375 */ 376 #define TAVOR_QP_SMI 0x1 377 #define TAVOR_QP_GSI 0x2 378 379 /* 380 * The tavor_qp_options_t structure is used in the Tavor QP allocation 381 * routines to provide additional option functionality. When a NULL pointer 382 * is passed in place of a pointer to this struct, it is a way of specifying 383 * the "default" behavior. Using this structure, however, is a way of 384 * controlling any extended behavior. 385 * 386 * Currently, the only defined "extended" behavior is for specifying whether 387 * a given QP's work queues should be allocated from kernel system memory 388 * (TAVOR_QUEUE_LOCATION_NORMAL) or should be allocated from local DDR memory 389 * (TAVOR_QUEUE_LOCATION_INDDR). This defaults today to always allocating 390 * from kernel system memory but can be changed by using the 391 * "tavor_qp_wq_inddr" configuration variable. 392 */ 393 typedef struct tavor_qp_options_s { 394 uint_t qpo_wq_loc; 395 } tavor_qp_options_t; 396 397 398 /* Defined in tavor_qp.c */ 399 int tavor_qp_alloc(tavor_state_t *state, tavor_qp_info_t *qpinfo, 400 uint_t sleepflag, tavor_qp_options_t *op); 401 int tavor_special_qp_alloc(tavor_state_t *state, tavor_qp_info_t *qpinfo, 402 uint_t sleepflag, tavor_qp_options_t *op); 403 int tavor_qp_free(tavor_state_t *state, tavor_qphdl_t *qphdl, 404 ibc_free_qp_flags_t free_qp_flags, ibc_qpn_hdl_t *qpnh, uint_t sleepflag); 405 int tavor_qp_query(tavor_state_t *state, tavor_qphdl_t qphdl, 406 ibt_qp_query_attr_t *attr_p); 407 tavor_qphdl_t tavor_qphdl_from_qpnum(tavor_state_t *state, uint_t qpnum); 408 void tavor_qp_release_qpn(tavor_state_t *state, tavor_qpn_entry_t *entry, 409 int flags); 410 void tavor_qpn_avl_init(tavor_state_t *state); 411 void tavor_qpn_avl_fini(tavor_state_t *state); 412 413 /* Defined in tavor_qpmod.c */ 414 int tavor_qp_modify(tavor_state_t *state, tavor_qphdl_t qp, 415 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p, 416 ibt_queue_sizes_t *actual_sz); 417 int tavor_qp_to_reset(tavor_state_t *state, tavor_qphdl_t qp); 418 419 #ifdef __cplusplus 420 } 421 #endif 422 423 #endif /* _SYS_IB_ADAPTERS_TAVOR_QP_H */ 424