5255 uts shouldn't open-code ISP2
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * hermon_srq.c 28 * Hermon Shared Receive Queue Processing Routines 29 * 30 * Implements all the routines necessary for allocating, freeing, querying, 31 * modifying and posting shared receive queues. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/conf.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 #include <sys/modctl.h> 39 #include <sys/bitmap.h> 40 41 #include <sys/ib/adapters/hermon/hermon.h> 42 43 static void hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl, 44 hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl); 45 46 /* 47 * hermon_srq_alloc() 48 * Context: Can be called only from user or kernel context. 49 */ 50 int 51 hermon_srq_alloc(hermon_state_t *state, hermon_srq_info_t *srqinfo, 52 uint_t sleepflag) 53 { 54 ibt_srq_hdl_t ibt_srqhdl; 55 hermon_pdhdl_t pd; 56 ibt_srq_sizes_t *sizes; 57 ibt_srq_sizes_t *real_sizes; 58 hermon_srqhdl_t *srqhdl; 59 ibt_srq_flags_t flags; 60 hermon_rsrc_t *srqc, *rsrc; 61 hermon_hw_srqc_t srqc_entry; 62 uint32_t *buf; 63 hermon_srqhdl_t srq; 64 hermon_umap_db_entry_t *umapdb; 65 ibt_mr_attr_t mr_attr; 66 hermon_mr_options_t mr_op; 67 hermon_mrhdl_t mr; 68 uint64_t value, srq_desc_off; 69 uint32_t log_srq_size; 70 uint32_t uarpg; 71 uint_t srq_is_umap; 72 int flag, status; 73 uint_t max_sgl; 74 uint_t wqesz; 75 uint_t srq_wr_sz; 76 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sizes)) 77 78 /* 79 * options-->wq_location used to be for location, now explicitly 80 * LOCATION_NORMAL 81 */ 82 83 /* 84 * Extract the necessary info from the hermon_srq_info_t structure 85 */ 86 real_sizes = srqinfo->srqi_real_sizes; 87 sizes = srqinfo->srqi_sizes; 88 pd = srqinfo->srqi_pd; 89 ibt_srqhdl = srqinfo->srqi_ibt_srqhdl; 90 flags = srqinfo->srqi_flags; 91 srqhdl = srqinfo->srqi_srqhdl; 92 93 /* 94 * Determine whether SRQ is being allocated for userland access or 95 * whether it is being allocated for kernel access. If the SRQ is 96 * being allocated for userland access, then lookup the UAR doorbell 97 * page number for the current process. Note: If this is not found 98 * (e.g. if the process has not previously open()'d the Hermon driver), 99 * then an error is returned. 100 */ 101 srq_is_umap = (flags & IBT_SRQ_USER_MAP) ? 1 : 0; 102 if (srq_is_umap) { 103 status = hermon_umap_db_find(state->hs_instance, ddi_get_pid(), 104 MLNX_UMAP_UARPG_RSRC, &value, 0, NULL); 105 if (status != DDI_SUCCESS) { 106 status = IBT_INVALID_PARAM; 107 goto srqalloc_fail3; 108 } 109 uarpg = ((hermon_rsrc_t *)(uintptr_t)value)->hr_indx; 110 } else { 111 uarpg = state->hs_kernel_uar_index; 112 } 113 114 /* Increase PD refcnt */ 115 hermon_pd_refcnt_inc(pd); 116 117 /* Allocate an SRQ context entry */ 118 status = hermon_rsrc_alloc(state, HERMON_SRQC, 1, sleepflag, &srqc); 119 if (status != DDI_SUCCESS) { 120 status = IBT_INSUFF_RESOURCE; 121 goto srqalloc_fail1; 122 } 123 124 /* Allocate the SRQ Handle entry */ 125 status = hermon_rsrc_alloc(state, HERMON_SRQHDL, 1, sleepflag, &rsrc); 126 if (status != DDI_SUCCESS) { 127 status = IBT_INSUFF_RESOURCE; 128 goto srqalloc_fail2; 129 } 130 131 srq = (hermon_srqhdl_t)rsrc->hr_addr; 132 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq)) 133 134 bzero(srq, sizeof (struct hermon_sw_srq_s)); 135 /* Calculate the SRQ number */ 136 137 /* just use the index, implicit in Hermon */ 138 srq->srq_srqnum = srqc->hr_indx; 139 140 /* 141 * If this will be a user-mappable SRQ, then allocate an entry for 142 * the "userland resources database". This will later be added to 143 * the database (after all further SRQ operations are successful). 144 * If we fail here, we must undo the reference counts and the 145 * previous resource allocation. 146 */ 147 if (srq_is_umap) { 148 umapdb = hermon_umap_db_alloc(state->hs_instance, 149 srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC, 150 (uint64_t)(uintptr_t)rsrc); 151 if (umapdb == NULL) { 152 status = IBT_INSUFF_RESOURCE; 153 goto srqalloc_fail3; 154 } 155 } 156 157 /* 158 * Allocate the doorbell record. Hermon just needs one for the 159 * SRQ, and use uarpg (above) as the uar index 160 */ 161 162 status = hermon_dbr_alloc(state, uarpg, &srq->srq_wq_dbr_acchdl, 163 &srq->srq_wq_vdbr, &srq->srq_wq_pdbr, &srq->srq_rdbr_mapoffset); 164 if (status != DDI_SUCCESS) { 165 status = IBT_INSUFF_RESOURCE; 166 goto srqalloc_fail4; 167 } 168 169 /* 170 * Calculate the appropriate size for the SRQ. 171 * Note: All Hermon SRQs must be a power-of-2 in size. Also 172 * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step 173 * is to round the requested size up to the next highest power-of-2 174 */ 175 srq_wr_sz = max(sizes->srq_wr_sz + 1, HERMON_SRQ_MIN_SIZE); 176 log_srq_size = highbit(srq_wr_sz); 177 if ((srq_wr_sz & (srq_wr_sz - 1)) == 0) { 178 log_srq_size = log_srq_size - 1; 179 } 180 181 /* 182 * Next we verify that the rounded-up size is valid (i.e. consistent 183 * with the device limits and/or software-configured limits). If not, 184 * then obviously we have a lot of cleanup to do before returning. 185 */ 186 if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) { 187 status = IBT_HCA_WR_EXCEEDED; 188 goto srqalloc_fail4a; 189 } 190 191 /* 192 * Next we verify that the requested number of SGL is valid (i.e. 193 * consistent with the device limits and/or software-configured 194 * limits). If not, then obviously the same cleanup needs to be done. 195 */ 196 max_sgl = state->hs_ibtfinfo.hca_attr->hca_max_srq_sgl; 197 if (sizes->srq_sgl_sz > max_sgl) { 198 status = IBT_HCA_SGL_EXCEEDED; 199 goto srqalloc_fail4a; 200 } 201 202 /* 203 * Determine the SRQ's WQE sizes. This depends on the requested 204 * number of SGLs. Note: This also has the side-effect of 205 * calculating the real number of SGLs (for the calculated WQE size) 206 */ 207 hermon_srq_sgl_to_logwqesz(state, sizes->srq_sgl_sz, 208 HERMON_QP_WQ_TYPE_RECVQ, &srq->srq_wq_log_wqesz, 209 &srq->srq_wq_sgl); 210 211 /* 212 * Allocate the memory for SRQ work queues. Note: The location from 213 * which we will allocate these work queues is always 214 * QUEUE_LOCATION_NORMAL. Since Hermon work queues are not 215 * allowed to cross a 32-bit (4GB) boundary, the alignment of the work 216 * queue memory is very important. We used to allocate work queues 217 * (the combined receive and send queues) so that they would be aligned 218 * on their combined size. That alignment guaranteed that they would 219 * never cross the 4GB boundary (Hermon work queues are on the order of 220 * MBs at maximum). Now we are able to relax this alignment constraint 221 * by ensuring that the IB address assigned to the queue memory (as a 222 * result of the hermon_mr_register() call) is offset from zero. 223 * Previously, we had wanted to use the ddi_dma_mem_alloc() routine to 224 * guarantee the alignment, but when attempting to use IOMMU bypass 225 * mode we found that we were not allowed to specify any alignment that 226 * was more restrictive than the system page size. So we avoided this 227 * constraint by passing two alignment values, one for the memory 228 * allocation itself and the other for the DMA handle (for later bind). 229 * This used to cause more memory than necessary to be allocated (in 230 * order to guarantee the more restrictive alignment contraint). But 231 * be guaranteeing the zero-based IB virtual address for the queue, we 232 * are able to conserve this memory. 233 * 234 * Note: If SRQ is not user-mappable, then it may come from either 235 * kernel system memory or from HCA-attached local DDR memory. 236 * 237 * Note2: We align this queue on a pagesize boundary. This is required 238 * to make sure that all the resulting IB addresses will start at 0, for 239 * a zero-based queue. By making sure we are aligned on at least a 240 * page, any offset we use into our queue will be the same as when we 241 * perform hermon_srq_modify() operations later. 242 */ 243 wqesz = (1 << srq->srq_wq_log_wqesz); 244 srq->srq_wqinfo.qa_size = (1 << log_srq_size) * wqesz; 245 srq->srq_wqinfo.qa_alloc_align = PAGESIZE; 246 srq->srq_wqinfo.qa_bind_align = PAGESIZE; 247 if (srq_is_umap) { 248 srq->srq_wqinfo.qa_location = HERMON_QUEUE_LOCATION_USERLAND; 249 } else { 250 srq->srq_wqinfo.qa_location = HERMON_QUEUE_LOCATION_NORMAL; 251 } 252 status = hermon_queue_alloc(state, &srq->srq_wqinfo, sleepflag); 253 if (status != DDI_SUCCESS) { 254 status = IBT_INSUFF_RESOURCE; 255 goto srqalloc_fail4a; 256 } 257 buf = (uint32_t *)srq->srq_wqinfo.qa_buf_aligned; 258 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*buf)) 259 260 /* 261 * Register the memory for the SRQ work queues. The memory for the SRQ 262 * must be registered in the Hermon cMPT tables. This gives us the LKey 263 * to specify in the SRQ context later. Note: If the work queue is to 264 * be allocated from DDR memory, then only a "bypass" mapping is 265 * appropriate. And if the SRQ memory is user-mappable, then we force 266 * DDI_DMA_CONSISTENT mapping. Also, in order to meet the alignment 267 * restriction, we pass the "mro_bind_override_addr" flag in the call 268 * to hermon_mr_register(). This guarantees that the resulting IB vaddr 269 * will be zero-based (modulo the offset into the first page). If we 270 * fail here, we still have the bunch of resource and reference count 271 * cleanup to do. 272 */ 273 flag = (sleepflag == HERMON_SLEEP) ? IBT_MR_SLEEP : 274 IBT_MR_NOSLEEP; 275 mr_attr.mr_vaddr = (uint64_t)(uintptr_t)buf; 276 mr_attr.mr_len = srq->srq_wqinfo.qa_size; 277 mr_attr.mr_as = NULL; 278 mr_attr.mr_flags = flag | IBT_MR_ENABLE_LOCAL_WRITE; 279 mr_op.mro_bind_type = state->hs_cfg_profile->cp_iommu_bypass; 280 mr_op.mro_bind_dmahdl = srq->srq_wqinfo.qa_dmahdl; 281 mr_op.mro_bind_override_addr = 1; 282 status = hermon_mr_register(state, pd, &mr_attr, &mr, 283 &mr_op, HERMON_SRQ_CMPT); 284 if (status != DDI_SUCCESS) { 285 status = IBT_INSUFF_RESOURCE; 286 goto srqalloc_fail5; 287 } 288 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr)) 289 290 /* 291 * Calculate the offset between the kernel virtual address space 292 * and the IB virtual address space. This will be used when 293 * posting work requests to properly initialize each WQE. 294 */ 295 srq_desc_off = (uint64_t)(uintptr_t)srq->srq_wqinfo.qa_buf_aligned - 296 (uint64_t)mr->mr_bindinfo.bi_addr; 297 298 srq->srq_wq_wqhdr = hermon_wrid_wqhdr_create(1 << log_srq_size); 299 300 /* 301 * Fill in all the return arguments (if necessary). This includes 302 * real queue size and real SGLs. 303 */ 304 if (real_sizes != NULL) { 305 real_sizes->srq_wr_sz = (1 << log_srq_size) - 1; 306 real_sizes->srq_sgl_sz = srq->srq_wq_sgl; 307 } 308 309 /* 310 * Fill in the SRQC entry. This is the final step before passing 311 * ownership of the SRQC entry to the Hermon hardware. We use all of 312 * the information collected/calculated above to fill in the 313 * requisite portions of the SRQC. Note: If this SRQ is going to be 314 * used for userland access, then we need to set the UAR page number 315 * appropriately (otherwise it's a "don't care") 316 */ 317 bzero(&srqc_entry, sizeof (hermon_hw_srqc_t)); 318 srqc_entry.state = HERMON_SRQ_STATE_HW_OWNER; 319 srqc_entry.log_srq_size = log_srq_size; 320 srqc_entry.srqn = srq->srq_srqnum; 321 srqc_entry.log_rq_stride = srq->srq_wq_log_wqesz - 4; 322 /* 16-byte chunks */ 323 324 srqc_entry.page_offs = srq->srq_wqinfo.qa_pgoffs >> 6; 325 srqc_entry.log2_pgsz = mr->mr_log2_pgsz; 326 srqc_entry.mtt_base_addrh = (uint32_t)((mr->mr_mttaddr >> 32) & 0xFF); 327 srqc_entry.mtt_base_addrl = mr->mr_mttaddr >> 3; 328 srqc_entry.pd = pd->pd_pdnum; 329 srqc_entry.dbr_addrh = (uint32_t)((uint64_t)srq->srq_wq_pdbr >> 32); 330 srqc_entry.dbr_addrl = (uint32_t)((uint64_t)srq->srq_wq_pdbr >> 2); 331 332 /* 333 * all others - specifically, xrcd, cqn_xrc, lwm, wqe_cnt, and wqe_cntr 334 * are zero thanks to the bzero of the structure 335 */ 336 337 /* 338 * Write the SRQC entry to hardware. Lastly, we pass ownership of 339 * the entry to the hardware (using the Hermon SW2HW_SRQ firmware 340 * command). Note: In general, this operation shouldn't fail. But 341 * if it does, we have to undo everything we've done above before 342 * returning error. 343 */ 344 status = hermon_cmn_ownership_cmd_post(state, SW2HW_SRQ, &srqc_entry, 345 sizeof (hermon_hw_srqc_t), srq->srq_srqnum, 346 sleepflag); 347 if (status != HERMON_CMD_SUCCESS) { 348 cmn_err(CE_CONT, "Hermon: SW2HW_SRQ command failed: %08x\n", 349 status); 350 if (status == HERMON_CMD_INVALID_STATUS) { 351 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST); 352 } 353 status = ibc_get_ci_failure(0); 354 goto srqalloc_fail8; 355 } 356 357 /* 358 * Fill in the rest of the Hermon SRQ handle. We can update 359 * the following fields for use in further operations on the SRQ. 360 */ 361 srq->srq_srqcrsrcp = srqc; 362 srq->srq_rsrcp = rsrc; 363 srq->srq_mrhdl = mr; 364 srq->srq_refcnt = 0; 365 srq->srq_is_umap = srq_is_umap; 366 srq->srq_uarpg = uarpg; 367 srq->srq_umap_dhp = (devmap_cookie_t)NULL; 368 srq->srq_pdhdl = pd; 369 srq->srq_wq_bufsz = (1 << log_srq_size); 370 srq->srq_wq_buf = buf; 371 srq->srq_desc_off = srq_desc_off; 372 srq->srq_hdlrarg = (void *)ibt_srqhdl; 373 srq->srq_state = 0; 374 srq->srq_real_sizes.srq_wr_sz = (1 << log_srq_size); 375 srq->srq_real_sizes.srq_sgl_sz = srq->srq_wq_sgl; 376 377 /* 378 * Put SRQ handle in Hermon SRQNum-to-SRQhdl list. Then fill in the 379 * "srqhdl" and return success 380 */ 381 hermon_icm_set_num_to_hdl(state, HERMON_SRQC, srqc->hr_indx, srq); 382 383 /* 384 * If this is a user-mappable SRQ, then we need to insert the 385 * previously allocated entry into the "userland resources database". 386 * This will allow for later lookup during devmap() (i.e. mmap()) 387 * calls. 388 */ 389 if (srq->srq_is_umap) { 390 hermon_umap_db_add(umapdb); 391 } else { /* initialize work queue for kernel SRQs */ 392 int i, len, last; 393 uint16_t *desc; 394 395 desc = (uint16_t *)buf; 396 len = wqesz / sizeof (*desc); 397 last = srq->srq_wq_bufsz - 1; 398 for (i = 0; i < last; i++) { 399 desc[1] = htons(i + 1); 400 desc += len; 401 } 402 srq->srq_wq_wqhdr->wq_tail = last; 403 srq->srq_wq_wqhdr->wq_head = 0; 404 } 405 406 *srqhdl = srq; 407 408 return (status); 409 410 /* 411 * The following is cleanup for all possible failure cases in this routine 412 */ 413 srqalloc_fail8: 414 hermon_wrid_wqhdr_destroy(srq->srq_wq_wqhdr); 415 srqalloc_fail7: 416 if (hermon_mr_deregister(state, &mr, HERMON_MR_DEREG_ALL, 417 HERMON_SLEEPFLAG_FOR_CONTEXT()) != DDI_SUCCESS) { 418 HERMON_WARNING(state, "failed to deregister SRQ memory"); 419 } 420 srqalloc_fail5: 421 hermon_queue_free(&srq->srq_wqinfo); 422 srqalloc_fail4a: 423 hermon_dbr_free(state, uarpg, srq->srq_wq_vdbr); 424 srqalloc_fail4: 425 if (srq_is_umap) { 426 hermon_umap_db_free(umapdb); 427 } 428 srqalloc_fail3: 429 hermon_rsrc_free(state, &rsrc); 430 srqalloc_fail2: 431 hermon_rsrc_free(state, &srqc); 432 srqalloc_fail1: 433 hermon_pd_refcnt_dec(pd); 434 srqalloc_fail: 435 return (status); 436 } 437 438 439 /* 440 * hermon_srq_free() 441 * Context: Can be called only from user or kernel context. 442 */ 443 /* ARGSUSED */ 444 int 445 hermon_srq_free(hermon_state_t *state, hermon_srqhdl_t *srqhdl, 446 uint_t sleepflag) 447 { 448 hermon_rsrc_t *srqc, *rsrc; 449 hermon_umap_db_entry_t *umapdb; 450 uint64_t value; 451 hermon_srqhdl_t srq; 452 hermon_mrhdl_t mr; 453 hermon_pdhdl_t pd; 454 hermon_hw_srqc_t srqc_entry; 455 uint32_t srqnum; 456 uint_t maxprot; 457 int status; 458 459 /* 460 * Pull all the necessary information from the Hermon Shared Receive 461 * Queue handle. This is necessary here because the resource for the 462 * SRQ handle is going to be freed up as part of this operation. 463 */ 464 srq = *srqhdl; 465 mutex_enter(&srq->srq_lock); 466 srqc = srq->srq_srqcrsrcp; 467 rsrc = srq->srq_rsrcp; 468 pd = srq->srq_pdhdl; 469 mr = srq->srq_mrhdl; 470 srqnum = srq->srq_srqnum; 471 472 /* 473 * If there are work queues still associated with the SRQ, then return 474 * an error. Otherwise, we will be holding the SRQ lock. 475 */ 476 if (srq->srq_refcnt != 0) { 477 mutex_exit(&srq->srq_lock); 478 return (IBT_SRQ_IN_USE); 479 } 480 481 /* 482 * If this was a user-mappable SRQ, then we need to remove its entry 483 * from the "userland resources database". If it is also currently 484 * mmap()'d out to a user process, then we need to call 485 * devmap_devmem_remap() to remap the SRQ memory to an invalid mapping. 486 * We also need to invalidate the SRQ tracking information for the 487 * user mapping. 488 */ 489 if (srq->srq_is_umap) { 490 status = hermon_umap_db_find(state->hs_instance, 491 srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC, &value, 492 HERMON_UMAP_DB_REMOVE, &umapdb); 493 if (status != DDI_SUCCESS) { 494 mutex_exit(&srq->srq_lock); 495 HERMON_WARNING(state, "failed to find in database"); 496 return (ibc_get_ci_failure(0)); 497 } 498 hermon_umap_db_free(umapdb); 499 if (srq->srq_umap_dhp != NULL) { 500 maxprot = (PROT_READ | PROT_WRITE | PROT_USER); 501 status = devmap_devmem_remap(srq->srq_umap_dhp, 502 state->hs_dip, 0, 0, srq->srq_wqinfo.qa_size, 503 maxprot, DEVMAP_MAPPING_INVALID, NULL); 504 if (status != DDI_SUCCESS) { 505 mutex_exit(&srq->srq_lock); 506 HERMON_WARNING(state, "failed in SRQ memory " 507 "devmap_devmem_remap()"); 508 return (ibc_get_ci_failure(0)); 509 } 510 srq->srq_umap_dhp = (devmap_cookie_t)NULL; 511 } 512 } 513 514 /* 515 * Put NULL into the Hermon SRQNum-to-SRQHdl list. This will allow any 516 * in-progress events to detect that the SRQ corresponding to this 517 * number has been freed. 518 */ 519 hermon_icm_set_num_to_hdl(state, HERMON_SRQC, srqc->hr_indx, NULL); 520 521 mutex_exit(&srq->srq_lock); 522 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq)); 523 524 /* 525 * Reclaim SRQC entry from hardware (using the Hermon HW2SW_SRQ 526 * firmware command). If the ownership transfer fails for any reason, 527 * then it is an indication that something (either in HW or SW) has 528 * gone seriously wrong. 529 */ 530 status = hermon_cmn_ownership_cmd_post(state, HW2SW_SRQ, &srqc_entry, 531 sizeof (hermon_hw_srqc_t), srqnum, sleepflag); 532 if (status != HERMON_CMD_SUCCESS) { 533 HERMON_WARNING(state, "failed to reclaim SRQC ownership"); 534 cmn_err(CE_CONT, "Hermon: HW2SW_SRQ command failed: %08x\n", 535 status); 536 if (status == HERMON_CMD_INVALID_STATUS) { 537 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST); 538 } 539 return (ibc_get_ci_failure(0)); 540 } 541 542 /* 543 * Deregister the memory for the Shared Receive Queue. If this fails 544 * for any reason, then it is an indication that something (either 545 * in HW or SW) has gone seriously wrong. So we print a warning 546 * message and return. 547 */ 548 status = hermon_mr_deregister(state, &mr, HERMON_MR_DEREG_ALL, 549 sleepflag); 550 if (status != DDI_SUCCESS) { 551 HERMON_WARNING(state, "failed to deregister SRQ memory"); 552 return (IBT_FAILURE); 553 } 554 555 hermon_wrid_wqhdr_destroy(srq->srq_wq_wqhdr); 556 557 /* Free the memory for the SRQ */ 558 hermon_queue_free(&srq->srq_wqinfo); 559 560 /* Free the dbr */ 561 hermon_dbr_free(state, srq->srq_uarpg, srq->srq_wq_vdbr); 562 563 /* Free the Hermon SRQ Handle */ 564 hermon_rsrc_free(state, &rsrc); 565 566 /* Free the SRQC entry resource */ 567 hermon_rsrc_free(state, &srqc); 568 569 /* Decrement the reference count on the protection domain (PD) */ 570 hermon_pd_refcnt_dec(pd); 571 572 /* Set the srqhdl pointer to NULL and return success */ 573 *srqhdl = NULL; 574 575 return (DDI_SUCCESS); 576 } 577 578 579 /* 580 * hermon_srq_modify() 581 * Context: Can be called only from user or kernel context. 582 */ 583 int 584 hermon_srq_modify(hermon_state_t *state, hermon_srqhdl_t srq, uint_t size, 585 uint_t *real_size, uint_t sleepflag) 586 { 587 hermon_qalloc_info_t new_srqinfo, old_srqinfo; 588 hermon_rsrc_t *mtt, *old_mtt; 589 hermon_bind_info_t bind; 590 hermon_bind_info_t old_bind; 591 hermon_mrhdl_t mr; 592 hermon_hw_srqc_t srqc_entry; 593 hermon_hw_dmpt_t mpt_entry; 594 uint64_t *wre_new, *wre_old; 595 uint64_t mtt_addr; 596 uint64_t srq_pgoffs; 597 uint64_t srq_desc_off; 598 uint32_t *buf, srq_old_bufsz; 599 uint32_t wqesz; 600 uint_t max_srq_size; 601 uint_t mtt_pgsize_bits; 602 uint_t log_srq_size, maxprot; 603 int status; 604 605 if ((state->hs_devlim.mod_wr_srq == 0) || 606 (state->hs_cfg_profile->cp_srq_resize_enabled == 0)) 607 return (IBT_NOT_SUPPORTED); 608 609 /* 610 * If size requested is larger than device capability, return 611 * Insufficient Resources 612 */ 613 max_srq_size = (1 << state->hs_cfg_profile->cp_log_max_srq_sz); 614 if (size > max_srq_size) { 615 return (IBT_HCA_WR_EXCEEDED); 616 } 617 618 /* 619 * Calculate the appropriate size for the SRQ. 620 * Note: All Hermon SRQs must be a power-of-2 in size. Also 621 * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step 622 * is to round the requested size up to the next highest power-of-2 623 */ 624 size = max(size, HERMON_SRQ_MIN_SIZE); 625 log_srq_size = highbit(size); 626 if ((size & (size - 1)) == 0) { 627 log_srq_size = log_srq_size - 1; 628 } 629 630 /* 631 * Next we verify that the rounded-up size is valid (i.e. consistent 632 * with the device limits and/or software-configured limits). 633 */ 634 if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) { 635 status = IBT_HCA_WR_EXCEEDED; 636 goto srqmodify_fail; 637 } 638 639 /* 640 * Allocate the memory for newly resized Shared Receive Queue. 641 * 642 * Note: If SRQ is not user-mappable, then it may come from either 643 * kernel system memory or from HCA-attached local DDR memory. 644 * 645 * Note2: We align this queue on a pagesize boundary. This is required 646 * to make sure that all the resulting IB addresses will start at 0, 647 * for a zero-based queue. By making sure we are aligned on at least a 648 * page, any offset we use into our queue will be the same as it was 649 * when we allocated it at hermon_srq_alloc() time. 650 */ 651 wqesz = (1 << srq->srq_wq_log_wqesz); 652 new_srqinfo.qa_size = (1 << log_srq_size) * wqesz; 653 new_srqinfo.qa_alloc_align = PAGESIZE; 654 new_srqinfo.qa_bind_align = PAGESIZE; 655 if (srq->srq_is_umap) { 656 new_srqinfo.qa_location = HERMON_QUEUE_LOCATION_USERLAND; 657 } else { 658 new_srqinfo.qa_location = HERMON_QUEUE_LOCATION_NORMAL; 659 } 660 status = hermon_queue_alloc(state, &new_srqinfo, sleepflag); 661 if (status != DDI_SUCCESS) { 662 status = IBT_INSUFF_RESOURCE; 663 goto srqmodify_fail; 664 } 665 buf = (uint32_t *)new_srqinfo.qa_buf_aligned; 666 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*buf)) 667 668 /* 669 * Allocate the memory for the new WRE list. This will be used later 670 * when we resize the wridlist based on the new SRQ size. 671 */ 672 wre_new = kmem_zalloc((1 << log_srq_size) * sizeof (uint64_t), 673 sleepflag); 674 if (wre_new == NULL) { 675 status = IBT_INSUFF_RESOURCE; 676 goto srqmodify_fail; 677 } 678 679 /* 680 * Fill in the "bind" struct. This struct provides the majority 681 * of the information that will be used to distinguish between an 682 * "addr" binding (as is the case here) and a "buf" binding (see 683 * below). The "bind" struct is later passed to hermon_mr_mem_bind() 684 * which does most of the "heavy lifting" for the Hermon memory 685 * registration routines. 686 */ 687 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(bind)) 688 bzero(&bind, sizeof (hermon_bind_info_t)); 689 bind.bi_type = HERMON_BINDHDL_VADDR; 690 bind.bi_addr = (uint64_t)(uintptr_t)buf; 691 bind.bi_len = new_srqinfo.qa_size; 692 bind.bi_as = NULL; 693 bind.bi_flags = sleepflag == HERMON_SLEEP ? IBT_MR_SLEEP : 694 IBT_MR_NOSLEEP | IBT_MR_ENABLE_LOCAL_WRITE; 695 bind.bi_bypass = state->hs_cfg_profile->cp_iommu_bypass; 696 697 status = hermon_mr_mtt_bind(state, &bind, new_srqinfo.qa_dmahdl, &mtt, 698 &mtt_pgsize_bits, 0); /* no relaxed ordering */ 699 if (status != DDI_SUCCESS) { 700 status = status; 701 kmem_free(wre_new, (1 << log_srq_size) * 702 sizeof (uint64_t)); 703 hermon_queue_free(&new_srqinfo); 704 goto srqmodify_fail; 705 } 706 707 /* 708 * Calculate the offset between the kernel virtual address space 709 * and the IB virtual address space. This will be used when 710 * posting work requests to properly initialize each WQE. 711 * 712 * Note: bind addr is zero-based (from alloc) so we calculate the 713 * correct new offset here. 714 */ 715 bind.bi_addr = bind.bi_addr & ((1 << mtt_pgsize_bits) - 1); 716 srq_desc_off = (uint64_t)(uintptr_t)new_srqinfo.qa_buf_aligned - 717 (uint64_t)bind.bi_addr; 718 srq_pgoffs = (uint_t) 719 ((uintptr_t)new_srqinfo.qa_buf_aligned & HERMON_PAGEOFFSET); 720 721 /* 722 * Fill in the MPT entry. This is the final step before passing 723 * ownership of the MPT entry to the Hermon hardware. We use all of 724 * the information collected/calculated above to fill in the 725 * requisite portions of the MPT. 726 */ 727 bzero(&mpt_entry, sizeof (hermon_hw_dmpt_t)); 728 mpt_entry.reg_win_len = bind.bi_len; 729 mtt_addr = (mtt->hr_indx << HERMON_MTT_SIZE_SHIFT); 730 mpt_entry.mtt_addr_h = mtt_addr >> 32; 731 mpt_entry.mtt_addr_l = mtt_addr >> 3; 732 733 /* 734 * for hermon we build up a new srqc and pass that (partially filled 735 * to resize SRQ instead of modifying the (d)mpt directly 736 */ 737 738 739 740 /* 741 * Now we grab the SRQ lock. Since we will be updating the actual 742 * SRQ location and the producer/consumer indexes, we should hold 743 * the lock. 744 * 745 * We do a HERMON_NOSLEEP here (and below), though, because we are 746 * holding the "srq_lock" and if we got raised to interrupt level 747 * by priority inversion, we would not want to block in this routine 748 * waiting for success. 749 */ 750 mutex_enter(&srq->srq_lock); 751 752 /* 753 * Copy old entries to new buffer 754 */ 755 srq_old_bufsz = srq->srq_wq_bufsz; 756 bcopy(srq->srq_wq_buf, buf, srq_old_bufsz * wqesz); 757 758 /* 759 * Setup MPT information for use in the MODIFY_MPT command 760 */ 761 mr = srq->srq_mrhdl; 762 mutex_enter(&mr->mr_lock); 763 764 /* 765 * now, setup the srqc information needed for resize - limit the 766 * values, but use the same structure as the srqc 767 */ 768 769 srqc_entry.log_srq_size = log_srq_size; 770 srqc_entry.page_offs = srq_pgoffs >> 6; 771 srqc_entry.log2_pgsz = mr->mr_log2_pgsz; 772 srqc_entry.mtt_base_addrl = (uint64_t)mtt_addr >> 32; 773 srqc_entry.mtt_base_addrh = mtt_addr >> 3; 774 775 /* 776 * RESIZE_SRQ 777 * 778 * If this fails for any reason, then it is an indication that 779 * something (either in HW or SW) has gone seriously wrong. So we 780 * print a warning message and return. 781 */ 782 status = hermon_resize_srq_cmd_post(state, &srqc_entry, 783 srq->srq_srqnum, sleepflag); 784 if (status != HERMON_CMD_SUCCESS) { 785 cmn_err(CE_CONT, "Hermon: RESIZE_SRQ command failed: %08x\n", 786 status); 787 if (status == HERMON_CMD_INVALID_STATUS) { 788 hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST); 789 } 790 (void) hermon_mr_mtt_unbind(state, &bind, mtt); 791 kmem_free(wre_new, (1 << log_srq_size) * 792 sizeof (uint64_t)); 793 hermon_queue_free(&new_srqinfo); 794 mutex_exit(&mr->mr_lock); 795 mutex_exit(&srq->srq_lock); 796 return (ibc_get_ci_failure(0)); 797 } 798 /* 799 * Update the Hermon Shared Receive Queue handle with all the new 800 * information. At the same time, save away all the necessary 801 * information for freeing up the old resources 802 */ 803 old_srqinfo = srq->srq_wqinfo; 804 old_mtt = srq->srq_mrhdl->mr_mttrsrcp; 805 bcopy(&srq->srq_mrhdl->mr_bindinfo, &old_bind, 806 sizeof (hermon_bind_info_t)); 807 808 /* Now set the new info */ 809 srq->srq_wqinfo = new_srqinfo; 810 srq->srq_wq_buf = buf; 811 srq->srq_wq_bufsz = (1 << log_srq_size); 812 bcopy(&bind, &srq->srq_mrhdl->mr_bindinfo, sizeof (hermon_bind_info_t)); 813 srq->srq_mrhdl->mr_mttrsrcp = mtt; 814 srq->srq_desc_off = srq_desc_off; 815 srq->srq_real_sizes.srq_wr_sz = (1 << log_srq_size); 816 817 /* Update MR mtt pagesize */ 818 mr->mr_logmttpgsz = mtt_pgsize_bits; 819 mutex_exit(&mr->mr_lock); 820 821 /* 822 * Initialize new wridlist, if needed. 823 * 824 * If a wridlist already is setup on an SRQ (the QP associated with an 825 * SRQ has moved "from_reset") then we must update this wridlist based 826 * on the new SRQ size. We allocate the new size of Work Request ID 827 * Entries, copy over the old entries to the new list, and 828 * re-initialize the srq wridlist in non-umap case 829 */ 830 wre_old = srq->srq_wq_wqhdr->wq_wrid; 831 832 bcopy(wre_old, wre_new, srq_old_bufsz * sizeof (uint64_t)); 833 834 /* Setup new sizes in wre */ 835 srq->srq_wq_wqhdr->wq_wrid = wre_new; 836 837 /* 838 * If "old" SRQ was a user-mappable SRQ that is currently mmap()'d out 839 * to a user process, then we need to call devmap_devmem_remap() to 840 * invalidate the mapping to the SRQ memory. We also need to 841 * invalidate the SRQ tracking information for the user mapping. 842 * 843 * Note: On failure, the remap really shouldn't ever happen. So, if it 844 * does, it is an indication that something has gone seriously wrong. 845 * So we print a warning message and return error (knowing, of course, 846 * that the "old" SRQ memory will be leaked) 847 */ 848 if ((srq->srq_is_umap) && (srq->srq_umap_dhp != NULL)) { 849 maxprot = (PROT_READ | PROT_WRITE | PROT_USER); 850 status = devmap_devmem_remap(srq->srq_umap_dhp, 851 state->hs_dip, 0, 0, srq->srq_wqinfo.qa_size, maxprot, 852 DEVMAP_MAPPING_INVALID, NULL); 853 if (status != DDI_SUCCESS) { 854 mutex_exit(&srq->srq_lock); 855 HERMON_WARNING(state, "failed in SRQ memory " 856 "devmap_devmem_remap()"); 857 /* We can, however, free the memory for old wre */ 858 kmem_free(wre_old, srq_old_bufsz * sizeof (uint64_t)); 859 return (ibc_get_ci_failure(0)); 860 } 861 srq->srq_umap_dhp = (devmap_cookie_t)NULL; 862 } 863 864 /* 865 * Drop the SRQ lock now. The only thing left to do is to free up 866 * the old resources. 867 */ 868 mutex_exit(&srq->srq_lock); 869 870 /* 871 * Unbind the MTT entries. 872 */ 873 status = hermon_mr_mtt_unbind(state, &old_bind, old_mtt); 874 if (status != DDI_SUCCESS) { 875 HERMON_WARNING(state, "failed to unbind old SRQ memory"); 876 status = ibc_get_ci_failure(0); 877 goto srqmodify_fail; 878 } 879 880 /* Free the memory for old wre */ 881 kmem_free(wre_old, srq_old_bufsz * sizeof (uint64_t)); 882 883 /* Free the memory for the old SRQ */ 884 hermon_queue_free(&old_srqinfo); 885 886 /* 887 * Fill in the return arguments (if necessary). This includes the 888 * real new completion queue size. 889 */ 890 if (real_size != NULL) { 891 *real_size = (1 << log_srq_size); 892 } 893 894 return (DDI_SUCCESS); 895 896 srqmodify_fail: 897 return (status); 898 } 899 900 901 /* 902 * hermon_srq_refcnt_inc() 903 * Context: Can be called from interrupt or base context. 904 */ 905 void 906 hermon_srq_refcnt_inc(hermon_srqhdl_t srq) 907 { 908 mutex_enter(&srq->srq_lock); 909 srq->srq_refcnt++; 910 mutex_exit(&srq->srq_lock); 911 } 912 913 914 /* 915 * hermon_srq_refcnt_dec() 916 * Context: Can be called from interrupt or base context. 917 */ 918 void 919 hermon_srq_refcnt_dec(hermon_srqhdl_t srq) 920 { 921 mutex_enter(&srq->srq_lock); 922 srq->srq_refcnt--; 923 mutex_exit(&srq->srq_lock); 924 } 925 926 927 /* 928 * hermon_srqhdl_from_srqnum() 929 * Context: Can be called from interrupt or base context. 930 * 931 * This routine is important because changing the unconstrained 932 * portion of the SRQ number is critical to the detection of a 933 * potential race condition in the SRQ handler code (i.e. the case 934 * where a SRQ is freed and alloc'd again before an event for the 935 * "old" SRQ can be handled). 936 * 937 * While this is not a perfect solution (not sure that one exists) 938 * it does help to mitigate the chance that this race condition will 939 * cause us to deliver a "stale" event to the new SRQ owner. Note: 940 * this solution does not scale well because the number of constrained 941 * bits increases (and, hence, the number of unconstrained bits 942 * decreases) as the number of supported SRQ grows. For small and 943 * intermediate values, it should hopefully provide sufficient 944 * protection. 945 */ 946 hermon_srqhdl_t 947 hermon_srqhdl_from_srqnum(hermon_state_t *state, uint_t srqnum) 948 { 949 uint_t srqindx, srqmask; 950 951 /* Calculate the SRQ table index from the srqnum */ 952 srqmask = (1 << state->hs_cfg_profile->cp_log_num_srq) - 1; 953 srqindx = srqnum & srqmask; 954 return (hermon_icm_num_to_hdl(state, HERMON_SRQC, srqindx)); 955 } 956 957 958 /* 959 * hermon_srq_sgl_to_logwqesz() 960 * Context: Can be called from interrupt or base context. 961 */ 962 static void 963 hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl, 964 hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl) 965 { 966 uint_t max_size, log2, actual_sgl; 967 968 switch (wq_type) { 969 case HERMON_QP_WQ_TYPE_RECVQ: 970 /* 971 * Use requested maximum SGL to calculate max descriptor size 972 * (while guaranteeing that the descriptor size is a 973 * power-of-2 cachelines). 974 */ 975 max_size = (HERMON_QP_WQE_MLX_SRQ_HDRS + (num_sgl << 4)); 976 log2 = highbit(max_size); 977 if ((max_size & (max_size - 1)) == 0) { 978 log2 = log2 - 1; 979 } 980 981 /* Make sure descriptor is at least the minimum size */ 982 log2 = max(log2, HERMON_QP_WQE_LOG_MINIMUM); 983 984 /* Calculate actual number of SGL (given WQE size) */ 985 actual_sgl = ((1 << log2) - HERMON_QP_WQE_MLX_SRQ_HDRS) >> 4; 986 break; 987 988 default: 989 HERMON_WARNING(state, "unexpected work queue type"); 990 break; 991 } 992 993 /* Fill in the return values */ 994 *logwqesz = log2; 995 *max_sgl = min(state->hs_cfg_profile->cp_srq_max_sgl, actual_sgl); 996 } --- EOF ---