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) 2002-2003, Network Appliance, Inc. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 /*
32  *
33  * MODULE: dapl_provider.c
34  *
35  * PURPOSE: Provider function table
36  * Description: DAT Interfaces to this provider
37  *
38  * $Id: dapl_provider.c,v 1.7 2003/08/08 19:42:54 sjs2 Exp $
39  */
40 
41 #include "dapl_provider.h"
42 
43 
44 /*
45  *
46  * Global Data
47  *
48  */
49 
50 DAPL_PROVIDER_LIST 		g_dapl_provider_list;
51 
52 
53 /*
54  * the function table for this provider
55  */
56 
57 DAT_PROVIDER g_dapl_provider_template =
58 {
59 	NULL,
60 	0,
61 	&dapl_ia_open,
62 	&dapl_ia_query,
63 	&dapl_ia_close,
64 
65 	&dapl_set_consumer_context,
66 	&dapl_get_consumer_context,
67 	&dapl_get_handle_type,
68 
69 	&dapl_cno_create,
70 	&dapl_cno_modify_agent,
71 	&dapl_cno_query,
72 	&dapl_cno_free,
73 	&dapl_cno_wait,
74 
75 	&dapl_cr_query,
76 	&dapl_cr_accept,
77 	&dapl_cr_reject,
78 	&dapl_cr_handoff,
79 
80 	&dapl_evd_create,
81 	&dapl_evd_query,
82 	&dapl_evd_modify_cno,
83 	&dapl_evd_enable,
84 	&dapl_evd_disable,
85 	&dapl_evd_wait,
86 	&dapl_evd_resize,
87 	&dapl_evd_post_se,
88 	&dapl_evd_dequeue,
89 	&dapl_evd_free,
90 
91 	&dapl_ep_create,
92 	&dapl_ep_query,
93 	&dapl_ep_modify,
94 	&dapl_ep_connect,
95 	&dapl_ep_dup_connect,
96 	&dapl_ep_disconnect,
97 	&dapl_ep_post_send,
98 	&dapl_ep_post_recv,
99 	&dapl_ep_post_rdma_read,
100 	&dapl_ep_post_rdma_write,
101 	&dapl_ep_get_status,
102 	&dapl_ep_free,
103 
104 	&dapl_lmr_create,
105 	&dapl_lmr_query,
106 	&dapl_lmr_free,
107 
108 	&dapl_rmr_create,
109 	&dapl_rmr_query,
110 	&dapl_rmr_bind,
111 	&dapl_rmr_free,
112 
113 	&dapl_psp_create,
114 	&dapl_psp_query,
115 	&dapl_psp_free,
116 
117 	&dapl_rsp_create,
118 	&dapl_rsp_query,
119 	&dapl_rsp_free,
120 
121 	&dapl_pz_create,
122 	&dapl_pz_query,
123 	&dapl_pz_free,
124 
125 	&dapl_psp_create_any,
126 	&dapl_ep_reset,
127 	&dapl_evd_set_unwaitable,
128 	&dapl_evd_clear_unwaitable,
129 
130 	&dapl_lmr_sync_rdma_read,
131 	&dapl_lmr_sync_rdma_write,
132 
133 	&dapl_ep_create_with_srq,
134 	&dapl_ep_recv_query,
135 	&dapl_ep_set_watermark,
136 
137 	&dapl_srq_create,
138 	&dapl_srq_free,
139 	&dapl_srq_post_recv,
140 	&dapl_srq_query,
141 	&dapl_srq_resize,
142 	&dapl_srq_set_lw
143 };
144 
145 
146 
147 /*
148  *
149  * Function Prototypes
150  *
151  */
152 
153 static DAT_BOOLEAN
154 dapl_provider_list_key_cmp(
155     const char *name_a,
156     const char *name_b);
157 
158 
159 /*
160  *
161  * Function Definitions
162  *
163  */
164 
165 DAT_RETURN
dapl_provider_list_create(void)166 dapl_provider_list_create(void)
167 {
168 	DAT_RETURN status;
169 
170 	status = DAT_SUCCESS;
171 
172 	/* create the head node */
173 	g_dapl_provider_list.head = dapl_os_alloc(
174 	    sizeof (DAPL_PROVIDER_LIST_NODE));
175 	if (NULL == g_dapl_provider_list.head) {
176 		status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
177 		    DAT_RESOURCE_MEMORY);
178 		goto bail;
179 	}
180 
181 	(void) dapl_os_memzero(g_dapl_provider_list.head,
182 	    sizeof (DAPL_PROVIDER_LIST_NODE));
183 
184 	/* create the tail node */
185 	g_dapl_provider_list.tail = dapl_os_alloc(
186 	    sizeof (DAPL_PROVIDER_LIST_NODE));
187 	if (NULL == g_dapl_provider_list.tail) {
188 		status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
189 		    DAT_RESOURCE_MEMORY);
190 		goto bail;
191 	}
192 
193 	(void) dapl_os_memzero(g_dapl_provider_list.tail,
194 	    sizeof (DAPL_PROVIDER_LIST_NODE));
195 
196 	g_dapl_provider_list.head->next = g_dapl_provider_list.tail;
197 	g_dapl_provider_list.tail->prev = g_dapl_provider_list.head;
198 	g_dapl_provider_list.size = 0;
199 
200 bail:
201 	if (DAT_SUCCESS != status) {
202 		if (NULL != g_dapl_provider_list.head) {
203 			dapl_os_free(g_dapl_provider_list.head,
204 			    sizeof (DAPL_PROVIDER_LIST_NODE));
205 		}
206 
207 		if (NULL != g_dapl_provider_list.tail) {
208 			dapl_os_free(g_dapl_provider_list.tail,
209 			    sizeof (DAPL_PROVIDER_LIST_NODE));
210 		}
211 	}
212 
213 	return (status);
214 }
215 
216 
217 DAT_RETURN
dapl_provider_list_destroy(void)218 dapl_provider_list_destroy(void)
219 {
220 	DAPL_PROVIDER_LIST_NODE *cur_node;
221 
222 	while (NULL != g_dapl_provider_list.head) {
223 		cur_node = g_dapl_provider_list.head;
224 		g_dapl_provider_list.head = cur_node->next;
225 
226 		dapl_os_free(cur_node, sizeof (DAPL_PROVIDER_LIST_NODE));
227 	}
228 
229 	return (DAT_SUCCESS);
230 }
231 
232 
233 DAT_COUNT
dapl_provider_list_size(void)234 dapl_provider_list_size(void)
235 {
236 	return (g_dapl_provider_list.size);
237 }
238 
239 
240 DAT_RETURN
dapl_provider_list_insert(IN const char * name,IN DAT_PROVIDER ** p_data)241 dapl_provider_list_insert(
242     IN  const char *name,
243     IN  DAT_PROVIDER **p_data)
244 {
245 	DAPL_PROVIDER_LIST_NODE *cur_node, *prev_node, *next_node;
246 	DAT_RETURN status;
247 	unsigned int len;
248 
249 	status = DAT_SUCCESS;
250 	*p_data = NULL;
251 
252 	cur_node = dapl_os_alloc(sizeof (DAPL_PROVIDER_LIST_NODE));
253 
254 	if (NULL == cur_node) {
255 		status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
256 		    DAT_RESOURCE_MEMORY);
257 		goto bail;
258 	}
259 
260 	len = dapl_os_strlen(name);
261 
262 	if (DAT_NAME_MAX_LENGTH <= len) {
263 		status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
264 		    DAT_RESOURCE_MEMORY);
265 		goto bail;
266 	}
267 
268 	/* insert node at end of list to preserve registration order */
269 	prev_node = g_dapl_provider_list.tail->prev;
270 	next_node = g_dapl_provider_list.tail;
271 
272 	(void) dapl_os_memcpy(cur_node->name, name, len);
273 	cur_node->name[len] = '\0';
274 	cur_node->data = g_dapl_provider_template;
275 	cur_node->data.device_name = cur_node->name;
276 	cur_node->next = next_node;
277 	cur_node->prev = prev_node;
278 
279 	prev_node->next = cur_node;
280 	next_node->prev = cur_node;
281 
282 	g_dapl_provider_list.size++;
283 
284 	if (NULL != p_data) {
285 		*p_data = &cur_node->data;
286 	}
287 
288 bail:
289 	if (DAT_SUCCESS != status) {
290 		if (NULL != cur_node) {
291 			dapl_os_free(cur_node,
292 			    sizeof (DAPL_PROVIDER_LIST_NODE));
293 		}
294 	}
295 
296 	return (status);
297 }
298 
299 
300 DAT_RETURN
dapl_provider_list_search(IN const char * name,OUT DAT_PROVIDER ** p_data)301 dapl_provider_list_search(
302     IN  const char *name,
303     OUT DAT_PROVIDER **p_data)
304 {
305 	DAPL_PROVIDER_LIST_NODE *cur_node;
306 	DAT_RETURN		status;
307 
308 	status = DAT_ERROR(DAT_NAME_NOT_FOUND, 0);
309 
310 	for (cur_node = g_dapl_provider_list.head->next;
311 	    g_dapl_provider_list.tail != cur_node;
312 	    cur_node = cur_node->next) {
313 		if (dapl_provider_list_key_cmp(cur_node->name, name)) {
314 			if (NULL != p_data) {
315 				*p_data = &cur_node->data;
316 			}
317 
318 			status = DAT_SUCCESS;
319 			goto bail;
320 		}
321 	}
322 
323 bail:
324 	return (status);
325 }
326 
327 
328 DAT_RETURN
dapl_provider_list_remove(IN const char * name)329 dapl_provider_list_remove(
330     IN  const char *name)
331 {
332 	DAPL_PROVIDER_LIST_NODE *cur_node, *prev_node, *next_node;
333 	DAT_RETURN status;
334 
335 	status = DAT_ERROR(DAT_NAME_NOT_FOUND, 0);
336 
337 	for (cur_node = g_dapl_provider_list.head->next;
338 	    g_dapl_provider_list.tail != cur_node;
339 	    cur_node = cur_node->next) {
340 		if (dapl_provider_list_key_cmp(cur_node->name, name)) {
341 			prev_node = cur_node->prev;
342 			next_node = cur_node->next;
343 
344 			prev_node->next = next_node;
345 			next_node->prev = prev_node;
346 
347 			dapl_os_free(cur_node,
348 			    sizeof (DAPL_PROVIDER_LIST_NODE));
349 
350 			g_dapl_provider_list.size--;
351 
352 			status = DAT_SUCCESS;
353 			goto bail;
354 		}
355 	}
356 
357 bail:
358 	return (status);
359 }
360 
361 
362 DAT_BOOLEAN
dapl_provider_list_key_cmp(const char * name_a,const char * name_b)363 dapl_provider_list_key_cmp(
364     const char *name_a,
365     const char *name_b)
366 {
367 	unsigned int len;
368 
369 	len = dapl_os_strlen(name_a);
370 
371 	if (dapl_os_strlen(name_b) != len) {
372 		return (DAT_FALSE);
373 	} else if (dapl_os_memcmp(name_a, name_b, len)) {
374 		return (DAT_FALSE);
375 	} else {
376 		return (DAT_TRUE);
377 	}
378 }
379