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.
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.
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]
23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
33 * MODULE: dapl_cookie.c
35 * PURPOSE: Manage CQE cookie structures
37 * The DAPL spec requires that all a cookies passed to a posting operation
38 * be returned in the operation's corresponding completion.
40 * Implementing this feature is complicated by the user's ability to
41 * suppress event generation for specific operations. When these operations
42 * complete successfully, the provider does not have an easy way to
43 * deallocate resources devoted to storing context data for these operations.
45 * To support this feature, a pool of memory is allocated up front large
46 * enough to hold cookie data for the maximum number of operations possible
49 * Two pieces of information are maintained to manage cookie allocation:
51 * head index : index of next unallocated cookie
52 * tail index : index of last unallocated cookie
54 * Each cookie store its index in this memory pool.
56 * When an event is received, the index stored in the event's cookie will be
57 * used to update the tail. This will implicitly deallocate all of the cookies
58 * "between" the old tail and the new tail.
60 * The implementation relies on the following assumptions:
62 * - there can be only 1 thread in dat_ep_post_send(), dat_ep_post_rdma_write(),
63 * dat_ep_post_rdma_read(), or dat_rmr_bind() at a time, therefore
64 * dapls_cb_get() does not need to be thread safe when manipulating
65 * request data structures.
67 * - there can be only 1 thread in dat_ep_post_recv(), therefore
68 * dapls_cb_get() does not need to be thread safe when manipulating
69 * receive data structures.
71 * - there can be only 1 thread generating completions for a given EP's request
72 * opeartions, therefore dapls_cb_put() does not need to be thread safe when
73 * manipulating request data structures.
75 * - there can be only 1 thread generating completions for a given EP's receive
76 * opeartions therefore dapls_cb_put() does not need to be thread safe when
77 * manipulating receive data structures.
79 * - completions are delivered in order
81 * $Id: dapl_cookie.c,v 1.13 2003/06/16 17:53:32 sjs2 Exp $
84 #include "dapl_cookie.h"
85 #include "dapl_ring_buffer_util.h"
95 DAPL_COOKIE_BUFFER
*buffer
,
96 DAPL_COOKIE
**cookie_ptr
);
100 DAPL_COOKIE_BUFFER
*buffer
,
101 DAPL_COOKIE
*cookie
);
106 * Function Definitions
113 * Given a DAPL_COOKIE_BUFFER, allocate and initialize memory for
114 * the data structure.
117 * buffer pointer to DAPL_COOKIE_BUFFER
118 * ep endpoint to associate with cookies
119 * size number of elements to allocate & manage
126 * DAT_INSUFFICIENT_RESOURCES
131 IN DAPL_COOKIE_BUFFER
*buffer
,
133 IN DAPL_COOKIE_QUEUE_TYPE type
,
140 * allocate one additional entry so that the tail
141 * can always point at an empty location
144 /* round up to multiple of 2 */
151 buffer
->pool
= dapl_os_alloc(size
* sizeof (DAPL_COOKIE
));
152 if (NULL
!= buffer
->pool
) {
153 buffer
->pool_size
= size
;
157 for (i
= 0; i
< size
; i
++) {
158 buffer
->pool
[i
].index
= i
;
159 buffer
->pool
[i
].queue_type
= type
;
160 if (type
== DAPL_COOKIE_QUEUE_EP
) {
161 buffer
->pool
[i
].queue
.ep
= queue
;
163 buffer
->pool
[i
].queue
.srq
= queue
;
167 return (DAT_SUCCESS
);
169 return (DAT_INSUFFICIENT_RESOURCES
);
176 * Given a DAPL_COOKIE_BUFFER, reallocate a larger buffer and initialize
177 * memory for the data structure from an old one
180 * curr_buffer pointer to existing DAPL_COOKIE_BUFFER
181 * new_size new number of elements to allocate & manage,
182 * has to be > current buffer's size
183 * new_buffer pointer to the newly allocated cookie buffer
190 * DAT_INVALID_PARAMETER
191 * DAT_INSUFFICIENT_RESOURCES
196 IN DAPL_COOKIE_BUFFER
*curr_buffer
,
197 IN DAT_COUNT new_size
,
198 IN DAPL_COOKIE_BUFFER
*new_buffer
)
204 DAT_RETURN dat_return
;
206 if (new_size
< curr_buffer
->pool_size
) {
207 return (DAT_ERROR(DAT_INVALID_PARAMETER
, 0));
211 * create a new cookie buffer, the queue type and queue ptr remain the
212 * same as the curr_buffer so use the values from there
214 dat_return
= dapls_cb_create(new_buffer
,
215 curr_buffer
->pool
[0].queue
.ptr
, curr_buffer
->pool
[0].queue_type
,
218 if (dat_return
!= DAT_SUCCESS
) {
222 /* copy all the free cookies to the new buffer */
223 head
= curr_buffer
->head
;
224 tail
= curr_buffer
->tail
;
226 while (head
!= tail
) {
227 new_buffer
->pool
[index
] = curr_buffer
->pool
[head
];
228 head
= (head
+ 1) % curr_buffer
->pool_size
;
231 new_buffer
->head
= 0;
232 new_buffer
->tail
= index
;
234 return (DAT_SUCCESS
);
240 * Free the data structure
243 * buffer pointer to DAPL_COOKIE_BUFFER
254 IN DAPL_COOKIE_BUFFER
*buffer
)
256 if (NULL
!= buffer
->pool
) {
257 dapl_os_free(buffer
->pool
, buffer
->pool_size
*
258 sizeof (DAPL_COOKIE
));
266 * Remove an entry from the buffer
269 * buffer pointer to DAPL_COOKIE_BUFFER
272 * cookie_ptr pointer to pointer to cookie
276 * DAT_INVALID_PARAMETER
277 * DAT_INSUFFICIENT_RESOURCES
282 IN DAPL_COOKIE_BUFFER
*buffer
,
283 OUT DAPL_COOKIE
**cookie_ptr
)
285 DAT_RETURN dat_status
;
288 dapl_os_assert(NULL
!= cookie_ptr
);
290 new_head
= (buffer
->head
+ 1) % buffer
->pool_size
;
292 if (new_head
== buffer
->tail
) {
293 dat_status
= DAT_INSUFFICIENT_RESOURCES
;
296 buffer
->head
= new_head
;
297 *cookie_ptr
= &buffer
->pool
[buffer
->head
];
298 dat_status
= DAT_SUCCESS
;
308 * Add entry(s) to the buffer
311 * buffer pointer to DAPL_COOKIE_BUFFER
312 * cookie pointer to cookie
315 * entry entry removed from the ring buffer
319 * DAT_INSUFFICIENT_EMPTY
324 IN DAPL_COOKIE_BUFFER
*buffer
,
325 IN DAPL_COOKIE
*cookie
)
327 buffer
->tail
= cookie
->index
;
329 return (DAT_SUCCESS
);
333 * dapls_rmr_cookie_alloc
335 * Allocate an RMR Bind cookie
338 * buffer pointer to DAPL_COOKIE_BUFFER
339 * rmr rmr to associate with the cookie
340 * user_cookie user's cookie data
343 * cookie_ptr pointer to pointer to allocated cookie
347 * DAT_INSUFFICIENT_EMPTY
351 dapls_rmr_cookie_alloc(
352 IN DAPL_COOKIE_BUFFER
*buffer
,
354 IN DAT_RMR_COOKIE user_cookie
,
355 OUT DAPL_COOKIE
**cookie_ptr
)
358 DAT_RETURN dat_status
;
360 if (DAT_SUCCESS
!= dapls_cb_get(buffer
, &cookie
)) {
362 dat_status
= DAT_ERROR(DAT_INSUFFICIENT_RESOURCES
,
363 DAT_RESOURCE_MEMORY
);
367 dat_status
= DAT_SUCCESS
;
368 cookie
->type
= DAPL_COOKIE_TYPE_RMR
;
369 cookie
->val
.rmr
.rmr
= rmr
;
370 cookie
->val
.rmr
.cookie
= user_cookie
;
371 *cookie_ptr
= cookie
;
379 * dapls_dto_cookie_alloc
381 * Allocate a DTO cookie
384 * buffer pointer to DAPL_COOKIE_BUFFER
386 * user_cookie user's cookie data
389 * cookie_ptr pointer to pointer to allocated cookie
393 * DAT_INSUFFICIENT_EMPTY
397 dapls_dto_cookie_alloc(
398 IN DAPL_COOKIE_BUFFER
*buffer
,
399 IN DAPL_DTO_TYPE type
,
400 IN DAT_DTO_COOKIE user_cookie
,
401 OUT DAPL_COOKIE
**cookie_ptr
)
405 if (DAT_SUCCESS
!= dapls_cb_get(buffer
, &cookie
)) {
407 return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES
,
408 DAT_RESOURCE_MEMORY
));
410 cookie
->type
= DAPL_COOKIE_TYPE_DTO
;
411 cookie
->val
.dto
.type
= type
;
412 cookie
->val
.dto
.cookie
= user_cookie
;
413 cookie
->val
.dto
.size
= 0;
415 *cookie_ptr
= cookie
;
416 return (DAT_SUCCESS
);
420 dapls_cookie_dealloc(
421 IN DAPL_COOKIE_BUFFER
*buffer
,
422 IN DAPL_COOKIE
*cookie
)
424 buffer
->tail
= cookie
->index
;