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_sp_util.c
34  *
35  * PURPOSE: Manage PSP Info structure
36  *
37  * $Id: dapl_sp_util.c,v 1.10 2003/08/20 14:55:39 sjs2 Exp $
38  */
39 
40 #include "dapl.h"
41 #include "dapl_sp_util.h"
42 
43 /*
44  * Local definitions
45  */
46 
47 
48 /*
49  * dapl_sp_alloc
50  *
51  * alloc and initialize a PSP INFO struct
52  *
53  * Input:
54  * 	IA INFO struct ptr
55  *
56  * Output:
57  * 	sp_ptr
58  *
59  * Returns:
60  * 	NULL
61  *	pointer to sp info struct
62  *
63  */
64 DAPL_SP *
dapls_sp_alloc(IN DAPL_IA * ia_ptr,IN DAT_BOOLEAN is_psp)65 dapls_sp_alloc(
66 	IN DAPL_IA *ia_ptr,
67 	IN DAT_BOOLEAN is_psp)
68 {
69 	DAPL_SP *sp_ptr;
70 
71 	/* Allocate EP */
72 	sp_ptr = (DAPL_SP *)dapl_os_alloc(sizeof (DAPL_SP));
73 	if (sp_ptr == NULL) {
74 		return (NULL);
75 	}
76 
77 	/* zero the structure */
78 	(void) dapl_os_memzero(sp_ptr, sizeof (DAPL_SP));
79 
80 	/*
81 	 * initialize the header
82 	 */
83 	sp_ptr->header.provider = ia_ptr->header.provider;
84 	if (is_psp) {
85 		sp_ptr->header.magic = DAPL_MAGIC_PSP;
86 		sp_ptr->header.handle_type = DAT_HANDLE_TYPE_PSP;
87 	} else {
88 		sp_ptr->header.magic = DAPL_MAGIC_RSP;
89 		sp_ptr->header.handle_type = DAT_HANDLE_TYPE_RSP;
90 	}
91 	sp_ptr->header.owner_ia = ia_ptr;
92 	sp_ptr->header.user_context.as_64 = 0;
93 	sp_ptr->header.user_context.as_ptr = NULL;
94 	dapl_llist_init_entry(&sp_ptr->header.ia_list_entry);
95 	dapl_os_lock_init(&sp_ptr->header.lock);
96 
97 	/*
98 	 * Initialize the Body (set to NULL above)
99 	 */
100 	dapl_llist_init_head(&sp_ptr->cr_list_head);
101 
102 	return (sp_ptr);
103 }
104 
105 
106 /*
107  * dapl_sp_free
108  *
109  * Free the passed in PSP structure.
110  *
111  * Input:
112  * 	entry point pointer
113  *
114  * Output:
115  * 	none
116  *
117  * Returns:
118  * 	none
119  *
120  */
121 void
dapls_sp_free_sp(IN DAPL_SP * sp_ptr)122 dapls_sp_free_sp(
123 	IN DAPL_SP *sp_ptr)
124 {
125 	dapl_os_assert(sp_ptr->header.magic == DAPL_MAGIC_PSP ||
126 	    sp_ptr->header.magic == DAPL_MAGIC_RSP);
127 	dapl_os_assert(dapl_llist_is_empty(&sp_ptr->cr_list_head));
128 
129 	dapl_os_lock(&sp_ptr->header.lock);
130 	/* reset magic to prevent reuse */
131 	sp_ptr->header.magic = DAPL_MAGIC_INVALID;
132 	dapl_os_unlock(&sp_ptr->header.lock);
133 	dapl_os_free(sp_ptr, sizeof (DAPL_SP));
134 }
135 
136 
137 /*
138  * dapl_cr_link_cr
139  *
140  * Add a cr to a PSP structure
141  *
142  * Input:
143  *	sp_ptr
144  *	cr_ptr
145  *
146  * Output:
147  * 	none
148  *
149  * Returns:
150  * 	none
151  *
152  */
153 void
dapl_sp_link_cr(IN DAPL_SP * sp_ptr,IN DAPL_CR * cr_ptr)154 dapl_sp_link_cr(
155 	IN DAPL_SP *sp_ptr,
156 	IN DAPL_CR *cr_ptr)
157 {
158 	dapl_os_lock(&sp_ptr->header.lock);
159 	dapl_llist_add_tail(&sp_ptr->cr_list_head,
160 	    &cr_ptr->header.ia_list_entry, cr_ptr);
161 	sp_ptr->cr_list_count++;
162 	dapl_os_unlock(&sp_ptr->header.lock);
163 }
164 
165 
166 /*
167  * dapl_sp_search_cr
168  *
169  * Search for a CR on the PSP cr_list with a matching cm_handle. When
170  * found, remove it from the list and update fields.
171  *
172  * Input:
173  *	sp_ptr
174  *	ib_cm_handle
175  *
176  * Output:
177  * 	none
178  *
179  * Returns:
180  * 	cr_ptr_fnd	Pointer to matching DAPL_CR
181  *
182  */
183 DAPL_CR *
dapl_sp_search_cr(IN DAPL_SP * sp_ptr,IN ib_cm_handle_t ib_cm_handle)184 dapl_sp_search_cr(
185 	IN DAPL_SP *sp_ptr,
186 	IN  ib_cm_handle_t ib_cm_handle)
187 {
188 	DAPL_CR	*cr_ptr;
189 	DAPL_CR	*cr_ptr_fnd;
190 
191 	dapl_os_lock(&sp_ptr->header.lock);
192 	cr_ptr_fnd = NULL;
193 	cr_ptr = (DAPL_CR *) dapl_llist_peek_head(&sp_ptr->cr_list_head);
194 
195 	do {
196 		if (cr_ptr->ib_cm_handle == ib_cm_handle) {
197 			cr_ptr_fnd = cr_ptr;
198 			break;
199 		}
200 		cr_ptr = cr_ptr->header.ia_list_entry.flink->data;
201 	} while ((void *)cr_ptr != (void *)sp_ptr->cr_list_head->data);
202 
203 	dapl_os_unlock(&sp_ptr->header.lock);
204 	return (cr_ptr_fnd);
205 }
206 
207 
208 
209 /*
210  * dapl_sp_remove_cr
211  *
212  * Remove the CR from the PSP. Done prior to freeing the CR resource.
213  *
214  * Input:
215  *	sp_ptr
216  *	cr_ptr
217  *
218  * Output:
219  * 	none
220  *
221  * Returns:
222  * 	void
223  *
224  */
225 void
dapl_sp_remove_cr(IN DAPL_SP * sp_ptr,IN DAPL_CR * cr_ptr)226 dapl_sp_remove_cr(
227 	IN  DAPL_SP *sp_ptr,
228 	IN  DAPL_CR *cr_ptr)
229 {
230 	dapl_os_lock(&sp_ptr->header.lock);
231 
232 	if (dapl_llist_is_empty(&sp_ptr->cr_list_head)) {
233 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
234 		    "***dapl_sp_remove_cr: removing from empty queue! sp %p\n",
235 		    sp_ptr);
236 		dapl_os_unlock(&sp_ptr->header.lock);
237 		return;
238 	}
239 
240 	(void) dapl_llist_remove_entry(&sp_ptr->cr_list_head,
241 	    &cr_ptr->header.ia_list_entry);
242 	sp_ptr->cr_list_count--;
243 
244 	dapl_os_unlock(&sp_ptr->header.lock);
245 }
246