Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / lib / udapl / udapl_tavor / common / dapl_cookie.c
blobb81ae621bf9b1beb0992ae3f9abc8b772a6736a2
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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
47 * on an endpoint.
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"
89 * Function Prototypes
93 DAT_RETURN
94 dapls_cb_get(
95 DAPL_COOKIE_BUFFER *buffer,
96 DAPL_COOKIE **cookie_ptr);
98 DAT_RETURN
99 dapls_cb_put(
100 DAPL_COOKIE_BUFFER *buffer,
101 DAPL_COOKIE *cookie);
106 * Function Definitions
111 * dapls_cb_create
113 * Given a DAPL_COOKIE_BUFFER, allocate and initialize memory for
114 * the data structure.
116 * Input:
117 * buffer pointer to DAPL_COOKIE_BUFFER
118 * ep endpoint to associate with cookies
119 * size number of elements to allocate & manage
121 * Output:
122 * none
124 * Returns:
125 * DAT_SUCCESS
126 * DAT_INSUFFICIENT_RESOURCES
129 DAT_RETURN
130 dapls_cb_create(
131 IN DAPL_COOKIE_BUFFER *buffer,
132 IN void *queue,
133 IN DAPL_COOKIE_QUEUE_TYPE type,
134 IN DAT_COUNT size)
137 DAT_COUNT i;
140 * allocate one additional entry so that the tail
141 * can always point at an empty location
143 size++;
144 /* round up to multiple of 2 */
145 i = 2;
146 while (size > i) {
147 i <<= 1;
149 size = i;
151 buffer->pool = dapl_os_alloc(size * sizeof (DAPL_COOKIE));
152 if (NULL != buffer->pool) {
153 buffer->pool_size = size;
154 buffer->head = 0;
155 buffer->tail = 0;
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;
162 } else {
163 buffer->pool[i].queue.srq = queue;
167 return (DAT_SUCCESS);
168 } else {
169 return (DAT_INSUFFICIENT_RESOURCES);
174 * dapls_cb_resize
176 * Given a DAPL_COOKIE_BUFFER, reallocate a larger buffer and initialize
177 * memory for the data structure from an old one
179 * Input:
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
185 * Output:
186 * none
188 * Returns:
189 * DAT_SUCCESS
190 * DAT_INVALID_PARAMETER
191 * DAT_INSUFFICIENT_RESOURCES
194 DAT_RETURN
195 dapls_cb_resize(
196 IN DAPL_COOKIE_BUFFER *curr_buffer,
197 IN DAT_COUNT new_size,
198 IN DAPL_COOKIE_BUFFER *new_buffer)
200 int index;
201 DAPL_ATOMIC head;
202 DAPL_ATOMIC tail;
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,
216 new_size);
218 if (dat_return != DAT_SUCCESS) {
219 return (dat_return);
222 /* copy all the free cookies to the new buffer */
223 head = curr_buffer->head;
224 tail = curr_buffer->tail;
225 index = 0;
226 while (head != tail) {
227 new_buffer->pool[index] = curr_buffer->pool[head];
228 head = (head + 1) % curr_buffer->pool_size;
229 index++;
231 new_buffer->head = 0;
232 new_buffer->tail = index;
234 return (DAT_SUCCESS);
238 * dapls_cb_free
240 * Free the data structure
242 * Input:
243 * buffer pointer to DAPL_COOKIE_BUFFER
245 * Output:
246 * none
248 * Returns:
249 * none
252 void
253 dapls_cb_free(
254 IN DAPL_COOKIE_BUFFER *buffer)
256 if (NULL != buffer->pool) {
257 dapl_os_free(buffer->pool, buffer->pool_size *
258 sizeof (DAPL_COOKIE));
264 * dapls_cb_get
266 * Remove an entry from the buffer
268 * Input:
269 * buffer pointer to DAPL_COOKIE_BUFFER
271 * Output:
272 * cookie_ptr pointer to pointer to cookie
274 * Returns:
275 * DAT_SUCCESS
276 * DAT_INVALID_PARAMETER
277 * DAT_INSUFFICIENT_RESOURCES
280 DAT_RETURN
281 dapls_cb_get(
282 IN DAPL_COOKIE_BUFFER *buffer,
283 OUT DAPL_COOKIE **cookie_ptr)
285 DAT_RETURN dat_status;
286 DAT_COUNT new_head;
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;
294 goto bail;
295 } else {
296 buffer->head = new_head;
297 *cookie_ptr = &buffer->pool[buffer->head];
298 dat_status = DAT_SUCCESS;
301 bail:
302 return (dat_status);
306 * dapls_cb_put
308 * Add entry(s) to the buffer
310 * Input:
311 * buffer pointer to DAPL_COOKIE_BUFFER
312 * cookie pointer to cookie
314 * Output:
315 * entry entry removed from the ring buffer
317 * Returns:
318 * DAT_SUCCESS
319 * DAT_INSUFFICIENT_EMPTY
322 DAT_RETURN
323 dapls_cb_put(
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
337 * Input:
338 * buffer pointer to DAPL_COOKIE_BUFFER
339 * rmr rmr to associate with the cookie
340 * user_cookie user's cookie data
342 * Output:
343 * cookie_ptr pointer to pointer to allocated cookie
345 * Returns:
346 * DAT_SUCCESS
347 * DAT_INSUFFICIENT_EMPTY
350 DAT_RETURN
351 dapls_rmr_cookie_alloc(
352 IN DAPL_COOKIE_BUFFER *buffer,
353 IN DAPL_RMR *rmr,
354 IN DAT_RMR_COOKIE user_cookie,
355 OUT DAPL_COOKIE **cookie_ptr)
357 DAPL_COOKIE *cookie;
358 DAT_RETURN dat_status;
360 if (DAT_SUCCESS != dapls_cb_get(buffer, &cookie)) {
361 *cookie_ptr = NULL;
362 dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
363 DAT_RESOURCE_MEMORY);
364 goto bail;
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;
373 bail:
374 return (dat_status);
379 * dapls_dto_cookie_alloc
381 * Allocate a DTO cookie
383 * Input:
384 * buffer pointer to DAPL_COOKIE_BUFFER
385 * type DTO type
386 * user_cookie user's cookie data
388 * Output:
389 * cookie_ptr pointer to pointer to allocated cookie
391 * Returns:
392 * DAT_SUCCESS
393 * DAT_INSUFFICIENT_EMPTY
396 DAT_RETURN
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)
403 DAPL_COOKIE *cookie;
405 if (DAT_SUCCESS != dapls_cb_get(buffer, &cookie)) {
406 *cookie_ptr = NULL;
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);
419 void
420 dapls_cookie_dealloc(
421 IN DAPL_COOKIE_BUFFER *buffer,
422 IN DAPL_COOKIE *cookie)
424 buffer->tail = cookie->index;