1321936Shselasky/* 2321936Shselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3321936Shselasky * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved. 4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5321936Shselasky * 6321936Shselasky * This software is available to you under a choice of one of two 7321936Shselasky * licenses. You may choose to be licensed under the terms of the GNU 8321936Shselasky * General Public License (GPL) Version 2, available from the file 9321936Shselasky * COPYING in the main directory of this source tree, or the 10321936Shselasky * OpenIB.org BSD license below: 11321936Shselasky * 12321936Shselasky * Redistribution and use in source and binary forms, with or 13321936Shselasky * without modification, are permitted provided that the following 14321936Shselasky * conditions are met: 15321936Shselasky * 16321936Shselasky * - Redistributions of source code must retain the above 17321936Shselasky * copyright notice, this list of conditions and the following 18321936Shselasky * disclaimer. 19321936Shselasky * 20321936Shselasky * - Redistributions in binary form must reproduce the above 21321936Shselasky * copyright notice, this list of conditions and the following 22321936Shselasky * disclaimer in the documentation and/or other materials 23321936Shselasky * provided with the distribution. 24321936Shselasky * 25321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32321936Shselasky * SOFTWARE. 33321936Shselasky * 34321936Shselasky */ 35321936Shselasky 36321936Shselasky/* 37321936Shselasky * Abstract: 38321936Shselasky * Implementation of opensm pkey manipulation functions. 39321936Shselasky */ 40321936Shselasky 41321936Shselasky#if HAVE_CONFIG_H 42321936Shselasky# include <config.h> 43321936Shselasky#endif /* HAVE_CONFIG_H */ 44321936Shselasky 45321936Shselasky#include <stdlib.h> 46321936Shselasky#include <stdio.h> 47321936Shselasky#include <string.h> 48321936Shselasky#include <complib/cl_debug.h> 49321936Shselasky#include <iba/ib_types.h> 50321936Shselasky#include <opensm/osm_file_ids.h> 51321936Shselasky#define FILE_ID OSM_FILE_PKEY_C 52321936Shselasky#include <opensm/osm_pkey.h> 53321936Shselasky#include <opensm/osm_log.h> 54321936Shselasky#include <opensm/osm_port.h> 55321936Shselasky#include <opensm/osm_node.h> 56321936Shselasky#include <opensm/osm_switch.h> 57321936Shselasky#include <opensm/osm_helper.h> 58321936Shselasky 59321936Shselaskyvoid osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl) 60321936Shselasky{ 61321936Shselasky cl_map_construct(&p_pkey_tbl->accum_pkeys); 62321936Shselasky cl_ptr_vector_construct(&p_pkey_tbl->blocks); 63321936Shselasky cl_ptr_vector_construct(&p_pkey_tbl->new_blocks); 64321936Shselasky cl_map_construct(&p_pkey_tbl->keys); 65321936Shselasky} 66321936Shselasky 67321936Shselaskyvoid osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl) 68321936Shselasky{ 69321936Shselasky ib_pkey_table_t *p_block; 70321936Shselasky uint16_t num_blocks, i; 71321936Shselasky 72321936Shselasky num_blocks = (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks)); 73321936Shselasky for (i = 0; i < num_blocks; i++) 74321936Shselasky if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, i))) 75321936Shselasky free(p_block); 76321936Shselasky cl_ptr_vector_destroy(&p_pkey_tbl->blocks); 77321936Shselasky 78321936Shselasky num_blocks = 79321936Shselasky (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks)); 80321936Shselasky for (i = 0; i < num_blocks; i++) 81321936Shselasky if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, i))) 82321936Shselasky free(p_block); 83321936Shselasky cl_ptr_vector_destroy(&p_pkey_tbl->new_blocks); 84321936Shselasky 85321936Shselasky cl_map_remove_all(&p_pkey_tbl->accum_pkeys); 86321936Shselasky cl_map_destroy(&p_pkey_tbl->accum_pkeys); 87321936Shselasky 88321936Shselasky cl_map_remove_all(&p_pkey_tbl->keys); 89321936Shselasky cl_map_destroy(&p_pkey_tbl->keys); 90321936Shselasky} 91321936Shselasky 92321936Shselaskyib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl) 93321936Shselasky{ 94321936Shselasky cl_map_init(&p_pkey_tbl->accum_pkeys, 1); 95321936Shselasky cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1); 96321936Shselasky cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1); 97321936Shselasky cl_map_init(&p_pkey_tbl->keys, 1); 98321936Shselasky cl_qlist_init(&p_pkey_tbl->pending); 99321936Shselasky p_pkey_tbl->last_pkey_idx = 0; 100321936Shselasky p_pkey_tbl->used_blocks = 0; 101321936Shselasky p_pkey_tbl->max_blocks = 0; 102321936Shselasky p_pkey_tbl->rcv_blocks_cnt = 0; 103321936Shselasky p_pkey_tbl->indx0_pkey = 0; 104321936Shselasky return IB_SUCCESS; 105321936Shselasky} 106321936Shselasky 107321936Shselaskyvoid osm_pkey_tbl_init_new_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl) 108321936Shselasky{ 109321936Shselasky ib_pkey_table_t *p_block; 110321936Shselasky size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks); 111321936Shselasky 112321936Shselasky for (b = 0; b < num_blocks; b++) 113321936Shselasky if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b))) 114321936Shselasky memset(p_block, 0, sizeof(*p_block)); 115321936Shselasky} 116321936Shselasky 117321936Shselaskyib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl, 118321936Shselasky IN uint16_t block, IN ib_pkey_table_t * p_tbl, 119321936Shselasky IN boolean_t allow_both_pkeys) 120321936Shselasky{ 121321936Shselasky uint16_t b, i; 122321936Shselasky ib_pkey_table_t *p_pkey_block; 123321936Shselasky uint16_t *p_prev_pkey; 124321936Shselasky ib_net16_t pkey, pkey_base; 125321936Shselasky 126321936Shselasky /* make sure the block is allocated */ 127321936Shselasky if (cl_ptr_vector_get_size(&p_pkey_tbl->blocks) > block) 128321936Shselasky p_pkey_block = 129321936Shselasky (ib_pkey_table_t *) cl_ptr_vector_get(&p_pkey_tbl->blocks, 130321936Shselasky block); 131321936Shselasky else 132321936Shselasky p_pkey_block = NULL; 133321936Shselasky 134321936Shselasky if (!p_pkey_block) { 135321936Shselasky p_pkey_block = 136321936Shselasky (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t)); 137321936Shselasky if (!p_pkey_block) 138321936Shselasky return IB_ERROR; 139321936Shselasky memset(p_pkey_block, 0, sizeof(ib_pkey_table_t)); 140321936Shselasky cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block); 141321936Shselasky } 142321936Shselasky 143321936Shselasky /* sets the block values */ 144321936Shselasky memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t)); 145321936Shselasky 146321936Shselasky /* 147321936Shselasky NOTE: as the spec does not require uniqueness of PKeys in 148321936Shselasky tables there is no other way but to refresh the entire keys map. 149321936Shselasky 150321936Shselasky Moreover, if the same key exists but with full membership it should 151321936Shselasky have precedence over the key with limited membership ! 152321936Shselasky */ 153321936Shselasky cl_map_remove_all(&p_pkey_tbl->keys); 154321936Shselasky 155321936Shselasky for (b = 0; b < cl_ptr_vector_get_size(&p_pkey_tbl->blocks); b++) { 156321936Shselasky 157321936Shselasky p_pkey_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b); 158321936Shselasky if (!p_pkey_block) 159321936Shselasky continue; 160321936Shselasky 161321936Shselasky for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) { 162321936Shselasky pkey = p_pkey_block->pkey_entry[i]; 163321936Shselasky if (ib_pkey_is_invalid(pkey)) 164321936Shselasky continue; 165321936Shselasky 166321936Shselasky if (allow_both_pkeys) 167321936Shselasky pkey_base = pkey; 168321936Shselasky else 169321936Shselasky pkey_base = ib_pkey_get_base(pkey); 170321936Shselasky 171321936Shselasky /* 172321936Shselasky If allow_both_pkeys is FALSE, 173321936Shselasky ignore the PKey Full Member bit in the key but store 174321936Shselasky the pointer to the table element as the map value 175321936Shselasky */ 176321936Shselasky p_prev_pkey = cl_map_get(&p_pkey_tbl->keys, pkey_base); 177321936Shselasky 178321936Shselasky /* we only insert if no previous or it is not full member and allow_both_pkeys is FALSE */ 179321936Shselasky if ((p_prev_pkey == NULL) || 180321936Shselasky (allow_both_pkeys == FALSE && 181321936Shselasky cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey))) 182321936Shselasky cl_map_insert(&p_pkey_tbl->keys, pkey_base, 183321936Shselasky &(p_pkey_block->pkey_entry[i]) 184321936Shselasky ); 185321936Shselasky } 186321936Shselasky } 187321936Shselasky return IB_SUCCESS; 188321936Shselasky} 189321936Shselasky 190321936Shselasky/* 191321936Shselasky Store the given pkey (along with it's overall index) in the accum_pkeys array. 192321936Shselasky*/ 193321936Shselaskycl_status_t osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl, 194321936Shselasky IN uint16_t pkey, 195321936Shselasky IN uint16_t pkey_idx) 196321936Shselasky{ 197321936Shselasky uintptr_t ptr = pkey_idx + 1; /* 0 means not found so bias by 1 */ 198321936Shselasky uint16_t *p_prev_pkey_idx; 199321936Shselasky cl_status_t status = CL_SUCCESS; 200321936Shselasky 201321936Shselasky if (pkey_idx >= p_pkey_tbl->last_pkey_idx) 202321936Shselasky p_pkey_tbl->last_pkey_idx = pkey_idx + 1; 203321936Shselasky 204321936Shselasky p_prev_pkey_idx = (uint16_t *) cl_map_get(&p_pkey_tbl->accum_pkeys, pkey); 205321936Shselasky 206321936Shselasky if (p_prev_pkey_idx != NULL) 207321936Shselasky cl_map_remove(&p_pkey_tbl->accum_pkeys, pkey); 208321936Shselasky 209321936Shselasky if (cl_map_insert(&p_pkey_tbl->accum_pkeys, pkey, (void *) ptr) == NULL) 210321936Shselasky status = CL_INSUFFICIENT_MEMORY; 211321936Shselasky 212321936Shselasky return status; 213321936Shselasky 214321936Shselasky} 215321936Shselasky 216321936Shselasky/* 217321936Shselasky+ * Find the next last pkey index 218321936Shselasky+*/ 219321936Shselaskyvoid osm_pkey_find_last_accum_pkey_index(IN osm_pkey_tbl_t * p_pkey_tbl) 220321936Shselasky{ 221321936Shselasky void *ptr; 222321936Shselasky uintptr_t pkey_idx_ptr; 223321936Shselasky uint16_t pkey_idx, last_pkey_idx = 0; 224321936Shselasky cl_map_iterator_t map_iter = cl_map_head(&p_pkey_tbl->accum_pkeys); 225321936Shselasky 226321936Shselasky while (map_iter != cl_map_end(&p_pkey_tbl->accum_pkeys)) { 227321936Shselasky ptr = (uint16_t *) cl_map_obj(map_iter); 228321936Shselasky CL_ASSERT(ptr); 229321936Shselasky pkey_idx_ptr = (uintptr_t) ptr; 230321936Shselasky pkey_idx = pkey_idx_ptr; 231321936Shselasky if (pkey_idx > last_pkey_idx) 232321936Shselasky last_pkey_idx = pkey_idx; 233321936Shselasky map_iter = cl_map_next(map_iter); 234321936Shselasky } 235321936Shselasky p_pkey_tbl->last_pkey_idx = last_pkey_idx; 236321936Shselasky} 237321936Shselasky 238321936Shselasky/* 239321936Shselasky Store the given pkey in the "new" blocks array. 240321936Shselasky Also, make sure the regular block exists. 241321936Shselasky*/ 242321936Shselaskyib_api_status_t osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl, 243321936Shselasky IN uint16_t block_idx, 244321936Shselasky IN uint8_t pkey_idx, 245321936Shselasky IN uint16_t pkey) 246321936Shselasky{ 247321936Shselasky ib_pkey_table_t *p_block; 248321936Shselasky 249321936Shselasky if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) { 250321936Shselasky p_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t)); 251321936Shselasky if (!p_block) 252321936Shselasky return IB_ERROR; 253321936Shselasky memset(p_block, 0, sizeof(ib_pkey_table_t)); 254321936Shselasky cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block); 255321936Shselasky } 256321936Shselasky 257321936Shselasky p_block->pkey_entry[pkey_idx] = pkey; 258321936Shselasky if (p_pkey_tbl->used_blocks <= block_idx) 259321936Shselasky p_pkey_tbl->used_blocks = block_idx + 1; 260321936Shselasky 261321936Shselasky return IB_SUCCESS; 262321936Shselasky} 263321936Shselasky 264321936Shselaskyboolean_t osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl, 265321936Shselasky OUT uint16_t * p_block_idx, 266321936Shselasky OUT uint8_t * p_pkey_idx) 267321936Shselasky{ 268321936Shselasky ib_pkey_table_t *p_new_block; 269321936Shselasky 270321936Shselasky CL_ASSERT(p_block_idx); 271321936Shselasky CL_ASSERT(p_pkey_idx); 272321936Shselasky 273321936Shselasky while (*p_block_idx < p_pkey_tbl->max_blocks) { 274321936Shselasky if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) { 275321936Shselasky *p_pkey_idx = 0; 276321936Shselasky (*p_block_idx)++; 277321936Shselasky if (*p_block_idx >= p_pkey_tbl->max_blocks) 278321936Shselasky return FALSE; 279321936Shselasky } 280321936Shselasky 281321936Shselasky p_new_block = 282321936Shselasky osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx); 283321936Shselasky 284321936Shselasky if (!p_new_block || 285321936Shselasky ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx])) 286321936Shselasky return TRUE; 287321936Shselasky else 288321936Shselasky (*p_pkey_idx)++; 289321936Shselasky } 290321936Shselasky return FALSE; 291321936Shselasky} 292321936Shselasky 293321936Shselaskyib_api_status_t osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl, 294321936Shselasky IN uint16_t * p_pkey, 295321936Shselasky OUT uint16_t * p_block_idx, 296321936Shselasky OUT uint8_t * p_pkey_idx) 297321936Shselasky{ 298321936Shselasky uint16_t num_of_blocks; 299321936Shselasky uint16_t block_index; 300321936Shselasky ib_pkey_table_t *block; 301321936Shselasky 302321936Shselasky CL_ASSERT(p_block_idx != NULL); 303321936Shselasky CL_ASSERT(p_pkey_idx != NULL); 304321936Shselasky 305321936Shselasky num_of_blocks = (uint16_t) cl_ptr_vector_get_size(&p_pkey_tbl->blocks); 306321936Shselasky for (block_index = 0; block_index < num_of_blocks; block_index++) { 307321936Shselasky block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); 308321936Shselasky if ((block->pkey_entry <= p_pkey) && 309321936Shselasky (p_pkey < 310321936Shselasky block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) { 311321936Shselasky *p_block_idx = block_index; 312321936Shselasky *p_pkey_idx = (uint8_t) (p_pkey - block->pkey_entry); 313321936Shselasky return IB_SUCCESS; 314321936Shselasky } 315321936Shselasky } 316321936Shselasky return IB_NOT_FOUND; 317321936Shselasky} 318321936Shselasky 319321936Shselaskystatic boolean_t match_pkey(IN const ib_net16_t * pkey1, 320321936Shselasky IN const ib_net16_t * pkey2) 321321936Shselasky{ 322321936Shselasky 323321936Shselasky /* if both pkeys are not full member - this is not a match */ 324321936Shselasky if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2))) 325321936Shselasky return FALSE; 326321936Shselasky 327321936Shselasky /* compare if the bases are the same. if they are - then 328321936Shselasky this is a match */ 329321936Shselasky if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2)) 330321936Shselasky return FALSE; 331321936Shselasky 332321936Shselasky return TRUE; 333321936Shselasky} 334321936Shselasky 335321936Shselaskyboolean_t osm_physp_share_this_pkey(IN const osm_physp_t * p_physp1, 336321936Shselasky IN const osm_physp_t * p_physp2, 337321936Shselasky IN ib_net16_t pkey, 338321936Shselasky IN boolean_t allow_both_pkeys) 339321936Shselasky{ 340321936Shselasky ib_net16_t *pkey1, *pkey2; 341321936Shselasky ib_net16_t full_pkey, limited_pkey; 342321936Shselasky 343321936Shselasky if (allow_both_pkeys) { 344321936Shselasky full_pkey = pkey | IB_PKEY_TYPE_MASK; 345321936Shselasky limited_pkey = pkey & ~IB_PKEY_TYPE_MASK; 346321936Shselasky pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys, 347321936Shselasky full_pkey); 348321936Shselasky if (!pkey1) 349321936Shselasky pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys, 350321936Shselasky limited_pkey); 351321936Shselasky pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys, 352321936Shselasky full_pkey); 353321936Shselasky if (!pkey2) 354321936Shselasky pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys, 355321936Shselasky limited_pkey); 356321936Shselasky } else { 357321936Shselasky pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys, 358321936Shselasky ib_pkey_get_base(pkey)); 359321936Shselasky pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys, 360321936Shselasky ib_pkey_get_base(pkey)); 361321936Shselasky } 362321936Shselasky return (pkey1 && pkey2 && match_pkey(pkey1, pkey2)); 363321936Shselasky} 364321936Shselasky 365321936Shselaskyib_net16_t osm_physp_find_common_pkey(IN const osm_physp_t * p_physp1, 366321936Shselasky IN const osm_physp_t * p_physp2, 367321936Shselasky IN boolean_t allow_both_pkeys) 368321936Shselasky{ 369321936Shselasky ib_net16_t *pkey1, *pkey2; 370321936Shselasky uint64_t pkey1_base, pkey2_base; 371321936Shselasky const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2; 372321936Shselasky cl_map_iterator_t map_iter1, map_iter2; 373321936Shselasky 374321936Shselasky pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1); 375321936Shselasky pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2); 376321936Shselasky 377321936Shselasky map_iter1 = cl_map_head(&pkey_tbl1->keys); 378321936Shselasky map_iter2 = cl_map_head(&pkey_tbl2->keys); 379321936Shselasky 380321936Shselasky /* we rely on the fact the map are sorted by pkey */ 381321936Shselasky while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) && 382321936Shselasky (map_iter2 != cl_map_end(&pkey_tbl2->keys))) { 383321936Shselasky pkey1 = (ib_net16_t *) cl_map_obj(map_iter1); 384321936Shselasky pkey2 = (ib_net16_t *) cl_map_obj(map_iter2); 385321936Shselasky 386321936Shselasky if (match_pkey(pkey1, pkey2)) 387321936Shselasky return *pkey1; 388321936Shselasky 389321936Shselasky /* advance the lower value if they are not equal */ 390321936Shselasky pkey1_base = cl_map_key(map_iter1); 391321936Shselasky pkey2_base = cl_map_key(map_iter2); 392321936Shselasky if (pkey2_base == pkey1_base) { 393321936Shselasky map_iter1 = cl_map_next(map_iter1); 394321936Shselasky map_iter2 = cl_map_next(map_iter2); 395321936Shselasky } else if (pkey2_base < pkey1_base) 396321936Shselasky map_iter2 = cl_map_next(map_iter2); 397321936Shselasky else 398321936Shselasky map_iter1 = cl_map_next(map_iter1); 399321936Shselasky } 400321936Shselasky 401321936Shselasky if (!allow_both_pkeys) 402321936Shselasky return 0; 403321936Shselasky 404321936Shselasky /* 405321936Shselasky When using allow_both_pkeys, the keys in pkey tables are the 406321936Shselasky pkey value including membership bit. 407321936Shselasky Therefore, in order to complete the search, we also need to 408321936Shselasky compare port\s 1 full pkeys with port 2 limited pkeys, and 409321936Shselasky port 2 full pkeys with port 1 full pkeys. 410321936Shselasky */ 411321936Shselasky 412321936Shselasky map_iter1 = cl_map_head(&pkey_tbl1->keys); 413321936Shselasky map_iter2 = cl_map_head(&pkey_tbl2->keys); 414321936Shselasky 415321936Shselasky /* comparing pkey_tbl1 full with pkey_tbl2 limited */ 416321936Shselasky while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) && 417321936Shselasky (map_iter2 != cl_map_end(&pkey_tbl2->keys))) { 418321936Shselasky pkey1 = (ib_net16_t *) cl_map_obj(map_iter1); 419321936Shselasky pkey2 = (ib_net16_t *) cl_map_obj(map_iter2); 420321936Shselasky 421321936Shselasky if (!ib_pkey_is_full_member(*pkey1)) { 422321936Shselasky map_iter1 = cl_map_next(map_iter1); 423321936Shselasky continue; 424321936Shselasky } 425321936Shselasky if (ib_pkey_is_full_member(*pkey2)) { 426321936Shselasky map_iter2 = cl_map_next(map_iter2); 427321936Shselasky continue; 428321936Shselasky } 429321936Shselasky 430321936Shselasky if (match_pkey(pkey1, pkey2)) 431321936Shselasky return *pkey1; 432321936Shselasky 433321936Shselasky /* advance the lower value if they are not equal */ 434321936Shselasky pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1)); 435321936Shselasky pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2)); 436321936Shselasky if (pkey2_base == pkey1_base) { 437321936Shselasky map_iter1 = cl_map_next(map_iter1); 438321936Shselasky map_iter2 = cl_map_next(map_iter2); 439321936Shselasky } else if (pkey2_base < pkey1_base) 440321936Shselasky map_iter2 = cl_map_next(map_iter2); 441321936Shselasky else 442321936Shselasky map_iter1 = cl_map_next(map_iter1); 443321936Shselasky } 444321936Shselasky 445321936Shselasky map_iter1 = cl_map_head(&pkey_tbl1->keys); 446321936Shselasky map_iter2 = cl_map_head(&pkey_tbl2->keys); 447321936Shselasky 448321936Shselasky /* comparing pkey_tbl1 limited with pkey_tbl2 full */ 449321936Shselasky while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) && 450321936Shselasky (map_iter2 != cl_map_end(&pkey_tbl2->keys))) { 451321936Shselasky pkey1 = (ib_net16_t *) cl_map_obj(map_iter1); 452321936Shselasky pkey2 = (ib_net16_t *) cl_map_obj(map_iter2); 453321936Shselasky 454321936Shselasky if (ib_pkey_is_full_member(*pkey1)) { 455321936Shselasky map_iter1 = cl_map_next(map_iter1); 456321936Shselasky continue; 457321936Shselasky } 458321936Shselasky if (!ib_pkey_is_full_member(*pkey2)) { 459321936Shselasky map_iter2 = cl_map_next(map_iter2); 460321936Shselasky continue; 461321936Shselasky } 462321936Shselasky 463321936Shselasky if (match_pkey(pkey1, pkey2)) 464321936Shselasky return *pkey1; 465321936Shselasky 466321936Shselasky /* advance the lower value if they are not equal */ 467321936Shselasky pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1)); 468321936Shselasky pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2)); 469321936Shselasky if (pkey2_base == pkey1_base) { 470321936Shselasky map_iter1 = cl_map_next(map_iter1); 471321936Shselasky map_iter2 = cl_map_next(map_iter2); 472321936Shselasky } else if (pkey2_base < pkey1_base) 473321936Shselasky map_iter2 = cl_map_next(map_iter2); 474321936Shselasky else 475321936Shselasky map_iter1 = cl_map_next(map_iter1); 476321936Shselasky } 477321936Shselasky 478321936Shselasky return 0; 479321936Shselasky} 480321936Shselasky 481321936Shselaskyboolean_t osm_physp_share_pkey(IN osm_log_t * p_log, 482321936Shselasky IN const osm_physp_t * p_physp_1, 483321936Shselasky IN const osm_physp_t * p_physp_2, 484321936Shselasky IN boolean_t allow_both_pkeys) 485321936Shselasky{ 486321936Shselasky const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2; 487321936Shselasky 488321936Shselasky if (p_physp_1 == p_physp_2) 489321936Shselasky return TRUE; 490321936Shselasky 491321936Shselasky pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1); 492321936Shselasky pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2); 493321936Shselasky 494321936Shselasky /* 495321936Shselasky The spec: 10.9.2 does not require each phys port to have PKey Table. 496321936Shselasky So actually if it does not, we need to use the default port instead. 497321936Shselasky 498321936Shselasky HACK: meanwhile we will ignore the check 499321936Shselasky */ 500321936Shselasky if (cl_is_map_empty(&pkey_tbl1->keys) 501321936Shselasky || cl_is_map_empty(&pkey_tbl2->keys)) 502321936Shselasky return TRUE; 503321936Shselasky 504321936Shselasky return 505321936Shselasky !ib_pkey_is_invalid(osm_physp_find_common_pkey 506321936Shselasky (p_physp_1, p_physp_2, allow_both_pkeys)); 507321936Shselasky} 508321936Shselasky 509321936Shselaskyboolean_t osm_port_share_pkey(IN osm_log_t * p_log, 510321936Shselasky IN const osm_port_t * p_port_1, 511321936Shselasky IN const osm_port_t * p_port_2, 512321936Shselasky IN boolean_t allow_both_pkeys) 513321936Shselasky{ 514321936Shselasky 515321936Shselasky osm_physp_t *p_physp1, *p_physp2; 516321936Shselasky boolean_t ret; 517321936Shselasky 518321936Shselasky OSM_LOG_ENTER(p_log); 519321936Shselasky 520321936Shselasky if (!p_port_1 || !p_port_2) { 521321936Shselasky ret = FALSE; 522321936Shselasky goto Exit; 523321936Shselasky } 524321936Shselasky 525321936Shselasky p_physp1 = p_port_1->p_physp; 526321936Shselasky p_physp2 = p_port_2->p_physp; 527321936Shselasky 528321936Shselasky if (!p_physp1 || !p_physp2) { 529321936Shselasky ret = FALSE; 530321936Shselasky goto Exit; 531321936Shselasky } 532321936Shselasky 533321936Shselasky ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2, allow_both_pkeys); 534321936Shselasky 535321936ShselaskyExit: 536321936Shselasky OSM_LOG_EXIT(p_log); 537321936Shselasky return ret; 538321936Shselasky} 539321936Shselasky 540321936Shselaskyboolean_t osm_physp_has_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey, 541321936Shselasky IN const osm_physp_t * p_physp) 542321936Shselasky{ 543321936Shselasky ib_net16_t *p_pkey, pkey_base; 544321936Shselasky const osm_pkey_tbl_t *pkey_tbl; 545321936Shselasky boolean_t res = FALSE; 546321936Shselasky 547321936Shselasky OSM_LOG_ENTER(p_log); 548321936Shselasky 549321936Shselasky OSM_LOG(p_log, OSM_LOG_DEBUG, 550321936Shselasky "Search for PKey: 0x%04x\n", cl_ntoh16(pkey)); 551321936Shselasky 552321936Shselasky /* if the pkey given is an invalid pkey - return TRUE. */ 553321936Shselasky if (ib_pkey_is_invalid(pkey)) { 554321936Shselasky OSM_LOG(p_log, OSM_LOG_DEBUG, 555321936Shselasky "Given invalid PKey - we treat it loosely and allow it\n"); 556321936Shselasky res = TRUE; 557321936Shselasky goto Exit; 558321936Shselasky } 559321936Shselasky 560321936Shselasky pkey_base = ib_pkey_get_base(pkey); 561321936Shselasky 562321936Shselasky pkey_tbl = osm_physp_get_pkey_tbl(p_physp); 563321936Shselasky 564321936Shselasky p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base); 565321936Shselasky if (p_pkey) { 566321936Shselasky res = TRUE; 567321936Shselasky OSM_LOG(p_log, OSM_LOG_DEBUG, 568321936Shselasky "PKey 0x%04x was found\n", cl_ntoh16(pkey)); 569321936Shselasky } else 570321936Shselasky OSM_LOG(p_log, OSM_LOG_DEBUG, 571321936Shselasky "PKey 0x%04x was not found\n", cl_ntoh16(pkey)); 572321936Shselasky 573321936ShselaskyExit: 574321936Shselasky OSM_LOG_EXIT(p_log); 575321936Shselasky return res; 576321936Shselasky} 577321936Shselasky 578321936Shselaskyvoid osm_pkey_tbl_set_indx0_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey, 579321936Shselasky IN boolean_t full, 580321936Shselasky OUT osm_pkey_tbl_t * p_pkey_tbl) 581321936Shselasky{ 582321936Shselasky p_pkey_tbl->indx0_pkey = (full == TRUE) ? 583321936Shselasky pkey | cl_hton16(0x8000) : pkey; 584321936Shselasky OSM_LOG(p_log, OSM_LOG_DEBUG, "pkey 0x%04x set at indx0\n", 585321936Shselasky cl_ntoh16(p_pkey_tbl->indx0_pkey)); 586321936Shselasky} 587