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