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
dapl_srq_create(IN DAT_IA_HANDLE ia_handle,IN DAT_PZ_HANDLE pz_handle,IN DAT_SRQ_ATTR * srq_attr,OUT DAT_SRQ_HANDLE * srq_handle)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
dapl_srq_free(IN DAT_SRQ_HANDLE srq_handle)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
dapl_srq_post_recv(IN DAT_SRQ_HANDLE srq_handle,IN DAT_COUNT num_segments,IN DAT_LMR_TRIPLET * local_iov,IN DAT_DTO_COOKIE user_cookie)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
dapl_srq_query(IN DAT_SRQ_HANDLE srq_handle,IN DAT_SRQ_PARAM_MASK srq_param_mask,OUT DAT_SRQ_PARAM * srq_param)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
dapl_srq_set_lw(IN DAT_SRQ_HANDLE srq_handle,IN DAT_COUNT low_watermark)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
dapl_srq_resize(IN DAT_SRQ_HANDLE srq_handle,IN DAT_COUNT srq_max_recv_dtos)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