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 59void 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 67void 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 92ib_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 107void 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 117ib_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*/ 193cl_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+*/ 219void 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*/ 242ib_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 264boolean_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 293ib_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 319static 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 335boolean_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 365ib_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 481boolean_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 509boolean_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 535Exit: 536 OSM_LOG_EXIT(p_log); 537 return ret; 538} 539 540boolean_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 573Exit: 574 OSM_LOG_EXIT(p_log); 575 return res; 576} 577 578void 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