xref: /freebsd/contrib/ofed/opensm/opensm/osm_pkey.c (revision d6b92ffa)
1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35 
36 /*
37  * Abstract:
38  *    Implementation of opensm pkey manipulation functions.
39  */
40 
41 #if HAVE_CONFIG_H
42 #  include <config.h>
43 #endif				/* HAVE_CONFIG_H */
44 
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <complib/cl_debug.h>
49 #include <iba/ib_types.h>
50 #include <opensm/osm_file_ids.h>
51 #define FILE_ID OSM_FILE_PKEY_C
52 #include <opensm/osm_pkey.h>
53 #include <opensm/osm_log.h>
54 #include <opensm/osm_port.h>
55 #include <opensm/osm_node.h>
56 #include <opensm/osm_switch.h>
57 #include <opensm/osm_helper.h>
58 
osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl)59 void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl)
60 {
61 	cl_map_construct(&p_pkey_tbl->accum_pkeys);
62 	cl_ptr_vector_construct(&p_pkey_tbl->blocks);
63 	cl_ptr_vector_construct(&p_pkey_tbl->new_blocks);
64 	cl_map_construct(&p_pkey_tbl->keys);
65 }
66 
osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl)67 void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl)
68 {
69 	ib_pkey_table_t *p_block;
70 	uint16_t num_blocks, i;
71 
72 	num_blocks = (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks));
73 	for (i = 0; i < num_blocks; i++)
74 		if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, i)))
75 			free(p_block);
76 	cl_ptr_vector_destroy(&p_pkey_tbl->blocks);
77 
78 	num_blocks =
79 	    (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks));
80 	for (i = 0; i < num_blocks; i++)
81 		if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, i)))
82 			free(p_block);
83 	cl_ptr_vector_destroy(&p_pkey_tbl->new_blocks);
84 
85 	cl_map_remove_all(&p_pkey_tbl->accum_pkeys);
86 	cl_map_destroy(&p_pkey_tbl->accum_pkeys);
87 
88 	cl_map_remove_all(&p_pkey_tbl->keys);
89 	cl_map_destroy(&p_pkey_tbl->keys);
90 }
91 
osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl)92 ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl)
93 {
94 	cl_map_init(&p_pkey_tbl->accum_pkeys, 1);
95 	cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1);
96 	cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1);
97 	cl_map_init(&p_pkey_tbl->keys, 1);
98 	cl_qlist_init(&p_pkey_tbl->pending);
99 	p_pkey_tbl->last_pkey_idx = 0;
100 	p_pkey_tbl->used_blocks = 0;
101 	p_pkey_tbl->max_blocks = 0;
102 	p_pkey_tbl->rcv_blocks_cnt = 0;
103 	p_pkey_tbl->indx0_pkey = 0;
104 	return IB_SUCCESS;
105 }
106 
osm_pkey_tbl_init_new_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl)107 void osm_pkey_tbl_init_new_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl)
108 {
109 	ib_pkey_table_t *p_block;
110 	size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks);
111 
112 	for (b = 0; b < num_blocks; b++)
113 		if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b)))
114 			memset(p_block, 0, sizeof(*p_block));
115 }
116 
osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,IN uint16_t block,IN ib_pkey_table_t * p_tbl,IN boolean_t allow_both_pkeys)117 ib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,
118 				 IN uint16_t block, IN ib_pkey_table_t * p_tbl,
119 				 IN boolean_t allow_both_pkeys)
120 {
121 	uint16_t b, i;
122 	ib_pkey_table_t *p_pkey_block;
123 	uint16_t *p_prev_pkey;
124 	ib_net16_t pkey, pkey_base;
125 
126 	/* make sure the block is allocated */
127 	if (cl_ptr_vector_get_size(&p_pkey_tbl->blocks) > block)
128 		p_pkey_block =
129 		    (ib_pkey_table_t *) cl_ptr_vector_get(&p_pkey_tbl->blocks,
130 							  block);
131 	else
132 		p_pkey_block = NULL;
133 
134 	if (!p_pkey_block) {
135 		p_pkey_block =
136 		    (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
137 		if (!p_pkey_block)
138 			return IB_ERROR;
139 		memset(p_pkey_block, 0, sizeof(ib_pkey_table_t));
140 		cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block);
141 	}
142 
143 	/* sets the block values */
144 	memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t));
145 
146 	/*
147 	   NOTE: as the spec does not require uniqueness of PKeys in
148 	   tables there is no other way but to refresh the entire keys map.
149 
150 	   Moreover, if the same key exists but with full membership it should
151 	   have precedence over the key with limited membership !
152 	 */
153 	cl_map_remove_all(&p_pkey_tbl->keys);
154 
155 	for (b = 0; b < cl_ptr_vector_get_size(&p_pkey_tbl->blocks); b++) {
156 
157 		p_pkey_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b);
158 		if (!p_pkey_block)
159 			continue;
160 
161 		for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) {
162 			pkey = p_pkey_block->pkey_entry[i];
163 			if (ib_pkey_is_invalid(pkey))
164 				continue;
165 
166 			if (allow_both_pkeys)
167 				pkey_base = pkey;
168 			else
169 				pkey_base = ib_pkey_get_base(pkey);
170 
171 			/*
172 			   If allow_both_pkeys is FALSE,
173 			   ignore the PKey Full Member bit in the key but store
174 			   the pointer to the table element as the map value
175 			 */
176 			p_prev_pkey = cl_map_get(&p_pkey_tbl->keys, pkey_base);
177 
178 			/* we only insert if no previous or it is not full member and allow_both_pkeys is FALSE */
179 			if ((p_prev_pkey == NULL) ||
180 			    (allow_both_pkeys == FALSE &&
181 			     cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
182 				cl_map_insert(&p_pkey_tbl->keys, pkey_base,
183 					      &(p_pkey_block->pkey_entry[i])
184 				    );
185 		}
186 	}
187 	return IB_SUCCESS;
188 }
189 
190 /*
191   Store the given pkey (along with it's overall index) in the accum_pkeys array.
192 */
osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl,IN uint16_t pkey,IN uint16_t pkey_idx)193 cl_status_t osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl,
194 					 IN uint16_t pkey,
195 					 IN uint16_t pkey_idx)
196 {
197 	uintptr_t ptr = pkey_idx + 1; /* 0 means not found so bias by 1 */
198 	uint16_t *p_prev_pkey_idx;
199 	cl_status_t status = CL_SUCCESS;
200 
201 	if (pkey_idx >= p_pkey_tbl->last_pkey_idx)
202 		p_pkey_tbl->last_pkey_idx = pkey_idx + 1;
203 
204 	p_prev_pkey_idx = (uint16_t *) cl_map_get(&p_pkey_tbl->accum_pkeys, pkey);
205 
206 	if (p_prev_pkey_idx != NULL)
207 		cl_map_remove(&p_pkey_tbl->accum_pkeys, pkey);
208 
209 	if (cl_map_insert(&p_pkey_tbl->accum_pkeys, pkey, (void *) ptr) == NULL)
210 		status = CL_INSUFFICIENT_MEMORY;
211 
212 	return status;
213 
214 }
215 
216 /*
217 + * Find the next last pkey index
218 +*/
osm_pkey_find_last_accum_pkey_index(IN osm_pkey_tbl_t * p_pkey_tbl)219 void osm_pkey_find_last_accum_pkey_index(IN osm_pkey_tbl_t * p_pkey_tbl)
220 {
221 	void *ptr;
222 	uintptr_t pkey_idx_ptr;
223 	uint16_t pkey_idx, last_pkey_idx = 0;
224 	cl_map_iterator_t map_iter = cl_map_head(&p_pkey_tbl->accum_pkeys);
225 
226 	while (map_iter != cl_map_end(&p_pkey_tbl->accum_pkeys)) {
227 		ptr = (uint16_t *) cl_map_obj(map_iter);
228 		CL_ASSERT(ptr);
229 		pkey_idx_ptr = (uintptr_t) ptr;
230 		pkey_idx = pkey_idx_ptr;
231 		if (pkey_idx > last_pkey_idx)
232 			last_pkey_idx = pkey_idx;
233 		map_iter = cl_map_next(map_iter);
234 	}
235 	p_pkey_tbl->last_pkey_idx = last_pkey_idx;
236 }
237 
238 /*
239   Store the given pkey in the "new" blocks array.
240   Also, make sure the regular block exists.
241 */
osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl,IN uint16_t block_idx,IN uint8_t pkey_idx,IN uint16_t pkey)242 ib_api_status_t osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
243 					   IN uint16_t block_idx,
244 					   IN uint8_t pkey_idx,
245 					   IN uint16_t pkey)
246 {
247 	ib_pkey_table_t *p_block;
248 
249 	if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) {
250 		p_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
251 		if (!p_block)
252 			return IB_ERROR;
253 		memset(p_block, 0, sizeof(ib_pkey_table_t));
254 		cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block);
255 	}
256 
257 	p_block->pkey_entry[pkey_idx] = pkey;
258 	if (p_pkey_tbl->used_blocks <= block_idx)
259 		p_pkey_tbl->used_blocks = block_idx + 1;
260 
261 	return IB_SUCCESS;
262 }
263 
osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl,OUT uint16_t * p_block_idx,OUT uint8_t * p_pkey_idx)264 boolean_t osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
265 					OUT uint16_t * p_block_idx,
266 					OUT uint8_t * p_pkey_idx)
267 {
268 	ib_pkey_table_t *p_new_block;
269 
270 	CL_ASSERT(p_block_idx);
271 	CL_ASSERT(p_pkey_idx);
272 
273 	while (*p_block_idx < p_pkey_tbl->max_blocks) {
274 		if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) {
275 			*p_pkey_idx = 0;
276 			(*p_block_idx)++;
277 			if (*p_block_idx >= p_pkey_tbl->max_blocks)
278 				return FALSE;
279 		}
280 
281 		p_new_block =
282 		    osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx);
283 
284 		if (!p_new_block ||
285 		    ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx]))
286 			return TRUE;
287 		else
288 			(*p_pkey_idx)++;
289 	}
290 	return FALSE;
291 }
292 
osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl,IN uint16_t * p_pkey,OUT uint16_t * p_block_idx,OUT uint8_t * p_pkey_idx)293 ib_api_status_t osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl,
294 					       IN uint16_t * p_pkey,
295 					       OUT uint16_t * p_block_idx,
296 					       OUT uint8_t * p_pkey_idx)
297 {
298 	uint16_t num_of_blocks;
299 	uint16_t block_index;
300 	ib_pkey_table_t *block;
301 
302 	CL_ASSERT(p_block_idx != NULL);
303 	CL_ASSERT(p_pkey_idx != NULL);
304 
305 	num_of_blocks = (uint16_t) cl_ptr_vector_get_size(&p_pkey_tbl->blocks);
306 	for (block_index = 0; block_index < num_of_blocks; block_index++) {
307 		block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
308 		if ((block->pkey_entry <= p_pkey) &&
309 		    (p_pkey <
310 		     block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) {
311 			*p_block_idx = block_index;
312 			*p_pkey_idx = (uint8_t) (p_pkey - block->pkey_entry);
313 			return IB_SUCCESS;
314 		}
315 	}
316 	return IB_NOT_FOUND;
317 }
318 
match_pkey(IN const ib_net16_t * pkey1,IN const ib_net16_t * pkey2)319 static boolean_t match_pkey(IN const ib_net16_t * pkey1,
320 			    IN const ib_net16_t * pkey2)
321 {
322 
323 	/* if both pkeys are not full member - this is not a match */
324 	if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2)))
325 		return FALSE;
326 
327 	/* compare if the bases are the same. if they are - then
328 	   this is a match */
329 	if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2))
330 		return FALSE;
331 
332 	return TRUE;
333 }
334 
osm_physp_share_this_pkey(IN const osm_physp_t * p_physp1,IN const osm_physp_t * p_physp2,IN ib_net16_t pkey,IN boolean_t allow_both_pkeys)335 boolean_t osm_physp_share_this_pkey(IN const osm_physp_t * p_physp1,
336 				    IN const osm_physp_t * p_physp2,
337 				    IN ib_net16_t pkey,
338 				    IN boolean_t allow_both_pkeys)
339 {
340 	ib_net16_t *pkey1, *pkey2;
341 	ib_net16_t full_pkey, limited_pkey;
342 
343 	if (allow_both_pkeys) {
344 		full_pkey = pkey | IB_PKEY_TYPE_MASK;
345 		limited_pkey = pkey & ~IB_PKEY_TYPE_MASK;
346 		pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
347 				   full_pkey);
348 		if (!pkey1)
349 			pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
350 					   limited_pkey);
351 		pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
352 				   full_pkey);
353 		if (!pkey2)
354 			pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
355 					   limited_pkey);
356 	} else {
357 		pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
358 				   ib_pkey_get_base(pkey));
359 		pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
360 				   ib_pkey_get_base(pkey));
361 	}
362 	return (pkey1 && pkey2 && match_pkey(pkey1, pkey2));
363 }
364 
osm_physp_find_common_pkey(IN const osm_physp_t * p_physp1,IN const osm_physp_t * p_physp2,IN boolean_t allow_both_pkeys)365 ib_net16_t osm_physp_find_common_pkey(IN const osm_physp_t * p_physp1,
366 				      IN const osm_physp_t * p_physp2,
367 				      IN boolean_t allow_both_pkeys)
368 {
369 	ib_net16_t *pkey1, *pkey2;
370 	uint64_t pkey1_base, pkey2_base;
371 	const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
372 	cl_map_iterator_t map_iter1, map_iter2;
373 
374 	pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1);
375 	pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2);
376 
377 	map_iter1 = cl_map_head(&pkey_tbl1->keys);
378 	map_iter2 = cl_map_head(&pkey_tbl2->keys);
379 
380 	/* we rely on the fact the map are sorted by pkey */
381 	while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
382 	       (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
383 		pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
384 		pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
385 
386 		if (match_pkey(pkey1, pkey2))
387 			return *pkey1;
388 
389 		/* advance the lower value if they are not equal */
390 		pkey1_base = cl_map_key(map_iter1);
391 		pkey2_base = cl_map_key(map_iter2);
392 		if (pkey2_base == pkey1_base) {
393 			map_iter1 = cl_map_next(map_iter1);
394 			map_iter2 = cl_map_next(map_iter2);
395 		} else if (pkey2_base < pkey1_base)
396 			map_iter2 = cl_map_next(map_iter2);
397 		else
398 			map_iter1 = cl_map_next(map_iter1);
399 	}
400 
401 	if (!allow_both_pkeys)
402 		return 0;
403 
404 	/*
405 	   When using allow_both_pkeys, the keys in pkey tables are the
406 	   pkey value including membership bit.
407 	   Therefore, in order to complete the search, we also need to
408 	   compare port\s 1 full pkeys with port 2 limited pkeys, and
409 	   port 2 full pkeys with port 1 full pkeys.
410 	*/
411 
412 	map_iter1 = cl_map_head(&pkey_tbl1->keys);
413 	map_iter2 = cl_map_head(&pkey_tbl2->keys);
414 
415 	/* comparing pkey_tbl1 full with pkey_tbl2 limited */
416 	while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
417 	       (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
418 		pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
419 		pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
420 
421 		if (!ib_pkey_is_full_member(*pkey1)) {
422 			map_iter1 = cl_map_next(map_iter1);
423 			continue;
424 		}
425 		if (ib_pkey_is_full_member(*pkey2)) {
426 			map_iter2 = cl_map_next(map_iter2);
427 			continue;
428 		}
429 
430 		if (match_pkey(pkey1, pkey2))
431 			return *pkey1;
432 
433 		/* advance the lower value if they are not equal */
434 		pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1));
435 		pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2));
436 		if (pkey2_base == pkey1_base) {
437 			map_iter1 = cl_map_next(map_iter1);
438 			map_iter2 = cl_map_next(map_iter2);
439 		} else if (pkey2_base < pkey1_base)
440 			map_iter2 = cl_map_next(map_iter2);
441 		else
442 			map_iter1 = cl_map_next(map_iter1);
443 	}
444 
445 	map_iter1 = cl_map_head(&pkey_tbl1->keys);
446 	map_iter2 = cl_map_head(&pkey_tbl2->keys);
447 
448 	/* comparing pkey_tbl1 limited with pkey_tbl2 full */
449 	while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
450 	       (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
451 		pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
452 		pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
453 
454 		if (ib_pkey_is_full_member(*pkey1)) {
455 			map_iter1 = cl_map_next(map_iter1);
456 			continue;
457 		}
458 		if (!ib_pkey_is_full_member(*pkey2)) {
459 			map_iter2 = cl_map_next(map_iter2);
460 			continue;
461 		}
462 
463 		if (match_pkey(pkey1, pkey2))
464 			return *pkey1;
465 
466 		/* advance the lower value if they are not equal */
467 		pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1));
468 		pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2));
469 		if (pkey2_base == pkey1_base) {
470 			map_iter1 = cl_map_next(map_iter1);
471 			map_iter2 = cl_map_next(map_iter2);
472 		} else if (pkey2_base < pkey1_base)
473 			map_iter2 = cl_map_next(map_iter2);
474 		else
475 			map_iter1 = cl_map_next(map_iter1);
476 	}
477 
478 	return 0;
479 }
480 
osm_physp_share_pkey(IN osm_log_t * p_log,IN const osm_physp_t * p_physp_1,IN const osm_physp_t * p_physp_2,IN boolean_t allow_both_pkeys)481 boolean_t osm_physp_share_pkey(IN osm_log_t * p_log,
482 			       IN const osm_physp_t * p_physp_1,
483 			       IN const osm_physp_t * p_physp_2,
484 			       IN boolean_t allow_both_pkeys)
485 {
486 	const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
487 
488 	if (p_physp_1 == p_physp_2)
489 		return TRUE;
490 
491 	pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1);
492 	pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2);
493 
494 	/*
495 	   The spec: 10.9.2 does not require each phys port to have PKey Table.
496 	   So actually if it does not, we need to use the default port instead.
497 
498 	   HACK: meanwhile we will ignore the check
499 	 */
500 	if (cl_is_map_empty(&pkey_tbl1->keys)
501 	    || cl_is_map_empty(&pkey_tbl2->keys))
502 		return TRUE;
503 
504 	return
505 	    !ib_pkey_is_invalid(osm_physp_find_common_pkey
506 				(p_physp_1, p_physp_2, allow_both_pkeys));
507 }
508 
osm_port_share_pkey(IN osm_log_t * p_log,IN const osm_port_t * p_port_1,IN const osm_port_t * p_port_2,IN boolean_t allow_both_pkeys)509 boolean_t osm_port_share_pkey(IN osm_log_t * p_log,
510 			      IN const osm_port_t * p_port_1,
511 			      IN const osm_port_t * p_port_2,
512 			      IN boolean_t allow_both_pkeys)
513 {
514 
515 	osm_physp_t *p_physp1, *p_physp2;
516 	boolean_t ret;
517 
518 	OSM_LOG_ENTER(p_log);
519 
520 	if (!p_port_1 || !p_port_2) {
521 		ret = FALSE;
522 		goto Exit;
523 	}
524 
525 	p_physp1 = p_port_1->p_physp;
526 	p_physp2 = p_port_2->p_physp;
527 
528 	if (!p_physp1 || !p_physp2) {
529 		ret = FALSE;
530 		goto Exit;
531 	}
532 
533 	ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2, allow_both_pkeys);
534 
535 Exit:
536 	OSM_LOG_EXIT(p_log);
537 	return ret;
538 }
539 
osm_physp_has_pkey(IN osm_log_t * p_log,IN ib_net16_t pkey,IN const osm_physp_t * p_physp)540 boolean_t osm_physp_has_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey,
541 			     IN const osm_physp_t * p_physp)
542 {
543 	ib_net16_t *p_pkey, pkey_base;
544 	const osm_pkey_tbl_t *pkey_tbl;
545 	boolean_t res = FALSE;
546 
547 	OSM_LOG_ENTER(p_log);
548 
549 	OSM_LOG(p_log, OSM_LOG_DEBUG,
550 		"Search for PKey: 0x%04x\n", cl_ntoh16(pkey));
551 
552 	/* if the pkey given is an invalid pkey - return TRUE. */
553 	if (ib_pkey_is_invalid(pkey)) {
554 		OSM_LOG(p_log, OSM_LOG_DEBUG,
555 			"Given invalid PKey - we treat it loosely and allow it\n");
556 		res = TRUE;
557 		goto Exit;
558 	}
559 
560 	pkey_base = ib_pkey_get_base(pkey);
561 
562 	pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
563 
564 	p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base);
565 	if (p_pkey) {
566 		res = TRUE;
567 		OSM_LOG(p_log, OSM_LOG_DEBUG,
568 			"PKey 0x%04x was found\n", cl_ntoh16(pkey));
569 	} else
570 		OSM_LOG(p_log, OSM_LOG_DEBUG,
571 			"PKey 0x%04x was not found\n", cl_ntoh16(pkey));
572 
573 Exit:
574 	OSM_LOG_EXIT(p_log);
575 	return res;
576 }
577 
osm_pkey_tbl_set_indx0_pkey(IN osm_log_t * p_log,IN ib_net16_t pkey,IN boolean_t full,OUT osm_pkey_tbl_t * p_pkey_tbl)578 void osm_pkey_tbl_set_indx0_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey,
579 				 IN boolean_t full,
580 				 OUT osm_pkey_tbl_t * p_pkey_tbl)
581 {
582 	p_pkey_tbl->indx0_pkey = (full == TRUE) ?
583 				 pkey | cl_hton16(0x8000) : pkey;
584 	OSM_LOG(p_log, OSM_LOG_DEBUG, "pkey 0x%04x set at indx0\n",
585 		cl_ntoh16(p_pkey_tbl->indx0_pkey));
586 }
587