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 osm_lid_mgr_t. 39219820Sjeff * This file implements the LID Manager object which is responsible for 40219820Sjeff * assigning LIDs to all ports on the subnet. 41219820Sjeff * 42219820Sjeff * DATA STRUCTURES: 43219820Sjeff * p_subn->port_lid_tbl : a vector pointing from lid to its port. 44219820Sjeff * osm db guid2lid domain : a hash from guid to lid (min lid). 45219820Sjeff * p_subn->port_guid_tbl : a map from guid to discovered port obj. 46219820Sjeff * 47219820Sjeff * ALGORITHM: 48219820Sjeff * 49219820Sjeff * 0. we define a function to obtain the correct port lid: 50219820Sjeff * __osm_lid_mgr_get_port_lid( p_mgr, port, &min_lid ): 51219820Sjeff * 0.1 if the port info lid matches the guid2lid return 0 52219820Sjeff * 0.2 if the port info has a lid and that range is empty in 53219820Sjeff * port_lid_tbl, return 0 and update the port_lid_tbl and 54219820Sjeff * guid2lid 55219820Sjeff * 0.3 else find an empty space in port_lid_tbl, update the 56219820Sjeff * port_lid_tbl and guid2lid, return 1 to flag a change required. 57219820Sjeff * 58219820Sjeff * 1. During initialization: 59219820Sjeff * 1.1 initialize the guid2lid database domain. 60219820Sjeff * 1.2 if reassign_lid is not set: 61219820Sjeff * 1.2.1 read the persistent data for the domain. 62219820Sjeff * 1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1) 63219820Sjeff * 64219820Sjeff * 2. During SM port lid assignment: 65219820Sjeff * 2.1 if reassign_lids is set, make it 2^lmc 66219820Sjeff * 2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid 67219820Sjeff * 2.3 call __osm_lid_mgr_get_port_lid the SM port 68219820Sjeff * 2.4 set the port info 69219820Sjeff * 70219820Sjeff * 3. During all other ports lid assignment: 71219820Sjeff * 3.1 go through all ports in the subnet 72219820Sjeff * 3.1.1 call __osm_lid_mgr_get_port_min_lid 73219820Sjeff * 3.1.2 if a change required send the port info 74219820Sjeff * 3.2 if any change send the signal PENDING... 75219820Sjeff * 76219820Sjeff * 4. Store the guid2lid 77219820Sjeff */ 78219820Sjeff 79219820Sjeff#if HAVE_CONFIG_H 80219820Sjeff# include <config.h> 81219820Sjeff#endif /* HAVE_CONFIG_H */ 82219820Sjeff 83219820Sjeff#include <stdlib.h> 84219820Sjeff#include <string.h> 85219820Sjeff#include <iba/ib_types.h> 86219820Sjeff#include <complib/cl_qmap.h> 87219820Sjeff#include <complib/cl_debug.h> 88219820Sjeff#include <opensm/osm_lid_mgr.h> 89219820Sjeff#include <opensm/osm_sm.h> 90219820Sjeff#include <opensm/osm_log.h> 91219820Sjeff#include <opensm/osm_node.h> 92219820Sjeff#include <opensm/osm_switch.h> 93219820Sjeff#include <opensm/osm_helper.h> 94219820Sjeff#include <opensm/osm_msgdef.h> 95219820Sjeff#include <vendor/osm_vendor_api.h> 96219820Sjeff#include <opensm/osm_db_pack.h> 97219820Sjeff 98219820Sjeff/********************************************************************** 99219820Sjeff lid range item of qlist 100219820Sjeff **********************************************************************/ 101219820Sjefftypedef struct osm_lid_mgr_range { 102219820Sjeff cl_list_item_t item; 103219820Sjeff uint16_t min_lid; 104219820Sjeff uint16_t max_lid; 105219820Sjeff} osm_lid_mgr_range_t; 106219820Sjeff 107219820Sjeff/********************************************************************** 108219820Sjeff **********************************************************************/ 109219820Sjeffvoid osm_lid_mgr_construct(IN osm_lid_mgr_t * const p_mgr) 110219820Sjeff{ 111219820Sjeff memset(p_mgr, 0, sizeof(*p_mgr)); 112219820Sjeff cl_ptr_vector_construct(&p_mgr->used_lids); 113219820Sjeff} 114219820Sjeff 115219820Sjeff/********************************************************************** 116219820Sjeff **********************************************************************/ 117219820Sjeffvoid osm_lid_mgr_destroy(IN osm_lid_mgr_t * const p_mgr) 118219820Sjeff{ 119219820Sjeff cl_list_item_t *p_item; 120219820Sjeff 121219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 122219820Sjeff 123219820Sjeff cl_ptr_vector_destroy(&p_mgr->used_lids); 124219820Sjeff p_item = cl_qlist_remove_head(&p_mgr->free_ranges); 125219820Sjeff while (p_item != cl_qlist_end(&p_mgr->free_ranges)) { 126219820Sjeff free((osm_lid_mgr_range_t *) p_item); 127219820Sjeff p_item = cl_qlist_remove_head(&p_mgr->free_ranges); 128219820Sjeff } 129219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 130219820Sjeff} 131219820Sjeff 132219820Sjeff/********************************************************************** 133219820SjeffValidate the guid to lid data by making sure that under the current 134219820SjeffLMC we did not get duplicates. If we do flag them as errors and remove 135219820Sjeffthe entry. 136219820Sjeff**********************************************************************/ 137219820Sjeffstatic void __osm_lid_mgr_validate_db(IN osm_lid_mgr_t * p_mgr) 138219820Sjeff{ 139219820Sjeff cl_qlist_t guids; 140219820Sjeff osm_db_guid_elem_t *p_item; 141219820Sjeff uint16_t lid; 142219820Sjeff uint16_t min_lid; 143219820Sjeff uint16_t max_lid; 144219820Sjeff uint16_t lmc_mask; 145219820Sjeff boolean_t lids_ok; 146219820Sjeff 147219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 148219820Sjeff 149219820Sjeff if (p_mgr->p_subn->opt.lmc) 150219820Sjeff lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); 151219820Sjeff else 152219820Sjeff lmc_mask = 0xffff; 153219820Sjeff 154219820Sjeff cl_qlist_init(&guids); 155219820Sjeff 156219820Sjeff if (osm_db_guid2lid_guids(p_mgr->p_g2l, &guids)) { 157219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0310: " 158219820Sjeff "could not get guid list\n"); 159219820Sjeff goto Exit; 160219820Sjeff } 161219820Sjeff 162219820Sjeff p_item = (osm_db_guid_elem_t *) cl_qlist_remove_head(&guids); 163219820Sjeff while ((cl_list_item_t *) p_item != cl_qlist_end(&guids)) { 164219820Sjeff if (osm_db_guid2lid_get 165219820Sjeff (p_mgr->p_g2l, p_item->guid, &min_lid, &max_lid)) 166219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0311: " 167219820Sjeff "could not get lid for guid:0x%016" PRIx64 "\n", 168219820Sjeff p_item->guid); 169219820Sjeff else { 170219820Sjeff lids_ok = TRUE; 171219820Sjeff 172219820Sjeff if ((min_lid > max_lid) || (min_lid == 0) 173219820Sjeff || (p_item->guid == 0) 174219820Sjeff || (max_lid > p_mgr->p_subn->max_ucast_lid_ho)) { 175219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0312: " 176219820Sjeff "Illegal LID range [%u:%u] for " 177219820Sjeff "guid:0x%016" PRIx64 "\n", min_lid, 178219820Sjeff max_lid, p_item->guid); 179219820Sjeff lids_ok = FALSE; 180219820Sjeff } else if ((min_lid != max_lid) 181219820Sjeff && ((min_lid & lmc_mask) != min_lid)) { 182219820Sjeff /* check that if the lids define a range that is valid 183219820Sjeff for the current LMC mask */ 184219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0313: " 185219820Sjeff "LID range [%u:%u] for guid:0x%016" 186219820Sjeff PRIx64 187219820Sjeff " is not aligned according to mask:0x%04x\n", 188219820Sjeff min_lid, max_lid, p_item->guid, 189219820Sjeff lmc_mask); 190219820Sjeff lids_ok = FALSE; 191219820Sjeff } else { 192219820Sjeff /* check if the lids were not previously assigned */ 193219820Sjeff for (lid = min_lid; lid <= max_lid; lid++) { 194219820Sjeff if ((cl_ptr_vector_get_size 195219820Sjeff (&p_mgr->used_lids) > lid) 196219820Sjeff && 197219820Sjeff (cl_ptr_vector_get 198219820Sjeff (&p_mgr->used_lids, lid))) { 199219820Sjeff OSM_LOG(p_mgr->p_log, 200219820Sjeff OSM_LOG_ERROR, "ERR 0314: " 201219820Sjeff "0x%04x for guid:0x%016" 202219820Sjeff PRIx64 203219820Sjeff " was previously used\n", 204219820Sjeff lid, p_item->guid); 205219820Sjeff lids_ok = FALSE; 206219820Sjeff } 207219820Sjeff } 208219820Sjeff } 209219820Sjeff 210219820Sjeff if (!lids_ok) { 211219820Sjeff if (osm_db_guid2lid_delete 212219820Sjeff (p_mgr->p_g2l, p_item->guid)) 213219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, 214219820Sjeff "ERR 0315: " 215219820Sjeff "failed to delete entry for " 216219820Sjeff "guid:0x%016" PRIx64 "\n", 217219820Sjeff p_item->guid); 218219820Sjeff } else { 219219820Sjeff /* mark it was visited */ 220219820Sjeff for (lid = min_lid; lid <= max_lid; lid++) 221219820Sjeff cl_ptr_vector_set(&p_mgr->used_lids, 222219820Sjeff lid, (void *)1); 223219820Sjeff } 224219820Sjeff } /* got a lid */ 225219820Sjeff free(p_item); 226219820Sjeff p_item = (osm_db_guid_elem_t *) cl_qlist_remove_head(&guids); 227219820Sjeff } /* all guids */ 228219820SjeffExit: 229219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 230219820Sjeff} 231219820Sjeff 232219820Sjeff/********************************************************************** 233219820Sjeff **********************************************************************/ 234219820Sjeffib_api_status_t 235219820Sjeffosm_lid_mgr_init(IN osm_lid_mgr_t * const p_mgr, IN osm_sm_t *sm) 236219820Sjeff{ 237219820Sjeff ib_api_status_t status = IB_SUCCESS; 238219820Sjeff 239219820Sjeff OSM_LOG_ENTER(sm->p_log); 240219820Sjeff 241219820Sjeff osm_lid_mgr_construct(p_mgr); 242219820Sjeff 243219820Sjeff p_mgr->sm = sm; 244219820Sjeff p_mgr->p_log = sm->p_log; 245219820Sjeff p_mgr->p_subn = sm->p_subn; 246219820Sjeff p_mgr->p_db = sm->p_db; 247219820Sjeff p_mgr->p_lock = sm->p_lock; 248219820Sjeff 249219820Sjeff /* we initialize and restore the db domain of guid to lid map */ 250219820Sjeff p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "/guid2lid"); 251219820Sjeff if (!p_mgr->p_g2l) { 252219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0316: " 253219820Sjeff "Error initializing Guid-to-Lid persistent database\n"); 254219820Sjeff status = IB_ERROR; 255219820Sjeff goto Exit; 256219820Sjeff } 257219820Sjeff 258219820Sjeff cl_ptr_vector_init(&p_mgr->used_lids, 100, 40); 259219820Sjeff cl_qlist_init(&p_mgr->free_ranges); 260219820Sjeff 261219820Sjeff /* we use the stored guid to lid table if not forced to reassign */ 262219820Sjeff if (!p_mgr->p_subn->opt.reassign_lids) { 263219820Sjeff if (osm_db_restore(p_mgr->p_g2l)) { 264219820Sjeff#ifndef __WIN__ 265219820Sjeff /* 266219820Sjeff * When Windows is BSODing, it might corrupt files that 267219820Sjeff * were previously opened for writing, even if the files 268219820Sjeff * are closed, so we might see corrupted guid2lid file. 269219820Sjeff */ 270219820Sjeff if (p_mgr->p_subn->opt.exit_on_fatal) { 271219820Sjeff osm_log(p_mgr->p_log, OSM_LOG_SYS, 272219820Sjeff "FATAL: Error restoring Guid-to-Lid " 273219820Sjeff "persistent database\n"); 274219820Sjeff status = IB_ERROR; 275219820Sjeff goto Exit; 276219820Sjeff } else 277219820Sjeff#endif 278219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, 279219820Sjeff "ERR 0317: Error restoring Guid-to-Lid " 280219820Sjeff "persistent database\n"); 281219820Sjeff } 282219820Sjeff 283219820Sjeff /* we need to make sure we did not get duplicates with 284219820Sjeff current lmc */ 285219820Sjeff __osm_lid_mgr_validate_db(p_mgr); 286219820Sjeff } 287219820Sjeff 288219820SjeffExit: 289219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 290219820Sjeff return (status); 291219820Sjeff} 292219820Sjeff 293219820Sjeffstatic uint16_t __osm_trim_lid(IN uint16_t lid) 294219820Sjeff{ 295219820Sjeff if ((lid > IB_LID_UCAST_END_HO) || (lid < IB_LID_UCAST_START_HO)) 296219820Sjeff return 0; 297219820Sjeff return lid; 298219820Sjeff} 299219820Sjeff 300219820Sjeff/********************************************************************** 301219820Sjeff initialize the manager for a new sweep: 302219820Sjeff scans the known persistent assignment and port_lid_tbl 303219820Sjeff re-calculate all empty ranges. 304219820Sjeff cleanup invalid port_lid_tbl entries 305219820Sjeff**********************************************************************/ 306219820Sjeffstatic int __osm_lid_mgr_init_sweep(IN osm_lid_mgr_t * const p_mgr) 307219820Sjeff{ 308219820Sjeff cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl; 309219820Sjeff cl_ptr_vector_t *p_persistent_vec = &p_mgr->used_lids; 310219820Sjeff uint16_t max_defined_lid; 311219820Sjeff uint16_t max_persistent_lid; 312219820Sjeff uint16_t max_discovered_lid; 313219820Sjeff uint16_t lid; 314219820Sjeff uint16_t disc_min_lid; 315219820Sjeff uint16_t disc_max_lid; 316219820Sjeff uint16_t db_min_lid; 317219820Sjeff uint16_t db_max_lid; 318219820Sjeff int status = 0; 319219820Sjeff cl_list_item_t *p_item; 320219820Sjeff boolean_t is_free; 321219820Sjeff osm_lid_mgr_range_t *p_range = NULL; 322219820Sjeff osm_port_t *p_port; 323219820Sjeff cl_qmap_t *p_port_guid_tbl; 324219820Sjeff uint8_t lmc_num_lids = (uint8_t) (1 << p_mgr->p_subn->opt.lmc); 325219820Sjeff uint16_t lmc_mask; 326219820Sjeff uint16_t req_lid, num_lids; 327219820Sjeff 328219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 329219820Sjeff 330219820Sjeff if (p_mgr->p_subn->opt.lmc) 331219820Sjeff lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); 332219820Sjeff else 333219820Sjeff lmc_mask = 0xffff; 334219820Sjeff 335219820Sjeff /* if we came out of standby we need to discard any previous guid2lid 336219820Sjeff info we might have. 337219820Sjeff Do this only if the honor_guid2lid_file option is FALSE. If not, then 338219820Sjeff need to honor this file. */ 339219820Sjeff if (p_mgr->p_subn->coming_out_of_standby == TRUE) { 340219820Sjeff if (p_mgr->p_subn->opt.honor_guid2lid_file == FALSE) { 341219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 342219820Sjeff "Ignore guid2lid file when coming out of standby\n"); 343219820Sjeff osm_db_clear(p_mgr->p_g2l); 344219820Sjeff for (lid = 0; 345219820Sjeff lid < cl_ptr_vector_get_size(&p_mgr->used_lids); 346219820Sjeff lid++) 347219820Sjeff cl_ptr_vector_set(p_persistent_vec, lid, NULL); 348219820Sjeff } else { 349219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 350219820Sjeff "Honor current guid2lid file when coming out " 351219820Sjeff "of standby\n"); 352219820Sjeff osm_db_clear(p_mgr->p_g2l); 353219820Sjeff if (osm_db_restore(p_mgr->p_g2l)) 354219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0306: " 355219820Sjeff "Error restoring Guid-to-Lid " 356219820Sjeff "persistent database. Ignoring it\n"); 357219820Sjeff } 358219820Sjeff } 359219820Sjeff 360219820Sjeff /* we need to cleanup the empty ranges list */ 361219820Sjeff p_item = cl_qlist_remove_head(&p_mgr->free_ranges); 362219820Sjeff while (p_item != cl_qlist_end(&p_mgr->free_ranges)) { 363219820Sjeff free((osm_lid_mgr_range_t *) p_item); 364219820Sjeff p_item = cl_qlist_remove_head(&p_mgr->free_ranges); 365219820Sjeff } 366219820Sjeff 367219820Sjeff /* first clean up the port_by_lid_tbl */ 368219820Sjeff for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++) 369219820Sjeff cl_ptr_vector_set(p_discovered_vec, lid, NULL); 370219820Sjeff 371219820Sjeff /* we if are in the first sweep and in reassign lids mode 372219820Sjeff we should ignore all the available info and simply define one 373219820Sjeff huge empty range */ 374219820Sjeff if ((p_mgr->p_subn->first_time_master_sweep == TRUE) && 375219820Sjeff (p_mgr->p_subn->opt.reassign_lids == TRUE)) { 376219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 377219820Sjeff "Skipping all lids as we are reassigning them\n"); 378219820Sjeff p_range = 379219820Sjeff (osm_lid_mgr_range_t *) malloc(sizeof(osm_lid_mgr_range_t)); 380219820Sjeff if (p_range) 381219820Sjeff p_range->min_lid = 1; 382219820Sjeff goto AfterScanningLids; 383219820Sjeff } 384219820Sjeff 385219820Sjeff /* go over all discovered ports and mark their entries */ 386219820Sjeff p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; 387219820Sjeff 388219820Sjeff for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); 389219820Sjeff p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl); 390219820Sjeff p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { 391219820Sjeff osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid); 392219820Sjeff disc_min_lid = __osm_trim_lid(disc_min_lid); 393219820Sjeff disc_max_lid = __osm_trim_lid(disc_max_lid); 394219820Sjeff for (lid = disc_min_lid; lid <= disc_max_lid; lid++) 395219820Sjeff cl_ptr_vector_set(p_discovered_vec, lid, p_port); 396219820Sjeff /* make sure the guid2lid entry is valid. If not, clean it. */ 397219820Sjeff if (!osm_db_guid2lid_get(p_mgr->p_g2l, 398219820Sjeff cl_ntoh64(osm_port_get_guid(p_port)), 399219820Sjeff &db_min_lid, &db_max_lid)) { 400219820Sjeff if (!p_port->p_node->sw || 401219820Sjeff osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, 402219820Sjeff p_mgr->p_subn)) 403219820Sjeff num_lids = lmc_num_lids; 404219820Sjeff else 405219820Sjeff num_lids = 1; 406219820Sjeff 407219820Sjeff if ((num_lids != 1) && 408219820Sjeff (((db_min_lid & lmc_mask) != db_min_lid) || 409219820Sjeff (db_max_lid - db_min_lid + 1 < num_lids))) { 410219820Sjeff /* Not aligned, or not wide enough, then remove the entry */ 411219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 412219820Sjeff "Cleaning persistent entry for guid:" 413219820Sjeff "0x%016" PRIx64 " illegal range:" 414219820Sjeff "[0x%x:0x%x]\n", 415219820Sjeff cl_ntoh64(osm_port_get_guid(p_port)), 416219820Sjeff db_min_lid, db_max_lid); 417219820Sjeff osm_db_guid2lid_delete(p_mgr->p_g2l, 418219820Sjeff cl_ntoh64 419219820Sjeff (osm_port_get_guid 420219820Sjeff (p_port))); 421219820Sjeff for (lid = db_min_lid; lid <= db_max_lid; lid++) 422219820Sjeff cl_ptr_vector_set(p_persistent_vec, lid, 423219820Sjeff NULL); 424219820Sjeff } 425219820Sjeff } 426219820Sjeff } 427219820Sjeff 428219820Sjeff /* 429219820Sjeff Our task is to find free lid ranges. 430219820Sjeff A lid can be used if 431219820Sjeff 1. a persistent assignment exists 432219820Sjeff 2. the lid is used by a discovered port that does not have a persistent 433219820Sjeff assignment. 434219820Sjeff 435219820Sjeff scan through all lid values of both the persistent table and 436219820Sjeff discovered table. 437219820Sjeff If the lid has an assigned port in the discovered table: 438219820Sjeff * make sure the lid matches the persistent table, or 439219820Sjeff * there is no other persistent assignment for that lid. 440219820Sjeff * else cleanup the port_by_lid_tbl, mark this as empty range. 441219820Sjeff Else if the lid does not have an entry in the persistent table 442219820Sjeff mark it as free. 443219820Sjeff */ 444219820Sjeff 445219820Sjeff /* find the range of lids to scan */ 446219820Sjeff max_discovered_lid = 447219820Sjeff (uint16_t) cl_ptr_vector_get_size(p_discovered_vec); 448219820Sjeff max_persistent_lid = 449219820Sjeff (uint16_t) cl_ptr_vector_get_size(p_persistent_vec); 450219820Sjeff 451219820Sjeff /* but the vectors have one extra entry for lid=0 */ 452219820Sjeff if (max_discovered_lid) 453219820Sjeff max_discovered_lid--; 454219820Sjeff if (max_persistent_lid) 455219820Sjeff max_persistent_lid--; 456219820Sjeff 457219820Sjeff if (max_persistent_lid > max_discovered_lid) 458219820Sjeff max_defined_lid = max_persistent_lid; 459219820Sjeff else 460219820Sjeff max_defined_lid = max_discovered_lid; 461219820Sjeff 462219820Sjeff for (lid = 1; lid <= max_defined_lid; lid++) { 463219820Sjeff is_free = TRUE; 464219820Sjeff /* first check to see if the lid is used by a persistent assignment */ 465219820Sjeff if ((lid <= max_persistent_lid) 466219820Sjeff && cl_ptr_vector_get(p_persistent_vec, lid)) { 467219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 468219820Sjeff "0x%04x is not free as its mapped by the " 469219820Sjeff "persistent db\n", lid); 470219820Sjeff is_free = FALSE; 471219820Sjeff } else { 472219820Sjeff /* check this is a discovered port */ 473219820Sjeff if (lid <= max_discovered_lid 474219820Sjeff && (p_port = (osm_port_t *) 475219820Sjeff cl_ptr_vector_get(p_discovered_vec, lid))) { 476219820Sjeff /* we have a port. Now lets see if we can preserve its lid range. */ 477219820Sjeff /* For that, we need to make sure: 478219820Sjeff 1. The port has a (legal) persistency entry. Then the local lid 479219820Sjeff is free (we will use the persistency value). 480219820Sjeff 2. Can the port keep its local assignment? 481219820Sjeff a. Make sure the lid a aligned. 482219820Sjeff b. Make sure all needed lids (for the lmc) are free according 483219820Sjeff to persistency table. 484219820Sjeff */ 485219820Sjeff /* qualify the guid of the port is not persistently mapped to 486219820Sjeff another range */ 487219820Sjeff if (!osm_db_guid2lid_get(p_mgr->p_g2l, 488219820Sjeff cl_ntoh64 489219820Sjeff (osm_port_get_guid 490219820Sjeff (p_port)), 491219820Sjeff &db_min_lid, 492219820Sjeff &db_max_lid)) { 493219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 494219820Sjeff "0x%04x is free as it was " 495219820Sjeff "discovered but mapped by the " 496219820Sjeff "persistent db to [0x%04x:0x%04x]\n", 497219820Sjeff lid, db_min_lid, db_max_lid); 498219820Sjeff } else { 499219820Sjeff /* can the port keep its assignment ? */ 500219820Sjeff /* get the lid range of that port, and the required number 501219820Sjeff of lids we are about to assign to it */ 502219820Sjeff osm_port_get_lid_range_ho(p_port, 503219820Sjeff &disc_min_lid, 504219820Sjeff &disc_max_lid); 505219820Sjeff if (!p_port->p_node->sw 506219820Sjeff || 507219820Sjeff osm_switch_sp0_is_lmc_capable 508219820Sjeff (p_port->p_node->sw, 509219820Sjeff p_mgr->p_subn)) { 510219820Sjeff disc_max_lid = 511219820Sjeff disc_min_lid + 512219820Sjeff lmc_num_lids - 1; 513219820Sjeff num_lids = lmc_num_lids; 514219820Sjeff } else 515219820Sjeff num_lids = 1; 516219820Sjeff 517219820Sjeff /* Make sure the lid is aligned */ 518219820Sjeff if ((num_lids != 1) 519219820Sjeff && ((disc_min_lid & lmc_mask) != 520219820Sjeff disc_min_lid)) { 521219820Sjeff /* The lid cannot be used */ 522219820Sjeff OSM_LOG(p_mgr->p_log, 523219820Sjeff OSM_LOG_DEBUG, 524219820Sjeff "0x%04x is free as it was " 525219820Sjeff "discovered but not aligned\n", 526219820Sjeff lid); 527219820Sjeff } else { 528219820Sjeff /* check that all needed lids are not persistently mapped */ 529219820Sjeff is_free = FALSE; 530219820Sjeff for (req_lid = disc_min_lid + 1; 531219820Sjeff req_lid <= disc_max_lid; 532219820Sjeff req_lid++) { 533219820Sjeff if ((req_lid <= 534219820Sjeff max_persistent_lid) 535219820Sjeff && 536219820Sjeff cl_ptr_vector_get 537219820Sjeff (p_persistent_vec, 538219820Sjeff req_lid)) { 539219820Sjeff OSM_LOG(p_mgr-> 540219820Sjeff p_log, 541219820Sjeff OSM_LOG_DEBUG, 542219820Sjeff "0x%04x is free as it was discovered " 543219820Sjeff "but mapped\n", 544219820Sjeff lid); 545219820Sjeff is_free = TRUE; 546219820Sjeff break; 547219820Sjeff } 548219820Sjeff } 549219820Sjeff 550219820Sjeff if (is_free == FALSE) { 551219820Sjeff /* This port will use its local lid, and consume the entire required lid range. 552219820Sjeff Thus we can skip that range. */ 553219820Sjeff /* If the disc_max_lid is greater then lid, we can skip right to it, 554219820Sjeff since we've done all neccessary checks on the lids in between. */ 555219820Sjeff if (disc_max_lid > lid) 556219820Sjeff lid = 557219820Sjeff disc_max_lid; 558219820Sjeff } 559219820Sjeff } 560219820Sjeff } 561219820Sjeff } 562219820Sjeff } 563219820Sjeff 564219820Sjeff if (is_free) { 565219820Sjeff if (p_range) 566219820Sjeff p_range->max_lid = lid; 567219820Sjeff else { 568219820Sjeff p_range = (osm_lid_mgr_range_t *) 569219820Sjeff malloc(sizeof(osm_lid_mgr_range_t)); 570219820Sjeff if (p_range) { 571219820Sjeff p_range->min_lid = lid; 572219820Sjeff p_range->max_lid = lid; 573219820Sjeff } 574219820Sjeff } 575219820Sjeff } else { 576219820Sjeff /* this lid is used so we need to finalize the previous free range */ 577219820Sjeff if (p_range) { 578219820Sjeff cl_qlist_insert_tail(&p_mgr->free_ranges, 579219820Sjeff &p_range->item); 580219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 581219820Sjeff "new free lid range [%u:%u]\n", 582219820Sjeff p_range->min_lid, p_range->max_lid); 583219820Sjeff p_range = NULL; 584219820Sjeff } 585219820Sjeff } 586219820Sjeff } 587219820Sjeff 588219820SjeffAfterScanningLids: 589219820Sjeff /* after scanning all known lids we need to extend the last range 590219820Sjeff to the max allowed lid */ 591219820Sjeff if (!p_range) { 592219820Sjeff p_range = 593219820Sjeff (osm_lid_mgr_range_t *) malloc(sizeof(osm_lid_mgr_range_t)); 594219820Sjeff /* 595219820Sjeff The p_range can be NULL in one of 2 cases: 596219820Sjeff 1. If max_defined_lid == 0. In this case, we want the 597219820Sjeff entire range. 598219820Sjeff 2. If all lids discovered in the loop where mapped. In this 599219820Sjeff case, no free range exists and we want to define it after the 600219820Sjeff last mapped lid. 601219820Sjeff */ 602219820Sjeff if (p_range) 603219820Sjeff p_range->min_lid = lid; 604219820Sjeff } 605219820Sjeff if (p_range) { 606219820Sjeff p_range->max_lid = p_mgr->p_subn->max_ucast_lid_ho; 607219820Sjeff cl_qlist_insert_tail(&p_mgr->free_ranges, &p_range->item); 608219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 609219820Sjeff "final free lid range [%u:%u]\n", 610219820Sjeff p_range->min_lid, p_range->max_lid); 611219820Sjeff } 612219820Sjeff 613219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 614219820Sjeff return status; 615219820Sjeff} 616219820Sjeff 617219820Sjeff/********************************************************************** 618219820Sjeff check if the given range of lids is free 619219820Sjeff**********************************************************************/ 620219820Sjeffstatic boolean_t 621219820Sjeff__osm_lid_mgr_is_range_not_persistent(IN osm_lid_mgr_t * const p_mgr, 622219820Sjeff IN const uint16_t lid, 623219820Sjeff IN const uint16_t num_lids) 624219820Sjeff{ 625219820Sjeff uint16_t i; 626219820Sjeff cl_status_t status; 627219820Sjeff osm_port_t *p_port; 628219820Sjeff const uint8_t start_lid = (uint8_t) (1 << p_mgr->p_subn->opt.lmc); 629219820Sjeff const cl_ptr_vector_t *const p_tbl = &p_mgr->used_lids; 630219820Sjeff 631219820Sjeff if (lid < start_lid) 632219820Sjeff return (FALSE); 633219820Sjeff 634219820Sjeff for (i = lid; i < lid + num_lids; i++) { 635219820Sjeff status = cl_ptr_vector_at(p_tbl, i, (void *)&p_port); 636219820Sjeff if (status == CL_SUCCESS) { 637219820Sjeff if (p_port != NULL) 638219820Sjeff return (FALSE); 639219820Sjeff } else 640219820Sjeff /* 641219820Sjeff We are out of range in the array. 642219820Sjeff Consider all further entries "free". 643219820Sjeff */ 644219820Sjeff return (TRUE); 645219820Sjeff } 646219820Sjeff 647219820Sjeff return (TRUE); 648219820Sjeff} 649219820Sjeff 650219820Sjeff/********************************************************************** 651219820Sjefffind a free lid range 652219820Sjeff**********************************************************************/ 653219820Sjeffstatic void 654219820Sjeff__osm_lid_mgr_find_free_lid_range(IN osm_lid_mgr_t * const p_mgr, 655219820Sjeff IN const uint8_t num_lids, 656219820Sjeff OUT uint16_t * const p_min_lid, 657219820Sjeff OUT uint16_t * const p_max_lid) 658219820Sjeff{ 659219820Sjeff uint16_t lid; 660219820Sjeff cl_list_item_t *p_item; 661219820Sjeff cl_list_item_t *p_next_item; 662219820Sjeff osm_lid_mgr_range_t *p_range = NULL; 663219820Sjeff uint8_t lmc_num_lids; 664219820Sjeff uint16_t lmc_mask; 665219820Sjeff 666219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "LMC = %u, number LIDs = %u\n", 667219820Sjeff p_mgr->p_subn->opt.lmc, num_lids); 668219820Sjeff 669219820Sjeff lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc); 670219820Sjeff if (p_mgr->p_subn->opt.lmc) 671219820Sjeff lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); 672219820Sjeff else 673219820Sjeff lmc_mask = 0xffff; 674219820Sjeff 675219820Sjeff /* 676219820Sjeff Search the list of free lid ranges for a range which is big enough 677219820Sjeff */ 678219820Sjeff p_item = cl_qlist_head(&p_mgr->free_ranges); 679219820Sjeff while (p_item != cl_qlist_end(&p_mgr->free_ranges)) { 680219820Sjeff p_next_item = cl_qlist_next(p_item); 681219820Sjeff p_range = (osm_lid_mgr_range_t *) p_item; 682219820Sjeff 683219820Sjeff lid = p_range->min_lid; 684219820Sjeff 685219820Sjeff /* if we require more then one lid we must align to LMC */ 686219820Sjeff if (num_lids > 1) { 687219820Sjeff if ((lid & lmc_mask) != lid) 688219820Sjeff lid = (lid + lmc_num_lids) & lmc_mask; 689219820Sjeff } 690219820Sjeff 691219820Sjeff /* but we can be out of the range */ 692219820Sjeff if (lid + num_lids - 1 <= p_range->max_lid) { 693219820Sjeff /* ok let us use that range */ 694219820Sjeff if (lid + num_lids - 1 == p_range->max_lid) 695219820Sjeff /* we consumed the entire range */ 696219820Sjeff cl_qlist_remove_item(&p_mgr->free_ranges, 697219820Sjeff p_item); 698219820Sjeff else 699219820Sjeff /* only update the available range */ 700219820Sjeff p_range->min_lid = lid + num_lids; 701219820Sjeff 702219820Sjeff *p_min_lid = lid; 703219820Sjeff *p_max_lid = (uint16_t) (lid + num_lids - 1); 704219820Sjeff return; 705219820Sjeff } 706219820Sjeff p_item = p_next_item; 707219820Sjeff } 708219820Sjeff 709219820Sjeff /* 710219820Sjeff Couldn't find a free range of lids. 711219820Sjeff */ 712219820Sjeff *p_min_lid = *p_max_lid = 0; 713219820Sjeff /* if we run out of lids, give an error and abort! */ 714219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0307: " 715219820Sjeff "OPENSM RAN OUT OF LIDS!!!\n"); 716219820Sjeff CL_ASSERT(0); 717219820Sjeff} 718219820Sjeff 719219820Sjeff/********************************************************************** 720219820Sjeff **********************************************************************/ 721219820Sjeffstatic void 722219820Sjeff__osm_lid_mgr_cleanup_discovered_port_lid_range(IN osm_lid_mgr_t * p_mgr, 723219820Sjeff IN osm_port_t * p_port) 724219820Sjeff{ 725219820Sjeff cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl; 726219820Sjeff uint16_t lid, min_lid, max_lid; 727219820Sjeff uint16_t max_tbl_lid = 728219820Sjeff (uint16_t) (cl_ptr_vector_get_size(p_discovered_vec)); 729219820Sjeff 730219820Sjeff osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid); 731219820Sjeff min_lid = __osm_trim_lid(min_lid); 732219820Sjeff max_lid = __osm_trim_lid(max_lid); 733219820Sjeff for (lid = min_lid; lid <= max_lid; lid++) { 734219820Sjeff if ((lid < max_tbl_lid) && 735219820Sjeff (p_port == 736219820Sjeff (osm_port_t *) cl_ptr_vector_get(p_discovered_vec, lid))) 737219820Sjeff cl_ptr_vector_set(p_discovered_vec, lid, NULL); 738219820Sjeff } 739219820Sjeff} 740219820Sjeff 741219820Sjeff/********************************************************************** 742219820Sjeff 0.1 if the port info lid matches the guid2lid return 0 743219820Sjeff 0.2 if the port info has a lid and that range is empty in 744219820Sjeff port_lid_tbl, return 0 and update the port_lid_tbl and 745219820Sjeff guid2lid 746219820Sjeff 0.3 else find an empty space in port_lid_tbl, update the 747219820Sjeff port_lid_tbl and guid2lid, return 1 to flag a change required. 748219820Sjeff**********************************************************************/ 749219820Sjeffstatic int 750219820Sjeff__osm_lid_mgr_get_port_lid(IN osm_lid_mgr_t * const p_mgr, 751219820Sjeff IN osm_port_t * const p_port, 752219820Sjeff OUT uint16_t * const p_min_lid, 753219820Sjeff OUT uint16_t * const p_max_lid) 754219820Sjeff{ 755219820Sjeff uint16_t lid, min_lid, max_lid; 756219820Sjeff uint64_t guid; 757219820Sjeff uint8_t num_lids = (1 << p_mgr->p_subn->opt.lmc); 758219820Sjeff int lid_changed = 0; 759219820Sjeff uint16_t lmc_mask; 760219820Sjeff 761219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 762219820Sjeff 763219820Sjeff if (p_mgr->p_subn->opt.lmc) 764219820Sjeff lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); 765219820Sjeff else 766219820Sjeff lmc_mask = 0xffff; 767219820Sjeff 768219820Sjeff /* get the lid from the guid2lid */ 769219820Sjeff guid = cl_ntoh64(osm_port_get_guid(p_port)); 770219820Sjeff 771219820Sjeff /* if the port is a base switch port 0 then we only need one lid */ 772219820Sjeff if (p_port->p_node->sw && 773219820Sjeff !osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn)) 774219820Sjeff num_lids = 1; 775219820Sjeff 776219820Sjeff /* if the port matches the guid2lid */ 777219820Sjeff if (!osm_db_guid2lid_get(p_mgr->p_g2l, guid, &min_lid, &max_lid)) { 778219820Sjeff *p_min_lid = min_lid; 779219820Sjeff *p_max_lid = min_lid + num_lids - 1; 780219820Sjeff if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port))) { 781219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 782219820Sjeff " matches its known lid:%u\n", guid, min_lid); 783219820Sjeff goto Exit; 784219820Sjeff } else { 785219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 786219820Sjeff "0x%016" PRIx64 " with lid:%u " 787219820Sjeff "does not match its known lid:%u\n", 788219820Sjeff guid, cl_ntoh16(osm_port_get_base_lid(p_port)), 789219820Sjeff min_lid); 790219820Sjeff __osm_lid_mgr_cleanup_discovered_port_lid_range(p_mgr, 791219820Sjeff p_port); 792219820Sjeff /* we still need to send the setting to the target port */ 793219820Sjeff lid_changed = 1; 794219820Sjeff goto Exit; 795219820Sjeff } 796219820Sjeff } else 797219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 798219820Sjeff "0x%016" PRIx64 " has no persistent lid assigned\n", 799219820Sjeff guid); 800219820Sjeff 801219820Sjeff /* if the port info carries a lid it must be lmc aligned and not mapped 802219820Sjeff by the pesistent storage */ 803219820Sjeff min_lid = cl_ntoh16(osm_port_get_base_lid(p_port)); 804219820Sjeff 805219820Sjeff /* we want to ignore the discovered lid if we are also on first sweep of 806219820Sjeff reassign lids flow */ 807219820Sjeff if (min_lid && 808219820Sjeff !((p_mgr->p_subn->first_time_master_sweep == TRUE) && 809219820Sjeff (p_mgr->p_subn->opt.reassign_lids == TRUE))) { 810219820Sjeff /* make sure lid is valid */ 811219820Sjeff if ((num_lids == 1) || ((min_lid & lmc_mask) == min_lid)) { 812219820Sjeff /* is it free */ 813219820Sjeff if (__osm_lid_mgr_is_range_not_persistent 814219820Sjeff (p_mgr, min_lid, num_lids)) { 815219820Sjeff *p_min_lid = min_lid; 816219820Sjeff *p_max_lid = min_lid + num_lids - 1; 817219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 818219820Sjeff "0x%016" PRIx64 819219820Sjeff " lid range:[%u-%u] is free\n", 820219820Sjeff guid, *p_min_lid, *p_max_lid); 821219820Sjeff goto NewLidSet; 822219820Sjeff } else 823219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 824219820Sjeff "0x%016" PRIx64 " existing lid " 825219820Sjeff "range:[%u:%u] is not free\n", 826219820Sjeff guid, min_lid, min_lid + num_lids - 1); 827219820Sjeff } else 828219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 829219820Sjeff "0x%016" PRIx64 " existing lid range:" 830219820Sjeff "[%u:%u] is not lmc aligned\n", 831219820Sjeff guid, min_lid, min_lid + num_lids - 1); 832219820Sjeff } 833219820Sjeff 834219820Sjeff /* first cleanup the existing discovered lid range */ 835219820Sjeff __osm_lid_mgr_cleanup_discovered_port_lid_range(p_mgr, p_port); 836219820Sjeff 837219820Sjeff /* find an empty space */ 838219820Sjeff __osm_lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, 839219820Sjeff p_max_lid); 840219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 841219820Sjeff "0x%016" PRIx64 " assigned a new lid range:[%u-%u]\n", 842219820Sjeff guid, *p_min_lid, *p_max_lid); 843219820Sjeff lid_changed = 1; 844219820Sjeff 845219820SjeffNewLidSet: 846219820Sjeff /* update the guid2lid db and used_lids */ 847219820Sjeff osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid); 848219820Sjeff for (lid = *p_min_lid; lid <= *p_max_lid; lid++) 849219820Sjeff cl_ptr_vector_set(&p_mgr->used_lids, lid, (void *)1); 850219820Sjeff 851219820SjeffExit: 852219820Sjeff /* make sure the assigned lids are marked in port_lid_tbl */ 853219820Sjeff for (lid = *p_min_lid; lid <= *p_max_lid; lid++) 854219820Sjeff cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port); 855219820Sjeff 856219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 857219820Sjeff return lid_changed; 858219820Sjeff} 859219820Sjeff 860219820Sjeff/********************************************************************** 861219820Sjeff Set to INIT the remote port of the given physical port 862219820Sjeff **********************************************************************/ 863219820Sjeffstatic void 864219820Sjeff__osm_lid_mgr_set_remote_pi_state_to_init(IN osm_lid_mgr_t * const p_mgr, 865219820Sjeff IN osm_physp_t * const p_physp) 866219820Sjeff{ 867219820Sjeff osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp); 868219820Sjeff 869219820Sjeff if (p_rem_physp == NULL) 870219820Sjeff return; 871219820Sjeff 872219820Sjeff /* but in some rare cases the remote side might be non responsive */ 873219820Sjeff ib_port_info_set_port_state(&p_rem_physp->port_info, IB_LINK_INIT); 874219820Sjeff} 875219820Sjeff 876219820Sjeff/********************************************************************** 877219820Sjeff **********************************************************************/ 878219820Sjeffstatic boolean_t 879219820Sjeff__osm_lid_mgr_set_physp_pi(IN osm_lid_mgr_t * const p_mgr, 880219820Sjeff IN osm_port_t * const p_port, 881219820Sjeff IN osm_physp_t * const p_physp, 882219820Sjeff IN ib_net16_t const lid) 883219820Sjeff{ 884219820Sjeff uint8_t payload[IB_SMP_DATA_SIZE]; 885219820Sjeff ib_port_info_t *p_pi = (ib_port_info_t *) payload; 886219820Sjeff const ib_port_info_t *p_old_pi; 887219820Sjeff osm_madw_context_t context; 888219820Sjeff osm_node_t *p_node; 889219820Sjeff ib_api_status_t status; 890219820Sjeff uint8_t mtu; 891219820Sjeff uint8_t op_vls; 892219820Sjeff uint8_t port_num; 893219820Sjeff boolean_t send_set = FALSE; 894219820Sjeff 895219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 896219820Sjeff 897219820Sjeff /* 898219820Sjeff Don't bother doing anything if this Physical Port is not valid. 899219820Sjeff This allows simplified code in the caller. 900219820Sjeff */ 901219820Sjeff if (!p_physp) 902219820Sjeff goto Exit; 903219820Sjeff 904219820Sjeff port_num = osm_physp_get_port_num(p_physp); 905219820Sjeff p_node = osm_physp_get_node_ptr(p_physp); 906219820Sjeff 907219820Sjeff if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0) { 908219820Sjeff /* 909219820Sjeff Switch ports that are not numbered 0 should not be set 910219820Sjeff with the following attributes as they are set later 911219820Sjeff (during NO_CHANGE state in link mgr). 912219820Sjeff */ 913219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 914219820Sjeff "Skipping switch port %u, GUID 0x%016" PRIx64 "\n", 915219820Sjeff port_num, cl_ntoh64(osm_physp_get_port_guid(p_physp))); 916219820Sjeff goto Exit; 917219820Sjeff } 918219820Sjeff 919219820Sjeff p_old_pi = &p_physp->port_info; 920219820Sjeff 921219820Sjeff /* 922219820Sjeff First, copy existing parameters from the PortInfo attribute we 923219820Sjeff already have for this node. 924219820Sjeff 925219820Sjeff Second, update with default values that we know must be set for 926219820Sjeff every Physical Port and the LID and set the neighbor MTU field 927219820Sjeff appropriately. 928219820Sjeff 929219820Sjeff Third, send the SMP to this physical port. 930219820Sjeff */ 931219820Sjeff 932219820Sjeff memset(payload, 0, IB_SMP_DATA_SIZE); 933219820Sjeff memcpy(payload, p_old_pi, sizeof(ib_port_info_t)); 934219820Sjeff 935219820Sjeff /* 936219820Sjeff Should never write back a value that is bigger then 3 in 937219820Sjeff the PortPhysicalState field, so cannot simply copy! 938219820Sjeff 939219820Sjeff Actually we want to write there: 940219820Sjeff port physical state - no change 941219820Sjeff link down default state = polling 942219820Sjeff port state - no change 943219820Sjeff */ 944219820Sjeff p_pi->state_info2 = 0x02; 945219820Sjeff ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE); 946219820Sjeff 947219820Sjeff if (ib_port_info_get_link_down_def_state(p_pi) != 948219820Sjeff ib_port_info_get_link_down_def_state(p_old_pi)) 949219820Sjeff send_set = TRUE; 950219820Sjeff 951219820Sjeff /* didn't get PortInfo before */ 952219820Sjeff if (!ib_port_info_get_port_state(p_old_pi)) 953219820Sjeff send_set = TRUE; 954219820Sjeff 955219820Sjeff p_pi->m_key = p_mgr->p_subn->opt.m_key; 956219820Sjeff if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key))) 957219820Sjeff send_set = TRUE; 958219820Sjeff 959219820Sjeff p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix; 960219820Sjeff if (memcmp(&p_pi->subnet_prefix, &p_old_pi->subnet_prefix, 961219820Sjeff sizeof(p_pi->subnet_prefix))) 962219820Sjeff send_set = TRUE; 963219820Sjeff 964219820Sjeff p_pi->base_lid = lid; 965219820Sjeff if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid, 966219820Sjeff sizeof(p_pi->base_lid))) 967219820Sjeff send_set = TRUE; 968219820Sjeff 969219820Sjeff /* we are updating the ports with our local sm_base_lid */ 970219820Sjeff p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid; 971219820Sjeff if (memcmp(&p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, 972219820Sjeff sizeof(p_pi->master_sm_base_lid))) 973219820Sjeff send_set = TRUE; 974219820Sjeff 975219820Sjeff p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period; 976219820Sjeff if (memcmp(&p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, 977219820Sjeff sizeof(p_pi->m_key_lease_period))) 978219820Sjeff send_set = TRUE; 979219820Sjeff 980219820Sjeff /* 981219820Sjeff we want to set the timeout for both the switch port 0 982219820Sjeff and the CA ports 983219820Sjeff */ 984219820Sjeff ib_port_info_set_timeout(p_pi, p_mgr->p_subn->opt.subnet_timeout); 985219820Sjeff if (ib_port_info_get_timeout(p_pi) != 986219820Sjeff ib_port_info_get_timeout(p_old_pi)) 987219820Sjeff send_set = TRUE; 988219820Sjeff 989219820Sjeff if (port_num != 0) { 990219820Sjeff /* 991219820Sjeff CAs don't have a port 0, and for switch port 0, 992219820Sjeff the state bits are ignored. 993219820Sjeff This is not the switch management port 994219820Sjeff */ 995219820Sjeff p_pi->link_width_enabled = p_old_pi->link_width_supported; 996219820Sjeff if (memcmp(&p_pi->link_width_enabled, 997219820Sjeff &p_old_pi->link_width_enabled, 998219820Sjeff sizeof(p_pi->link_width_enabled))) 999219820Sjeff send_set = TRUE; 1000219820Sjeff 1001219820Sjeff /* M_KeyProtectBits are always zero */ 1002219820Sjeff p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc; 1003219820Sjeff if (memcmp(&p_pi->mkey_lmc, &p_old_pi->mkey_lmc, 1004219820Sjeff sizeof(p_pi->mkey_lmc))) 1005219820Sjeff send_set = TRUE; 1006219820Sjeff 1007219820Sjeff /* calc new op_vls and mtu */ 1008219820Sjeff op_vls = 1009219820Sjeff osm_physp_calc_link_op_vls(p_mgr->p_log, p_mgr->p_subn, 1010219820Sjeff p_physp); 1011219820Sjeff mtu = osm_physp_calc_link_mtu(p_mgr->p_log, p_physp); 1012219820Sjeff 1013219820Sjeff ib_port_info_set_neighbor_mtu(p_pi, mtu); 1014219820Sjeff 1015219820Sjeff if (ib_port_info_get_neighbor_mtu(p_pi) != 1016219820Sjeff ib_port_info_get_neighbor_mtu(p_old_pi)) 1017219820Sjeff send_set = TRUE; 1018219820Sjeff 1019219820Sjeff ib_port_info_set_op_vls(p_pi, op_vls); 1020219820Sjeff if (ib_port_info_get_op_vls(p_pi) != 1021219820Sjeff ib_port_info_get_op_vls(p_old_pi)) 1022219820Sjeff send_set = TRUE; 1023219820Sjeff 1024219820Sjeff /* 1025219820Sjeff Several timeout mechanisms: 1026219820Sjeff */ 1027219820Sjeff ib_port_info_set_phy_and_overrun_err_thd(p_pi, 1028219820Sjeff p_mgr->p_subn->opt. 1029219820Sjeff local_phy_errors_threshold, 1030219820Sjeff p_mgr->p_subn->opt. 1031219820Sjeff overrun_errors_threshold); 1032219820Sjeff 1033219820Sjeff if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold, 1034219820Sjeff sizeof(p_pi->error_threshold))) 1035219820Sjeff send_set = TRUE; 1036219820Sjeff 1037219820Sjeff /* 1038219820Sjeff To reset the port state machine we can send 1039219820Sjeff PortInfo.State = DOWN. (see: 7.2.7 p171 lines:10-19) 1040219820Sjeff */ 1041219820Sjeff if ((mtu != ib_port_info_get_neighbor_mtu(p_old_pi)) || 1042219820Sjeff (op_vls != ib_port_info_get_op_vls(p_old_pi))) { 1043219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 1044219820Sjeff "Sending Link Down to GUID 0x%016" 1045219820Sjeff PRIx64 " port %d due to op_vls or " 1046219820Sjeff "mtu change. MTU:%u,%u VL_CAP:%u,%u\n", 1047219820Sjeff cl_ntoh64(osm_physp_get_port_guid(p_physp)), 1048219820Sjeff port_num, mtu, 1049219820Sjeff ib_port_info_get_neighbor_mtu(p_old_pi), 1050219820Sjeff op_vls, ib_port_info_get_op_vls(p_old_pi)); 1051219820Sjeff 1052219820Sjeff /* 1053219820Sjeff we need to make sure the internal DB will follow the 1054219820Sjeff fact that the remote port is also going through 1055219820Sjeff "down" state into "init"... 1056219820Sjeff */ 1057219820Sjeff __osm_lid_mgr_set_remote_pi_state_to_init(p_mgr, 1058219820Sjeff p_physp); 1059219820Sjeff 1060219820Sjeff ib_port_info_set_port_state(p_pi, IB_LINK_DOWN); 1061219820Sjeff if (ib_port_info_get_port_state(p_pi) != 1062219820Sjeff ib_port_info_get_port_state(p_old_pi)) 1063219820Sjeff send_set = TRUE; 1064219820Sjeff } 1065219820Sjeff } else { 1066219820Sjeff /* 1067219820Sjeff For Port 0, NeighborMTU is relevant only for Enh. SP0. 1068219820Sjeff In this case, we'll set the MTU according to the mtu_cap 1069219820Sjeff */ 1070219820Sjeff ib_port_info_set_neighbor_mtu(p_pi, 1071219820Sjeff ib_port_info_get_mtu_cap 1072219820Sjeff (p_old_pi)); 1073219820Sjeff if (ib_port_info_get_neighbor_mtu(p_pi) != 1074219820Sjeff ib_port_info_get_neighbor_mtu(p_old_pi)) 1075219820Sjeff send_set = TRUE; 1076219820Sjeff 1077219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 1078219820Sjeff "Updating neighbor_mtu on switch GUID 0x%016" PRIx64 1079219820Sjeff " port 0 to:%u\n", 1080219820Sjeff cl_ntoh64(osm_physp_get_port_guid(p_physp)), 1081219820Sjeff ib_port_info_get_neighbor_mtu(p_pi)); 1082219820Sjeff 1083219820Sjeff /* Determine if enhanced switch port 0 and if so set LMC */ 1084219820Sjeff if (osm_switch_sp0_is_lmc_capable(p_node->sw, p_mgr->p_subn)) { 1085219820Sjeff /* M_KeyProtectBits are always zero */ 1086219820Sjeff p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc; 1087219820Sjeff if (memcmp(&p_pi->mkey_lmc, &p_old_pi->mkey_lmc, 1088219820Sjeff sizeof(p_pi->mkey_lmc))) 1089219820Sjeff send_set = TRUE; 1090219820Sjeff } 1091219820Sjeff } 1092219820Sjeff 1093219820Sjeff context.pi_context.node_guid = osm_node_get_node_guid(p_node); 1094219820Sjeff context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); 1095219820Sjeff context.pi_context.set_method = TRUE; 1096219820Sjeff context.pi_context.light_sweep = FALSE; 1097219820Sjeff context.pi_context.active_transition = FALSE; 1098219820Sjeff 1099219820Sjeff /* 1100219820Sjeff We need to set the cli_rereg bit when we are in first_time_master_sweep 1101219820Sjeff for ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11 1102219820Sjeff Also, if this port was just now discovered, then we should also set 1103219820Sjeff the cli_rereg bit. We know that the port was just discovered if its 1104219820Sjeff is_new field is set. 1105219820Sjeff */ 1106219820Sjeff if ((p_mgr->p_subn->first_time_master_sweep == TRUE || p_port->is_new) 1107219820Sjeff && !p_mgr->p_subn->opt.no_clients_rereg 1108219820Sjeff && (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG)) { 1109219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 1110219820Sjeff "Seting client rereg on %s, port %d\n", 1111219820Sjeff p_port->p_node->print_desc, p_port->p_physp->port_num); 1112219820Sjeff ib_port_info_set_client_rereg(p_pi, 1); 1113219820Sjeff send_set = TRUE; 1114219820Sjeff } else 1115219820Sjeff ib_port_info_set_client_rereg(p_pi, 0); 1116219820Sjeff 1117219820Sjeff /* We need to send the PortInfo Set request with the new sm_lid 1118219820Sjeff in the following cases: 1119219820Sjeff 1. There is a change in the values (send_set == TRUE) 1120219820Sjeff 2. first_time_master_sweep flag on the subnet is TRUE. This means the 1121219820Sjeff SM just became master, and it then needs to send a PortInfo Set to 1122219820Sjeff every port. 1123219820Sjeff */ 1124219820Sjeff if (p_mgr->p_subn->first_time_master_sweep == TRUE) 1125219820Sjeff send_set = TRUE; 1126219820Sjeff 1127219820Sjeff if (send_set) { 1128219820Sjeff p_mgr->send_set_reqs = TRUE; 1129219820Sjeff status = osm_req_set(p_mgr->sm, 1130219820Sjeff osm_physp_get_dr_path_ptr(p_physp), 1131219820Sjeff payload, 1132219820Sjeff sizeof(payload), 1133219820Sjeff IB_MAD_ATTR_PORT_INFO, 1134219820Sjeff cl_hton32(osm_physp_get_port_num(p_physp)), 1135219820Sjeff CL_DISP_MSGID_NONE, &context); 1136219820Sjeff } 1137219820Sjeff 1138219820SjeffExit: 1139219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 1140219820Sjeff return send_set; 1141219820Sjeff} 1142219820Sjeff 1143219820Sjeff/********************************************************************** 1144219820Sjeff Processes our own node 1145219820Sjeff Lock must already be held. 1146219820Sjeff**********************************************************************/ 1147219820Sjeffstatic boolean_t 1148219820Sjeff__osm_lid_mgr_process_our_sm_node(IN osm_lid_mgr_t * const p_mgr) 1149219820Sjeff{ 1150219820Sjeff osm_port_t *p_port; 1151219820Sjeff uint16_t min_lid_ho; 1152219820Sjeff uint16_t max_lid_ho; 1153219820Sjeff boolean_t res = TRUE; 1154219820Sjeff 1155219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 1156219820Sjeff 1157219820Sjeff /* 1158219820Sjeff Acquire our own port object. 1159219820Sjeff */ 1160219820Sjeff p_port = 1161219820Sjeff osm_get_port_by_guid(p_mgr->p_subn, p_mgr->p_subn->sm_port_guid); 1162219820Sjeff if (!p_port) { 1163219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0308: " 1164219820Sjeff "Can't acquire SM's port object, GUID 0x%016" PRIx64 1165219820Sjeff "\n", cl_ntoh64(p_mgr->p_subn->sm_port_guid)); 1166219820Sjeff res = FALSE; 1167219820Sjeff goto Exit; 1168219820Sjeff } 1169219820Sjeff 1170219820Sjeff /* 1171219820Sjeff Determine the LID this SM will use for its own port. 1172219820Sjeff Be careful. With an LMC > 0, the bottom of the LID range becomes 1173219820Sjeff unusable, since port hardware will mask off least significant bits, 1174219820Sjeff leaving a LID of 0 (invalid). Therefore, make sure that we always 1175219820Sjeff configure the SM with a LID that has non-zero bits, even after 1176219820Sjeff LMC masking by hardware. 1177219820Sjeff */ 1178219820Sjeff __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho); 1179219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 1180219820Sjeff "Current base LID is %u\n", min_lid_ho); 1181219820Sjeff /* 1182219820Sjeff Update subnet object. 1183219820Sjeff */ 1184219820Sjeff p_mgr->p_subn->master_sm_base_lid = cl_hton16(min_lid_ho); 1185219820Sjeff p_mgr->p_subn->sm_base_lid = cl_hton16(min_lid_ho); 1186219820Sjeff 1187219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, 1188219820Sjeff "Assigning SM's port 0x%016" PRIx64 1189219820Sjeff "\n\t\t\t\tto LID range [%u,%u]\n", 1190219820Sjeff cl_ntoh64(osm_port_get_guid(p_port)), min_lid_ho, max_lid_ho); 1191219820Sjeff 1192219820Sjeff /* 1193219820Sjeff Set the PortInfo the Physical Port associated with this Port. 1194219820Sjeff */ 1195219820Sjeff __osm_lid_mgr_set_physp_pi(p_mgr, p_port, p_port->p_physp, 1196219820Sjeff cl_hton16(min_lid_ho)); 1197219820Sjeff 1198219820SjeffExit: 1199219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 1200219820Sjeff return res; 1201219820Sjeff} 1202219820Sjeff 1203219820Sjeff/********************************************************************** 1204219820Sjeff **********************************************************************/ 1205219820Sjeffosm_signal_t osm_lid_mgr_process_sm(IN osm_lid_mgr_t * const p_mgr) 1206219820Sjeff{ 1207219820Sjeff osm_signal_t signal = OSM_SIGNAL_DONE_PENDING; 1208219820Sjeff 1209219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 1210219820Sjeff 1211219820Sjeff CL_ASSERT(p_mgr->p_subn->sm_port_guid); 1212219820Sjeff 1213219820Sjeff CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock); 1214219820Sjeff 1215219820Sjeff /* initialize the port_lid_tbl and empty ranges list following the 1216219820Sjeff persistent db */ 1217219820Sjeff __osm_lid_mgr_init_sweep(p_mgr); 1218219820Sjeff 1219219820Sjeff /* Set the send_set_reqs of the p_mgr to FALSE, and 1220219820Sjeff we'll see if any set requests were sent. If not - 1221219820Sjeff can signal OSM_SIGNAL_DONE */ 1222219820Sjeff p_mgr->send_set_reqs = FALSE; 1223219820Sjeff if (__osm_lid_mgr_process_our_sm_node(p_mgr) == FALSE) 1224219820Sjeff /* The initialization failed */ 1225219820Sjeff signal = OSM_SIGNAL_DONE; 1226219820Sjeff 1227219820Sjeff if (p_mgr->send_set_reqs == FALSE) 1228219820Sjeff signal = OSM_SIGNAL_DONE; 1229219820Sjeff 1230219820Sjeff CL_PLOCK_RELEASE(p_mgr->p_lock); 1231219820Sjeff 1232219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 1233219820Sjeff return (signal); 1234219820Sjeff} 1235219820Sjeff 1236219820Sjeff/********************************************************************** 1237219820Sjeff 1 go through all ports in the subnet. 1238219820Sjeff 1.1 call __osm_lid_mgr_get_port_min_lid 1239219820Sjeff 1.2 if a change is required send the port info 1240219820Sjeff 2 if any change send the signal PENDING... 1241219820Sjeff**********************************************************************/ 1242219820Sjeffosm_signal_t osm_lid_mgr_process_subnet(IN osm_lid_mgr_t * const p_mgr) 1243219820Sjeff{ 1244219820Sjeff osm_signal_t signal; 1245219820Sjeff cl_qmap_t *p_port_guid_tbl; 1246219820Sjeff osm_port_t *p_port; 1247219820Sjeff ib_net64_t port_guid; 1248219820Sjeff uint16_t min_lid_ho, max_lid_ho; 1249219820Sjeff int lid_changed; 1250219820Sjeff 1251219820Sjeff CL_ASSERT(p_mgr); 1252219820Sjeff 1253219820Sjeff OSM_LOG_ENTER(p_mgr->p_log); 1254219820Sjeff 1255219820Sjeff CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock); 1256219820Sjeff 1257219820Sjeff CL_ASSERT(p_mgr->p_subn->sm_port_guid); 1258219820Sjeff 1259219820Sjeff /* Set the send_set_reqs of the p_mgr to FALSE, and 1260219820Sjeff we'll see if any set requests were sent. If not - 1261219820Sjeff can signal OSM_SIGNAL_DONE */ 1262219820Sjeff p_mgr->send_set_reqs = FALSE; 1263219820Sjeff 1264219820Sjeff p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; 1265219820Sjeff 1266219820Sjeff for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); 1267219820Sjeff p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl); 1268219820Sjeff p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { 1269219820Sjeff port_guid = osm_port_get_guid(p_port); 1270219820Sjeff 1271219820Sjeff /* 1272219820Sjeff Our own port is a special case in that we want to 1273219820Sjeff assign a LID to ourselves first, since we have to 1274219820Sjeff advertise that LID value to the other ports. 1275219820Sjeff 1276219820Sjeff For that reason, our node is treated separately and 1277219820Sjeff we will not add it to any of these lists. 1278219820Sjeff */ 1279219820Sjeff if (port_guid == p_mgr->p_subn->sm_port_guid) { 1280219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, 1281219820Sjeff "Skipping our own port 0x%016" PRIx64 "\n", 1282219820Sjeff cl_ntoh64(port_guid)); 1283219820Sjeff continue; 1284219820Sjeff } 1285219820Sjeff 1286219820Sjeff /* 1287219820Sjeff get the port lid range - we need to send it on first active 1288219820Sjeff sweep or if there was a change (the result of 1289219820Sjeff __osm_lid_mgr_get_port_lid) 1290219820Sjeff */ 1291219820Sjeff lid_changed = 1292219820Sjeff __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, 1293219820Sjeff &max_lid_ho); 1294219820Sjeff 1295219820Sjeff /* we can call the function to update the port info as it known 1296219820Sjeff to look for any field change and will only send an updated 1297219820Sjeff if required */ 1298219820Sjeff OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, 1299219820Sjeff "Assigned port 0x%016" PRIx64 1300219820Sjeff ", LID [%u,%u]\n", cl_ntoh64(port_guid), 1301219820Sjeff min_lid_ho, max_lid_ho); 1302219820Sjeff 1303219820Sjeff /* the proc returns the fact it sent a set port info */ 1304219820Sjeff if (__osm_lid_mgr_set_physp_pi 1305219820Sjeff (p_mgr, p_port, p_port->p_physp, cl_hton16(min_lid_ho))) 1306219820Sjeff p_mgr->send_set_reqs = TRUE; 1307219820Sjeff } /* all ports */ 1308219820Sjeff 1309219820Sjeff /* store the guid to lid table in persistent db */ 1310219820Sjeff osm_db_store(p_mgr->p_g2l); 1311219820Sjeff 1312219820Sjeff if (p_mgr->send_set_reqs == FALSE) 1313219820Sjeff signal = OSM_SIGNAL_DONE; 1314219820Sjeff else 1315219820Sjeff signal = OSM_SIGNAL_DONE_PENDING; 1316219820Sjeff 1317219820Sjeff CL_PLOCK_RELEASE(p_mgr->p_lock); 1318219820Sjeff 1319219820Sjeff OSM_LOG_EXIT(p_mgr->p_log); 1320219820Sjeff return (signal); 1321219820Sjeff} 1322