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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * 29 * MODULE: dapl_srq.c 30 * 31 * PURPOSE: Shared Receive Queue 32 * Description: Interfaces in this file are completely described in 33 * the DAPL 1.2 API, Chapter 6, section 5 34 * 35 */ 36 37 #include "dapl.h" 38 #include "dapl_adapter_util.h" 39 #include "dapl_ia_util.h" 40 #include "dapl_srq_util.h" 41 #include "dapl_cookie.h" 42 43 /* 44 * dapl_srq_create 45 * 46 * uDAPL: User Direct Access Program Library Version 1.2, 6.5.1 47 * 48 * creates an instance of a Shared Receive Queue (SRQ) that is provided 49 * to the Consumer as srq_handle. 50 * 51 * Input: 52 * ia_handle 53 * pz_handle 54 * srq_attr 55 * 56 * Output: 57 * srq_handle 58 * 59 * Returns: 60 * DAT_SUCCESS 61 * DAT_INSUFFICIENT_RESOURCES 62 * DAT_INVALID_HANDLE 63 * DAT_INVALID_PARAMETER 64 * DAT_MODEL_NOT_SUPPORTED 65 */ 66 67 DAT_RETURN 68 dapl_srq_create( 69 IN DAT_IA_HANDLE ia_handle, 70 IN DAT_PZ_HANDLE pz_handle, 71 IN DAT_SRQ_ATTR *srq_attr, 72 OUT DAT_SRQ_HANDLE *srq_handle) 73 { 74 DAPL_IA *ia_ptr; 75 DAPL_SRQ *srq_ptr; 76 DAT_SRQ_ATTR srq_attr_limit; 77 DAT_RETURN dat_status; 78 79 ia_ptr = (DAPL_IA *)ia_handle; 80 dat_status = DAT_SUCCESS; 81 /* 82 * Verify parameters 83 */ 84 if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) { 85 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 86 DAT_INVALID_HANDLE_IA); 87 goto bail; 88 } 89 90 if ((pz_handle == NULL) || DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) { 91 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 92 DAT_INVALID_HANDLE_PZ); 93 goto bail; 94 } 95 96 if ((srq_attr == NULL) || ((uintptr_t)srq_attr & 3)) { 97 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); 98 goto bail; 99 } 100 101 if (srq_handle == NULL) { 102 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); 103 goto bail; 104 } 105 106 if (srq_attr->max_recv_dtos == 0 || srq_attr->max_recv_iov == 0 || 107 srq_attr->low_watermark != DAT_SRQ_LW_DEFAULT) { 108 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); 109 goto bail; 110 } 111 112 /* Verify the attributes against the transport */ 113 (void) dapl_os_memzero(&srq_attr_limit, sizeof (DAT_SRQ_ATTR)); 114 dat_status = dapls_ib_query_hca(ia_ptr->hca_ptr, NULL, NULL, NULL, 115 &srq_attr_limit); 116 if (dat_status != DAT_SUCCESS) { 117 goto bail; 118 } 119 if (srq_attr->max_recv_dtos > srq_attr_limit.max_recv_dtos || 120 srq_attr->max_recv_iov > srq_attr_limit.max_recv_iov) { 121 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); 122 goto bail; 123 } 124 125 /* Allocate SRQ */ 126 srq_ptr = dapl_srq_alloc(ia_ptr, srq_attr); 127 if (srq_ptr == NULL) { 128 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 129 DAT_RESOURCE_MEMORY); 130 goto bail; 131 } 132 133 /* Take a reference on the PZ handle */ 134 dapl_os_atomic_inc(&((DAPL_PZ *)pz_handle)->pz_ref_count); 135 136 /* 137 * Fill in the SRQ 138 */ 139 srq_ptr->param.ia_handle = ia_handle; 140 srq_ptr->param.srq_state = DAT_SRQ_STATE_OPERATIONAL; 141 srq_ptr->param.pz_handle = pz_handle; 142 srq_ptr->param.max_recv_dtos = srq_attr->max_recv_dtos; 143 srq_ptr->param.max_recv_iov = srq_attr->max_recv_iov; 144 srq_ptr->param.low_watermark = DAT_SRQ_LW_DEFAULT; 145 146 srq_ptr->param.available_dto_count = DAT_VALUE_UNKNOWN; 147 srq_ptr->param.outstanding_dto_count = 0; 148 149 dat_status = dapls_ib_srq_alloc(ia_ptr, srq_ptr); 150 if (dat_status != DAT_SUCCESS) { 151 dapl_os_atomic_dec(&((DAPL_PZ *)pz_handle)->pz_ref_count); 152 dapl_srq_dealloc(srq_ptr); 153 goto bail; 154 } 155 /* Link it onto the IA */ 156 dapl_ia_link_srq(ia_ptr, srq_ptr); 157 158 *srq_handle = srq_ptr; 159 bail: 160 return (dat_status); 161 } 162 163 /* 164 * dapl_srq_free 165 * 166 * uDAPL: User Direct Access Program Library Version 1.2, 6.5.5 167 * 168 * destroys an instance of the SRQ. The SRQ cannot be destroyed if it is 169 * in use by an EP. 170 * 171 * Input: 172 * srq_handle 173 * 174 * Output: 175 * none 176 * 177 * Returns: 178 * DAT_SUCCESS 179 * DAT_INVALID_HANDLE 180 * DAT_INVALID_STATE 181 */ 182 183 DAT_RETURN 184 dapl_srq_free( 185 IN DAT_SRQ_HANDLE srq_handle) 186 { 187 DAPL_SRQ *srq_ptr; 188 DAPL_IA *ia_ptr; 189 DAT_SRQ_PARAM *param; 190 DAT_RETURN dat_status = DAT_SUCCESS; 191 192 if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) { 193 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 194 DAT_INVALID_HANDLE_SRQ); 195 goto bail; 196 } 197 198 srq_ptr = (DAPL_SRQ *)srq_handle; 199 param = &srq_ptr->param; 200 if (0 != srq_ptr->srq_ref_count) { 201 dapl_dbg_log(DAPL_DBG_TYPE_EP, 202 "dapl_srq_free: Free SRQ: %p, refcnt %d\n", 203 srq_ptr, srq_ptr->srq_ref_count); 204 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 205 DAT_INVALID_STATE_SRQ_IN_USE); 206 goto bail; 207 } 208 209 ia_ptr = srq_ptr->header.owner_ia; 210 param->srq_state = DAT_SRQ_STATE_ERROR; 211 212 dapls_ib_srq_free(ia_ptr, srq_ptr); 213 214 /* Remove link from the IA */ 215 dapl_ia_unlink_srq(ia_ptr, srq_ptr); 216 217 dapl_os_assert(param->pz_handle != NULL); 218 dapl_os_atomic_dec(&((DAPL_PZ *)param->pz_handle)->pz_ref_count); 219 param->pz_handle = NULL; 220 221 dapl_srq_dealloc(srq_ptr); 222 223 bail: 224 return (dat_status); 225 } 226 227 /* 228 * dapl_srq_post_recv 229 * 230 * uDAPL: User Direct Access Program Library Version 1.2, 6.5.8 231 * 232 * posts the receive buffer that can be used for the incoming message into 233 * the local_iov by any connected EP that uses SRQ. 234 * 235 * Input: 236 * srq_handle 237 * num_segments 238 * local_iov 239 * user_cookie 240 * 241 * Output: 242 * none 243 * 244 * Returns: 245 * DAT_SUCCESS 246 * DAT_INVALID_HANDLE 247 * DAT_INSUFFICIENT_RESOURCES 248 * DAT_INVALID_PARAMETER 249 * DAT_PROTECTION_VIOLATION 250 * DAT_PRIVILEGES_VIOLATION 251 */ 252 253 DAT_RETURN 254 dapl_srq_post_recv( 255 IN DAT_SRQ_HANDLE srq_handle, 256 IN DAT_COUNT num_segments, 257 IN DAT_LMR_TRIPLET *local_iov, 258 IN DAT_DTO_COOKIE user_cookie) 259 { 260 DAPL_SRQ *srq_ptr; 261 DAPL_COOKIE *cookie; 262 DAT_RETURN dat_status; 263 264 dapl_dbg_log(DAPL_DBG_TYPE_API, 265 "dapl_srq_post_recv (%p, %d, %p, %P)\n", 266 srq_handle, 267 num_segments, 268 local_iov, 269 user_cookie.as_64); 270 271 if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) { 272 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 273 DAT_INVALID_HANDLE_SRQ); 274 goto bail; 275 } 276 277 srq_ptr = (DAPL_SRQ *) srq_handle; 278 279 /* 280 * Synchronization ok since this buffer is only used for receive 281 * requests, which aren't allowed to race with each other. 282 */ 283 dat_status = dapls_dto_cookie_alloc(&srq_ptr->recv_buffer, 284 DAPL_DTO_TYPE_RECV, 285 user_cookie, 286 &cookie); 287 if (DAT_SUCCESS != dat_status) { 288 goto bail; 289 } 290 291 /* 292 * Invoke provider specific routine to post DTO 293 */ 294 dat_status = dapls_ib_post_srq(srq_ptr, cookie, num_segments, 295 local_iov); 296 297 if (dat_status != DAT_SUCCESS) { 298 dapls_cookie_dealloc(&srq_ptr->recv_buffer, cookie); 299 } else { 300 dapl_os_atomic_inc(&srq_ptr->recv_count); 301 } 302 303 bail: 304 dapl_dbg_log(DAPL_DBG_TYPE_RTN, 305 "dapl_srq_post_recv () returns 0x%x\n", dat_status); 306 307 return (dat_status); 308 } 309 310 311 /* 312 * dapl_srq_query 313 * 314 * uDAPL: User Direct Access Program Library Version 1.2, 6.5.6 315 * 316 * provides to the Consumer SRQ parameters. The Consumer passes in a pointer 317 * to the Consumer-allocated structures for SRQ parameters that the Provider 318 * fills. 319 * 320 * Input: 321 * srq_handle 322 * srq_param_mask 323 * 324 * Output: 325 * srq_param 326 * 327 * Returns: 328 * DAT_SUCCESS 329 * DAT_INVALID_HANDLE 330 * DAT_INVALID_PARAMETER 331 */ 332 333 DAT_RETURN 334 dapl_srq_query( 335 IN DAT_SRQ_HANDLE srq_handle, 336 IN DAT_SRQ_PARAM_MASK srq_param_mask, 337 OUT DAT_SRQ_PARAM *srq_param) 338 { 339 DAPL_SRQ *srq_ptr; 340 DAT_RETURN dat_status; 341 342 dat_status = DAT_SUCCESS; 343 344 if (srq_param_mask & ~DAT_SRQ_FIELD_ALL) { 345 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); 346 goto bail; 347 } 348 349 if (NULL == srq_param) { 350 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); 351 goto bail; 352 } 353 354 355 if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) { 356 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0); 357 goto bail; 358 } 359 360 srq_ptr = (DAPL_SRQ *)srq_handle; 361 /* Do a struct copy */ 362 *srq_param = srq_ptr->param; 363 /* update the outstanding dto count */ 364 srq_param->outstanding_dto_count = srq_ptr->recv_count; 365 366 bail: 367 return (dat_status); 368 } 369 370 /* 371 * dapl_srq_set_lw 372 * 373 * uDAPL: User Direct Access Program Library Version 1.2, 6.5.4 374 * 375 * sets the low watermark value for SRQ and arms SRQ for generating an 376 * asynchronous event for low watermark. An asynchronous event will be 377 * generated when the number of buffers on SRQ is below the low watermark 378 * for the first time. This may happen during this call or when an 379 * associated EP takes a buffer from the SRQ. 380 * 381 * Input: 382 * srq_handle 383 * low_watermark 384 * 385 * Output: 386 * none 387 * 388 * Returns: 389 * DAT_SUCCESS 390 * DAT_INVALID_HANDLE 391 * DAT_INVALID_PARAMETER 392 * DAT_MODEL_NOT_SUPPORTED 393 */ 394 395 /* ARGSUSED */ 396 DAT_RETURN 397 dapl_srq_set_lw( 398 IN DAT_SRQ_HANDLE srq_handle, 399 IN DAT_COUNT low_watermark) 400 { 401 return (DAT_MODEL_NOT_SUPPORTED); 402 } 403 404 /* 405 * dapl_srq_resize 406 * 407 * uDAPL: User Direct Access Program Library Version 1.2, 6.5.7 408 * 409 * modifies the size of the queue of SRQ. Resizing of SRQ shall not cause 410 * any incoming messages on any of the EPs that use the SRQ to be lost. 411 * 412 * Input: 413 * srq_handle 414 * srq_max_recv_dto 415 * 416 * Output: 417 * none 418 * 419 * Returns: 420 * DAT_SUCCESS 421 * DAT_INVALID_HANDLE 422 * DAT_INVALID_PARAMETER 423 * DAT_INSUFFICIENT_RESOURCES 424 * DAT_INVALID_STATE 425 */ 426 427 /* ARGSUSED */ 428 DAT_RETURN 429 dapl_srq_resize( 430 IN DAT_SRQ_HANDLE srq_handle, 431 IN DAT_COUNT srq_max_recv_dtos) 432 { 433 DAPL_SRQ *srq_ptr; 434 DAT_SRQ_ATTR srq_attr_limit; 435 DAPL_COOKIE_BUFFER new_cb; 436 DAT_RETURN dat_status; 437 438 439 srq_ptr = (DAPL_SRQ *)srq_handle; 440 dat_status = DAT_SUCCESS; 441 442 if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) { 443 return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_HANDLE_TYPE_SRQ)); 444 } 445 446 /* can't shrink below the number of outstanding recvs */ 447 if (srq_max_recv_dtos < srq_ptr->recv_count) { 448 return (DAT_ERROR(DAT_INVALID_STATE, 0)); 449 } 450 451 /* 452 * shrinking SRQs is not supported on tavor return success without 453 * any modification. 454 */ 455 if (srq_max_recv_dtos <= srq_ptr->param.max_recv_dtos) { 456 return (DAT_SUCCESS); 457 } 458 459 /* Verify the attributes against the transport */ 460 (void) dapl_os_memzero(&srq_attr_limit, sizeof (DAT_SRQ_ATTR)); 461 dat_status = dapls_ib_query_hca(srq_ptr->header.owner_ia->hca_ptr, 462 NULL, NULL, NULL, &srq_attr_limit); 463 if (dat_status != DAT_SUCCESS) { 464 return (dat_status); 465 } 466 467 if (srq_max_recv_dtos > srq_attr_limit.max_recv_dtos) { 468 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); 469 return (dat_status); 470 } 471 472 dat_status = dapls_cb_resize(&srq_ptr->recv_buffer, srq_max_recv_dtos, 473 &new_cb); 474 if (dat_status != DAT_SUCCESS) { 475 return (dat_status); 476 } 477 478 dat_status = dapls_ib_srq_resize(srq_ptr, srq_max_recv_dtos); 479 if (dat_status != DAT_SUCCESS) { 480 goto bail; 481 } 482 483 dapls_cb_free(&srq_ptr->recv_buffer); 484 srq_ptr->recv_buffer = new_cb; /* struct copy */ 485 srq_ptr->param.max_recv_dtos = srq_max_recv_dtos; 486 487 return (DAT_SUCCESS); 488 bail: 489 dapls_cb_free(&new_cb); 490 491 return (dat_status); 492 } 493