1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff * 34219820Sjeff */ 35219820Sjeff 36219820Sjeff/* 37219820Sjeff * Abstract: 38219820Sjeff * Implementation of the P_Key Manager (Partititon Manager). 39219820Sjeff * This is part of the OpenSM. 40219820Sjeff */ 41219820Sjeff 42219820Sjeff#if HAVE_CONFIG_H 43219820Sjeff# include <config.h> 44219820Sjeff#endif /* HAVE_CONFIG_H */ 45219820Sjeff 46219820Sjeff#include <string.h> 47219820Sjeff#include <iba/ib_types.h> 48219820Sjeff#include <complib/cl_qmap.h> 49219820Sjeff#include <complib/cl_debug.h> 50219820Sjeff#include <opensm/osm_node.h> 51219820Sjeff#include <opensm/osm_switch.h> 52219820Sjeff#include <opensm/osm_partition.h> 53219820Sjeff#include <opensm/osm_opensm.h> 54219820Sjeff 55219820Sjeff/********************************************************************** 56219820Sjeff **********************************************************************/ 57219820Sjeff/* 58219820Sjeff The max number of pkey blocks for a physical port is located in 59219820Sjeff a different place for switch external ports (SwitchInfo) and the 60219820Sjeff rest of the ports (NodeInfo). 61219820Sjeff*/ 62219820Sjeffstatic uint16_t 63219820Sjeffpkey_mgr_get_physp_max_blocks(IN const osm_subn_t * p_subn, 64219820Sjeff IN const osm_physp_t * p_physp) 65219820Sjeff{ 66219820Sjeff osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); 67219820Sjeff uint16_t num_pkeys = 0; 68219820Sjeff 69219820Sjeff if (!p_node->sw || (osm_physp_get_port_num(p_physp) == 0)) 70219820Sjeff num_pkeys = cl_ntoh16(p_node->node_info.partition_cap); 71219820Sjeff else 72219820Sjeff num_pkeys = cl_ntoh16(p_node->sw->switch_info.enforce_cap); 73219820Sjeff return ((num_pkeys + 31) / 32); 74219820Sjeff} 75219820Sjeff 76219820Sjeff/********************************************************************** 77219820Sjeff **********************************************************************/ 78219820Sjeff/* 79219820Sjeff * Insert new pending pkey entry to the specific port pkey table 80219820Sjeff * pending pkeys. New entries are inserted at the back. 81219820Sjeff */ 82219820Sjeffstatic void 83219820Sjeffpkey_mgr_process_physical_port(IN osm_log_t * p_log, 84219820Sjeff IN osm_sm_t * sm, 85219820Sjeff IN const ib_net16_t pkey, 86219820Sjeff IN osm_physp_t * p_physp) 87219820Sjeff{ 88219820Sjeff osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); 89219820Sjeff osm_pkey_tbl_t *p_pkey_tbl; 90219820Sjeff ib_net16_t *p_orig_pkey; 91219820Sjeff char *stat = NULL; 92219820Sjeff osm_pending_pkey_t *p_pending; 93219820Sjeff 94219820Sjeff p_pkey_tbl = &p_physp->pkeys; 95219820Sjeff p_pending = (osm_pending_pkey_t *) malloc(sizeof(osm_pending_pkey_t)); 96219820Sjeff if (!p_pending) { 97219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0502: " 98219820Sjeff "Failed to allocate new pending pkey entry for node " 99219820Sjeff "0x%016" PRIx64 " port %u\n", 100219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 101219820Sjeff osm_physp_get_port_num(p_physp)); 102219820Sjeff return; 103219820Sjeff } 104219820Sjeff p_pending->pkey = pkey; 105219820Sjeff p_orig_pkey = cl_map_get(&p_pkey_tbl->keys, ib_pkey_get_base(pkey)); 106219820Sjeff if (!p_orig_pkey) { 107219820Sjeff p_pending->is_new = TRUE; 108219820Sjeff cl_qlist_insert_tail(&p_pkey_tbl->pending, 109219820Sjeff (cl_list_item_t *) p_pending); 110219820Sjeff stat = "inserted"; 111219820Sjeff } else { 112219820Sjeff CL_ASSERT(ib_pkey_get_base(*p_orig_pkey) == 113219820Sjeff ib_pkey_get_base(pkey)); 114219820Sjeff p_pending->is_new = FALSE; 115219820Sjeff if (osm_pkey_tbl_get_block_and_idx(p_pkey_tbl, p_orig_pkey, 116219820Sjeff &p_pending->block, 117219820Sjeff &p_pending->index) != 118219820Sjeff IB_SUCCESS) { 119219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0503: " 120219820Sjeff "Failed to obtain P_Key 0x%04x block and index for node " 121219820Sjeff "0x%016" PRIx64 " port %u\n", 122219820Sjeff ib_pkey_get_base(pkey), 123219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 124219820Sjeff osm_physp_get_port_num(p_physp)); 125219820Sjeff return; 126219820Sjeff } 127219820Sjeff cl_qlist_insert_head(&p_pkey_tbl->pending, 128219820Sjeff (cl_list_item_t *) p_pending); 129219820Sjeff stat = "updated"; 130219820Sjeff } 131219820Sjeff 132219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 133219820Sjeff "pkey 0x%04x was %s for node 0x%016" PRIx64 " port %u\n", 134219820Sjeff cl_ntoh16(pkey), stat, 135219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 136219820Sjeff osm_physp_get_port_num(p_physp)); 137219820Sjeff} 138219820Sjeff 139219820Sjeff/********************************************************************** 140219820Sjeff **********************************************************************/ 141219820Sjeffstatic void 142219820Sjeffpkey_mgr_process_partition_table(osm_log_t * p_log, osm_sm_t * sm, 143219820Sjeff const osm_prtn_t * p_prtn, 144219820Sjeff const boolean_t full) 145219820Sjeff{ 146219820Sjeff const cl_map_t *p_tbl = 147219820Sjeff full ? &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl; 148219820Sjeff cl_map_iterator_t i, i_next; 149219820Sjeff ib_net16_t pkey = p_prtn->pkey; 150219820Sjeff osm_physp_t *p_physp; 151219820Sjeff 152219820Sjeff if (full) 153219820Sjeff pkey |= cl_hton16(0x8000); 154219820Sjeff 155219820Sjeff i_next = cl_map_head(p_tbl); 156219820Sjeff while (i_next != cl_map_end(p_tbl)) { 157219820Sjeff i = i_next; 158219820Sjeff i_next = cl_map_next(i); 159219820Sjeff p_physp = cl_map_obj(i); 160219820Sjeff if (p_physp) 161219820Sjeff pkey_mgr_process_physical_port(p_log, sm, pkey, 162219820Sjeff p_physp); 163219820Sjeff } 164219820Sjeff} 165219820Sjeff 166219820Sjeff/********************************************************************** 167219820Sjeff **********************************************************************/ 168219820Sjeffstatic ib_api_status_t 169219820Sjeffpkey_mgr_update_pkey_entry(IN osm_sm_t * sm, 170219820Sjeff IN const osm_physp_t * p_physp, 171219820Sjeff IN const ib_pkey_table_t * block, 172219820Sjeff IN const uint16_t block_index) 173219820Sjeff{ 174219820Sjeff osm_madw_context_t context; 175219820Sjeff osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); 176219820Sjeff uint32_t attr_mod; 177219820Sjeff 178219820Sjeff context.pkey_context.node_guid = osm_node_get_node_guid(p_node); 179219820Sjeff context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp); 180219820Sjeff context.pkey_context.set_method = TRUE; 181219820Sjeff attr_mod = block_index; 182219820Sjeff if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) 183219820Sjeff attr_mod |= osm_physp_get_port_num(p_physp) << 16; 184219820Sjeff return osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), 185219820Sjeff (uint8_t *) block, sizeof(*block), 186219820Sjeff IB_MAD_ATTR_P_KEY_TABLE, 187219820Sjeff cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context); 188219820Sjeff} 189219820Sjeff 190219820Sjeff/********************************************************************** 191219820Sjeff **********************************************************************/ 192219820Sjeffstatic boolean_t 193219820Sjeffpkey_mgr_enforce_partition(IN osm_log_t * p_log, osm_sm_t * sm, 194219820Sjeff IN osm_physp_t * p_physp, IN const boolean_t enforce) 195219820Sjeff{ 196219820Sjeff osm_madw_context_t context; 197219820Sjeff uint8_t payload[IB_SMP_DATA_SIZE]; 198219820Sjeff ib_port_info_t *p_pi; 199219820Sjeff ib_api_status_t status; 200219820Sjeff 201219820Sjeff p_pi = &p_physp->port_info; 202219820Sjeff 203219820Sjeff if ((p_pi->vl_enforce & 0xc) == (0xc) * (enforce == TRUE)) { 204219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 205219820Sjeff "No need to update PortInfo for " 206219820Sjeff "node 0x%016" PRIx64 " port %u\n", 207219820Sjeff cl_ntoh64(osm_node_get_node_guid 208219820Sjeff (osm_physp_get_node_ptr(p_physp))), 209219820Sjeff osm_physp_get_port_num(p_physp)); 210219820Sjeff return FALSE; 211219820Sjeff } 212219820Sjeff 213219820Sjeff memset(payload, 0, IB_SMP_DATA_SIZE); 214219820Sjeff memcpy(payload, p_pi, sizeof(ib_port_info_t)); 215219820Sjeff 216219820Sjeff p_pi = (ib_port_info_t *) payload; 217219820Sjeff if (enforce == TRUE) 218219820Sjeff p_pi->vl_enforce |= 0xc; 219219820Sjeff else 220219820Sjeff p_pi->vl_enforce &= ~0xc; 221219820Sjeff p_pi->state_info2 = 0; 222219820Sjeff ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE); 223219820Sjeff 224219820Sjeff context.pi_context.node_guid = 225219820Sjeff osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp)); 226219820Sjeff context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); 227219820Sjeff context.pi_context.set_method = TRUE; 228219820Sjeff context.pi_context.light_sweep = FALSE; 229219820Sjeff context.pi_context.active_transition = FALSE; 230219820Sjeff 231219820Sjeff status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), 232219820Sjeff payload, sizeof(payload), 233219820Sjeff IB_MAD_ATTR_PORT_INFO, 234219820Sjeff cl_hton32(osm_physp_get_port_num(p_physp)), 235219820Sjeff CL_DISP_MSGID_NONE, &context); 236219820Sjeff if (status != IB_SUCCESS) { 237219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0511: " 238219820Sjeff "Failed to set PortInfo for " 239219820Sjeff "node 0x%016" PRIx64 " port %u\n", 240219820Sjeff cl_ntoh64(osm_node_get_node_guid 241219820Sjeff (osm_physp_get_node_ptr(p_physp))), 242219820Sjeff osm_physp_get_port_num(p_physp)); 243219820Sjeff return FALSE; 244219820Sjeff } else { 245219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 246219820Sjeff "Set PortInfo for node 0x%016" PRIx64 " port %u\n", 247219820Sjeff cl_ntoh64(osm_node_get_node_guid 248219820Sjeff (osm_physp_get_node_ptr(p_physp))), 249219820Sjeff osm_physp_get_port_num(p_physp)); 250219820Sjeff return TRUE; 251219820Sjeff } 252219820Sjeff} 253219820Sjeff 254219820Sjeff/********************************************************************** 255219820Sjeff **********************************************************************/ 256219820Sjeffstatic boolean_t pkey_mgr_update_port(osm_log_t * p_log, osm_sm_t * sm, 257219820Sjeff const osm_port_t * const p_port) 258219820Sjeff{ 259219820Sjeff osm_physp_t *p_physp; 260219820Sjeff osm_node_t *p_node; 261219820Sjeff ib_pkey_table_t *block, *new_block; 262219820Sjeff osm_pkey_tbl_t *p_pkey_tbl; 263219820Sjeff uint16_t block_index; 264219820Sjeff uint8_t pkey_index; 265219820Sjeff uint16_t last_free_block_index = 0; 266219820Sjeff uint8_t last_free_pkey_index = 0; 267219820Sjeff uint16_t num_of_blocks; 268219820Sjeff uint16_t max_num_of_blocks; 269219820Sjeff ib_api_status_t status; 270219820Sjeff boolean_t ret_val = FALSE; 271219820Sjeff osm_pending_pkey_t *p_pending; 272219820Sjeff boolean_t found; 273219820Sjeff ib_pkey_table_t empty_block; 274219820Sjeff 275219820Sjeff memset(&empty_block, 0, sizeof(ib_pkey_table_t)); 276219820Sjeff 277219820Sjeff p_physp = p_port->p_physp; 278219820Sjeff if (!p_physp) 279219820Sjeff return FALSE; 280219820Sjeff 281219820Sjeff p_node = osm_physp_get_node_ptr(p_physp); 282219820Sjeff p_pkey_tbl = &p_physp->pkeys; 283219820Sjeff num_of_blocks = osm_pkey_tbl_get_num_blocks(p_pkey_tbl); 284219820Sjeff max_num_of_blocks = 285219820Sjeff pkey_mgr_get_physp_max_blocks(sm->p_subn, p_physp); 286219820Sjeff if (p_pkey_tbl->max_blocks > max_num_of_blocks) { 287219820Sjeff OSM_LOG(p_log, OSM_LOG_INFO, 288219820Sjeff "Max number of blocks reduced from %u to %u " 289219820Sjeff "for node 0x%016" PRIx64 " port %u\n", 290219820Sjeff p_pkey_tbl->max_blocks, max_num_of_blocks, 291219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 292219820Sjeff osm_physp_get_port_num(p_physp)); 293219820Sjeff } 294219820Sjeff p_pkey_tbl->max_blocks = max_num_of_blocks; 295219820Sjeff 296219820Sjeff osm_pkey_tbl_init_new_blocks(p_pkey_tbl); 297219820Sjeff p_pkey_tbl->used_blocks = 0; 298219820Sjeff 299219820Sjeff /* 300219820Sjeff process every pending pkey in order - 301219820Sjeff first must be "updated" last are "new" 302219820Sjeff */ 303219820Sjeff p_pending = 304219820Sjeff (osm_pending_pkey_t *) cl_qlist_remove_head(&p_pkey_tbl->pending); 305219820Sjeff while (p_pending != 306219820Sjeff (osm_pending_pkey_t *) cl_qlist_end(&p_pkey_tbl->pending)) { 307219820Sjeff if (p_pending->is_new == FALSE) { 308219820Sjeff block_index = p_pending->block; 309219820Sjeff pkey_index = p_pending->index; 310219820Sjeff found = TRUE; 311219820Sjeff } else { 312219820Sjeff found = osm_pkey_find_next_free_entry(p_pkey_tbl, 313219820Sjeff &last_free_block_index, 314219820Sjeff &last_free_pkey_index); 315219820Sjeff if (!found) { 316219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0504: " 317219820Sjeff "Failed to find empty space for new pkey 0x%04x " 318219820Sjeff "for node 0x%016" PRIx64 " port %u\n", 319219820Sjeff cl_ntoh16(p_pending->pkey), 320219820Sjeff cl_ntoh64(osm_node_get_node_guid 321219820Sjeff (p_node)), 322219820Sjeff osm_physp_get_port_num(p_physp)); 323219820Sjeff } else { 324219820Sjeff block_index = last_free_block_index; 325219820Sjeff pkey_index = last_free_pkey_index++; 326219820Sjeff } 327219820Sjeff } 328219820Sjeff 329219820Sjeff if (found) { 330219820Sjeff if (IB_SUCCESS != 331219820Sjeff osm_pkey_tbl_set_new_entry(p_pkey_tbl, block_index, 332219820Sjeff pkey_index, 333219820Sjeff p_pending->pkey)) { 334219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0505: " 335219820Sjeff "Failed to set PKey 0x%04x in block %u idx %u " 336219820Sjeff "for node 0x%016" PRIx64 " port %u\n", 337219820Sjeff cl_ntoh16(p_pending->pkey), block_index, 338219820Sjeff pkey_index, 339219820Sjeff cl_ntoh64(osm_node_get_node_guid 340219820Sjeff (p_node)), 341219820Sjeff osm_physp_get_port_num(p_physp)); 342219820Sjeff } 343219820Sjeff } 344219820Sjeff 345219820Sjeff free(p_pending); 346219820Sjeff p_pending = 347219820Sjeff (osm_pending_pkey_t *) cl_qlist_remove_head(&p_pkey_tbl-> 348219820Sjeff pending); 349219820Sjeff } 350219820Sjeff 351219820Sjeff /* now look for changes and store */ 352219820Sjeff for (block_index = 0; block_index < num_of_blocks; block_index++) { 353219820Sjeff block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); 354219820Sjeff new_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index); 355219820Sjeff if (!new_block) 356219820Sjeff new_block = &empty_block; 357219820Sjeff if (block && !memcmp(new_block, block, sizeof(*block))) 358219820Sjeff continue; 359219820Sjeff 360219820Sjeff status = 361219820Sjeff pkey_mgr_update_pkey_entry(sm, p_physp, new_block, 362219820Sjeff block_index); 363219820Sjeff if (status == IB_SUCCESS) { 364219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 365219820Sjeff "Updated pkey table block %d for node 0x%016" 366219820Sjeff PRIx64 " port %u\n", block_index, 367219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 368219820Sjeff osm_physp_get_port_num(p_physp)); 369219820Sjeff ret_val = TRUE; 370219820Sjeff } else { 371219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0506: " 372219820Sjeff "pkey_mgr_update_pkey_entry() failed to update " 373219820Sjeff "pkey table block %d for node 0x%016" PRIx64 374219820Sjeff " port %u\n", block_index, 375219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 376219820Sjeff osm_physp_get_port_num(p_physp)); 377219820Sjeff } 378219820Sjeff } 379219820Sjeff 380219820Sjeff return ret_val; 381219820Sjeff} 382219820Sjeff 383219820Sjeff/********************************************************************** 384219820Sjeff **********************************************************************/ 385219820Sjeffstatic boolean_t 386219820Sjeffpkey_mgr_update_peer_port(osm_log_t * p_log, osm_sm_t * sm, 387219820Sjeff const osm_subn_t * p_subn, 388219820Sjeff const osm_port_t * const p_port, boolean_t enforce) 389219820Sjeff{ 390219820Sjeff osm_physp_t *p_physp, *peer; 391219820Sjeff osm_node_t *p_node; 392219820Sjeff ib_pkey_table_t *block, *peer_block; 393219820Sjeff const osm_pkey_tbl_t *p_pkey_tbl; 394219820Sjeff osm_pkey_tbl_t *p_peer_pkey_tbl; 395219820Sjeff uint16_t block_index; 396219820Sjeff uint16_t num_of_blocks; 397219820Sjeff uint16_t peer_max_blocks; 398219820Sjeff ib_api_status_t status = IB_SUCCESS; 399219820Sjeff boolean_t ret_val = FALSE; 400219820Sjeff boolean_t port_info_set = FALSE; 401219820Sjeff ib_pkey_table_t empty_block; 402219820Sjeff 403219820Sjeff memset(&empty_block, 0, sizeof(ib_pkey_table_t)); 404219820Sjeff 405219820Sjeff p_physp = p_port->p_physp; 406219820Sjeff if (!p_physp) 407219820Sjeff return FALSE; 408219820Sjeff peer = osm_physp_get_remote(p_physp); 409219820Sjeff if (!peer) 410219820Sjeff return FALSE; 411219820Sjeff p_node = osm_physp_get_node_ptr(peer); 412219820Sjeff if (!p_node->sw || !p_node->sw->switch_info.enforce_cap) 413219820Sjeff return FALSE; 414219820Sjeff 415219820Sjeff p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp); 416219820Sjeff p_peer_pkey_tbl = &peer->pkeys; 417219820Sjeff num_of_blocks = osm_pkey_tbl_get_num_blocks(p_pkey_tbl); 418219820Sjeff peer_max_blocks = pkey_mgr_get_physp_max_blocks(p_subn, peer); 419219820Sjeff if (peer_max_blocks < p_pkey_tbl->used_blocks) { 420219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0508: " 421219820Sjeff "Not enough pkey entries (%u < %u) on switch 0x%016" 422219820Sjeff PRIx64 " port %u. Clearing Enforcement bit\n", 423219820Sjeff peer_max_blocks, num_of_blocks, 424219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 425219820Sjeff osm_physp_get_port_num(peer)); 426219820Sjeff enforce = FALSE; 427219820Sjeff } 428219820Sjeff 429219820Sjeff if (pkey_mgr_enforce_partition(p_log, sm, peer, enforce)) 430219820Sjeff port_info_set = TRUE; 431219820Sjeff 432219820Sjeff if (enforce == FALSE) 433219820Sjeff return port_info_set; 434219820Sjeff 435219820Sjeff p_peer_pkey_tbl->used_blocks = p_pkey_tbl->used_blocks; 436219820Sjeff for (block_index = 0; block_index < p_pkey_tbl->used_blocks; 437219820Sjeff block_index++) { 438219820Sjeff block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index); 439219820Sjeff if (!block) 440219820Sjeff block = &empty_block; 441219820Sjeff 442219820Sjeff peer_block = 443219820Sjeff osm_pkey_tbl_block_get(p_peer_pkey_tbl, block_index); 444219820Sjeff if (!peer_block 445219820Sjeff || memcmp(peer_block, block, sizeof(*peer_block))) { 446219820Sjeff status = 447219820Sjeff pkey_mgr_update_pkey_entry(sm, peer, block, 448219820Sjeff block_index); 449219820Sjeff if (status == IB_SUCCESS) 450219820Sjeff ret_val = TRUE; 451219820Sjeff else 452219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0509: " 453219820Sjeff "pkey_mgr_update_pkey_entry() failed to update " 454219820Sjeff "pkey table block %d for node 0x%016" 455219820Sjeff PRIx64 " port %u\n", block_index, 456219820Sjeff cl_ntoh64(osm_node_get_node_guid 457219820Sjeff (p_node)), 458219820Sjeff osm_physp_get_port_num(peer)); 459219820Sjeff } 460219820Sjeff } 461219820Sjeff 462219820Sjeff if (ret_val) 463219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 464219820Sjeff "Pkey table was updated for node 0x%016" PRIx64 465219820Sjeff " port %u\n", 466219820Sjeff cl_ntoh64(osm_node_get_node_guid(p_node)), 467219820Sjeff osm_physp_get_port_num(peer)); 468219820Sjeff 469219820Sjeff if (port_info_set) 470219820Sjeff return TRUE; 471219820Sjeff return ret_val; 472219820Sjeff} 473219820Sjeff 474219820Sjeff/********************************************************************** 475219820Sjeff **********************************************************************/ 476219820Sjeffosm_signal_t osm_pkey_mgr_process(IN osm_opensm_t * p_osm) 477219820Sjeff{ 478219820Sjeff cl_qmap_t *p_tbl; 479219820Sjeff cl_map_item_t *p_next; 480219820Sjeff osm_prtn_t *p_prtn; 481219820Sjeff osm_port_t *p_port; 482219820Sjeff osm_signal_t signal = OSM_SIGNAL_DONE; 483219820Sjeff 484219820Sjeff CL_ASSERT(p_osm); 485219820Sjeff 486219820Sjeff OSM_LOG_ENTER(&p_osm->log); 487219820Sjeff 488219820Sjeff CL_PLOCK_EXCL_ACQUIRE(&p_osm->lock); 489219820Sjeff 490219820Sjeff if (osm_prtn_make_partitions(&p_osm->log, &p_osm->subn) != IB_SUCCESS) { 491219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 0510: " 492219820Sjeff "osm_prtn_make_partitions() failed\n"); 493219820Sjeff goto _err; 494219820Sjeff } 495219820Sjeff 496219820Sjeff /* populate the pending pkey entries by scanning all partitions */ 497219820Sjeff p_tbl = &p_osm->subn.prtn_pkey_tbl; 498219820Sjeff p_next = cl_qmap_head(p_tbl); 499219820Sjeff while (p_next != cl_qmap_end(p_tbl)) { 500219820Sjeff p_prtn = (osm_prtn_t *) p_next; 501219820Sjeff p_next = cl_qmap_next(p_next); 502219820Sjeff pkey_mgr_process_partition_table(&p_osm->log, &p_osm->sm, 503219820Sjeff p_prtn, FALSE); 504219820Sjeff pkey_mgr_process_partition_table(&p_osm->log, &p_osm->sm, 505219820Sjeff p_prtn, TRUE); 506219820Sjeff } 507219820Sjeff 508219820Sjeff /* calculate and set new pkey tables */ 509219820Sjeff p_tbl = &p_osm->subn.port_guid_tbl; 510219820Sjeff p_next = cl_qmap_head(p_tbl); 511219820Sjeff while (p_next != cl_qmap_end(p_tbl)) { 512219820Sjeff p_port = (osm_port_t *) p_next; 513219820Sjeff p_next = cl_qmap_next(p_next); 514219820Sjeff if (pkey_mgr_update_port(&p_osm->log, &p_osm->sm, p_port)) 515219820Sjeff signal = OSM_SIGNAL_DONE_PENDING; 516219820Sjeff if ((osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_SWITCH) 517219820Sjeff && pkey_mgr_update_peer_port(&p_osm->log, &p_osm->sm, 518219820Sjeff &p_osm->subn, p_port, 519219820Sjeff !p_osm->subn.opt. 520219820Sjeff no_partition_enforcement)) 521219820Sjeff signal = OSM_SIGNAL_DONE_PENDING; 522219820Sjeff } 523219820Sjeff 524219820Sjeff_err: 525219820Sjeff CL_PLOCK_RELEASE(&p_osm->lock); 526219820Sjeff OSM_LOG_EXIT(&p_osm->log); 527219820Sjeff return (signal); 528219820Sjeff} 529