Blame opensm/osm_lid_mgr.c

Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * This software is available to you under a choice of one of two
Packit Service 54dbc3
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit Service 54dbc3
 * General Public License (GPL) Version 2, available from the file
Packit Service 54dbc3
 * COPYING in the main directory of this source tree, or the
Packit Service 54dbc3
 * OpenIB.org BSD license below:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *     Redistribution and use in source and binary forms, with or
Packit Service 54dbc3
 *     without modification, are permitted provided that the following
Packit Service 54dbc3
 *     conditions are met:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions of source code must retain the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions in binary form must reproduce the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer in the documentation and/or other materials
Packit Service 54dbc3
 *        provided with the distribution.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit Service 54dbc3
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service 54dbc3
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit Service 54dbc3
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit Service 54dbc3
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit Service 54dbc3
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 54dbc3
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit Service 54dbc3
 * SOFTWARE.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Abstract:
Packit Service 54dbc3
 *    Implementation of osm_lid_mgr_t.
Packit Service 54dbc3
 * This file implements the LID Manager object which is responsible for
Packit Service 54dbc3
 * assigning LIDs to all ports on the subnet.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * DATA STRUCTURES:
Packit Service 54dbc3
 *  p_subn->port_lid_tbl : a vector pointing from lid to its port.
Packit Service 54dbc3
 *  osm db guid2lid domain : a hash from guid to lid (min lid).
Packit Service 54dbc3
 *  p_subn->port_guid_tbl : a map from guid to discovered port obj.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * ALGORITHM:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * 0. we define a function to obtain the correct port lid:
Packit Service 54dbc3
 *    lid_mgr_get_port_lid( p_mgr, port, &min_lid, &max_lid ):
Packit Service 54dbc3
 *    0.1 if the port info lid matches the guid2lid return 0
Packit Service 54dbc3
 *    0.2 if the port info has a lid and that range is empty in
Packit Service 54dbc3
 *        port_lid_tbl, return 0 and update the port_lid_tbl and
Packit Service 54dbc3
 *        guid2lid
Packit Service 54dbc3
 *    0.3 else find an empty space in port_lid_tbl, update the
Packit Service 54dbc3
 *    port_lid_tbl and guid2lid, return 1 to flag a change required.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * 1. During initialization:
Packit Service 54dbc3
 *   1.1 initialize the guid2lid database domain.
Packit Service 54dbc3
 *   1.2 if reassign_lid is not set:
Packit Service 54dbc3
 *   1.2.1 read the persistent data for the domain.
Packit Service 54dbc3
 *   1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1)
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * 2. During SM port lid assignment:
Packit Service 54dbc3
 *   2.1 if reassign_lids is set, make it 2^lmc
Packit Service 54dbc3
 *   2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid
Packit Service 54dbc3
 *   2.3 call lid_mgr_get_port_lid for the SM port
Packit Service 54dbc3
 *   2.4 set the port info
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * 3. During all other ports lid assignment:
Packit Service 54dbc3
 *   3.1 go through all ports in the subnet
Packit Service 54dbc3
 *   3.1.1 call lid_mgr_get_port_lid
Packit Service 54dbc3
 *   3.1.2 if a change required send the port info
Packit Service 54dbc3
 *   3.2 if any change send the signal PENDING...
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * 4. Store the guid2lid
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
#if HAVE_CONFIG_H
Packit Service 54dbc3
#  include <config.h>
Packit Service 54dbc3
#endif				/* HAVE_CONFIG_H */
Packit Service 54dbc3
Packit Service 54dbc3
#include <stdlib.h>
Packit Service 54dbc3
#include <string.h>
Packit Service 54dbc3
#include <iba/ib_types.h>
Packit Service 54dbc3
#include <complib/cl_qmap.h>
Packit Service 54dbc3
#include <complib/cl_debug.h>
Packit Service 54dbc3
#include <opensm/osm_file_ids.h>
Packit Service 54dbc3
#define FILE_ID OSM_FILE_LID_MGR_C
Packit Service 54dbc3
#include <opensm/osm_lid_mgr.h>
Packit Service 54dbc3
#include <opensm/osm_sm.h>
Packit Service 54dbc3
#include <opensm/osm_log.h>
Packit Service 54dbc3
#include <opensm/osm_node.h>
Packit Service 54dbc3
#include <opensm/osm_switch.h>
Packit Service 54dbc3
#include <opensm/osm_helper.h>
Packit Service 54dbc3
#include <opensm/osm_msgdef.h>
Packit Service 54dbc3
#include <vendor/osm_vendor_api.h>
Packit Service 54dbc3
#include <opensm/osm_db_pack.h>
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
  lid range item of qlist
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
typedef struct osm_lid_mgr_range {
Packit Service 54dbc3
	cl_list_item_t item;
Packit Service 54dbc3
	uint16_t min_lid;
Packit Service 54dbc3
	uint16_t max_lid;
Packit Service 54dbc3
} osm_lid_mgr_range_t;
Packit Service 54dbc3
Packit Service 54dbc3
void osm_lid_mgr_construct(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	memset(p_mgr, 0, sizeof(*p_mgr));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_lid_mgr_destroy(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	while ((p_item = cl_qlist_remove_head(&p_mgr->free_ranges)) !=
Packit Service 54dbc3
	       cl_qlist_end(&p_mgr->free_ranges))
Packit Service 54dbc3
		free((osm_lid_mgr_range_t *) p_item);
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
Validate the guid to lid data by making sure that under the current
Packit Service 54dbc3
LMC we did not get duplicates. If we do flag them as errors and remove
Packit Service 54dbc3
the entry.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void lid_mgr_validate_db(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_qlist_t guids;
Packit Service 54dbc3
	osm_db_guid_elem_t *p_item;
Packit Service 54dbc3
	uint16_t lid;
Packit Service 54dbc3
	uint16_t min_lid;
Packit Service 54dbc3
	uint16_t max_lid;
Packit Service 54dbc3
	uint16_t lmc_mask;
Packit Service 54dbc3
	boolean_t lids_ok;
Packit Service 54dbc3
	uint8_t lmc_num_lids = (uint8_t) (1 << p_mgr->p_subn->opt.lmc);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	lmc_mask = ~(lmc_num_lids - 1);
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qlist_init(&guids);
Packit Service 54dbc3
Packit Service 54dbc3
	if (osm_db_guid2lid_guids(p_mgr->p_g2l, &guids)) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0310: "
Packit Service 54dbc3
			"could not get guid list\n");
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	while ((p_item = (osm_db_guid_elem_t *) cl_qlist_remove_head(&guids))
Packit Service 54dbc3
	       != (osm_db_guid_elem_t *) cl_qlist_end(&guids)) {
Packit Service 54dbc3
		if (osm_db_guid2lid_get(p_mgr->p_g2l, p_item->guid,
Packit Service 54dbc3
					&min_lid, &max_lid))
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0311: "
Packit Service 54dbc3
				"could not get lid for guid:0x%016" PRIx64 "\n",
Packit Service 54dbc3
				p_item->guid);
Packit Service 54dbc3
		else {
Packit Service 54dbc3
			lids_ok = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
			if (min_lid > max_lid || min_lid == 0
Packit Service 54dbc3
			    || p_item->guid == 0
Packit Service 54dbc3
			    || max_lid > p_mgr->p_subn->max_ucast_lid_ho) {
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
					"ERR 0312: "
Packit Service 54dbc3
					"Illegal LID range [%u:%u] for "
Packit Service 54dbc3
					"guid:0x%016" PRIx64 "\n", min_lid,
Packit Service 54dbc3
					max_lid, p_item->guid);
Packit Service 54dbc3
				lids_ok = FALSE;
Packit Service 54dbc3
			} else if (min_lid != max_lid
Packit Service 54dbc3
				   && (min_lid & lmc_mask) != min_lid) {
Packit Service 54dbc3
				/* check that if the lids define a range that is
Packit Service 54dbc3
				   valid for the current LMC mask */
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
					"ERR 0313: "
Packit Service 54dbc3
					"LID range [%u:%u] for guid:0x%016"
Packit Service 54dbc3
					PRIx64
Packit Service 54dbc3
					" is not aligned according to mask:0x%04x\n",
Packit Service 54dbc3
					min_lid, max_lid, p_item->guid,
Packit Service 54dbc3
					lmc_mask);
Packit Service 54dbc3
				lids_ok = FALSE;
Packit Service 54dbc3
			} else {
Packit Service 54dbc3
				/* check if the lids were not previously assigned */
Packit Service 54dbc3
				for (lid = min_lid; lid <= max_lid; lid++) {
Packit Service 54dbc3
					if (p_mgr->used_lids[lid]) {
Packit Service 54dbc3
						OSM_LOG(p_mgr->p_log,
Packit Service 54dbc3
							OSM_LOG_ERROR,
Packit Service 54dbc3
							"ERR 0314: "
Packit Service 54dbc3
							"0x%04x for guid:0x%016"
Packit Service 54dbc3
							PRIx64
Packit Service 54dbc3
							" was previously used\n",
Packit Service 54dbc3
							lid, p_item->guid);
Packit Service 54dbc3
						lids_ok = FALSE;
Packit Service 54dbc3
					}
Packit Service 54dbc3
				}
Packit Service 54dbc3
			}
Packit Service 54dbc3
Packit Service 54dbc3
			if (lids_ok)
Packit Service 54dbc3
				/* mark that it was visited */
Packit Service 54dbc3
				for (lid = min_lid; lid <= max_lid; lid++) {
Packit Service 54dbc3
					if (lid < min_lid + lmc_num_lids)
Packit Service 54dbc3
						p_mgr->used_lids[lid] = 1;
Packit Service 54dbc3
				}
Packit Service 54dbc3
			else if (osm_db_guid2lid_delete(p_mgr->p_g2l,
Packit Service 54dbc3
							p_item->guid))
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
					"ERR 0315: failed to delete entry for "
Packit Service 54dbc3
					"guid:0x%016" PRIx64 "\n",
Packit Service 54dbc3
					p_item->guid);
Packit Service 54dbc3
		}		/* got a lid */
Packit Service 54dbc3
		free(p_item);
Packit Service 54dbc3
	}			/* all guids */
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
ib_api_status_t osm_lid_mgr_init(IN osm_lid_mgr_t * p_mgr, IN osm_sm_t * sm)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status = IB_SUCCESS;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_lid_mgr_construct(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	p_mgr->sm = sm;
Packit Service 54dbc3
	p_mgr->p_log = sm->p_log;
Packit Service 54dbc3
	p_mgr->p_subn = sm->p_subn;
Packit Service 54dbc3
	p_mgr->p_db = sm->p_db;
Packit Service 54dbc3
	p_mgr->p_lock = sm->p_lock;
Packit Service 54dbc3
Packit Service 54dbc3
	/* we initialize and restore the db domain of guid to lid map */
Packit Service 54dbc3
	p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "guid2lid");
Packit Service 54dbc3
	if (!p_mgr->p_g2l) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0316: "
Packit Service 54dbc3
			"Error initializing Guid-to-Lid persistent database\n");
Packit Service 54dbc3
		status = IB_ERROR;
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qlist_init(&p_mgr->free_ranges);
Packit Service 54dbc3
Packit Service 54dbc3
	/* we use the stored guid to lid table if not forced to reassign */
Packit Service 54dbc3
	if (!p_mgr->p_subn->opt.reassign_lids) {
Packit Service 54dbc3
		if (osm_db_restore(p_mgr->p_g2l)) {
Packit Service 54dbc3
#ifndef __WIN__
Packit Service 54dbc3
			/*
Packit Service 54dbc3
			 * When Windows is BSODing, it might corrupt files that
Packit Service 54dbc3
			 * were previously opened for writing, even if the files
Packit Service 54dbc3
			 * are closed, so we might see corrupted guid2lid file.
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			if (p_mgr->p_subn->opt.exit_on_fatal) {
Packit Service 54dbc3
				osm_log_v2(p_mgr->p_log, OSM_LOG_SYS, FILE_ID,
Packit Service 54dbc3
					   "FATAL: Error restoring Guid-to-Lid "
Packit Service 54dbc3
					   "persistent database\n");
Packit Service 54dbc3
				status = IB_ERROR;
Packit Service 54dbc3
				goto Exit;
Packit Service 54dbc3
			} else
Packit Service 54dbc3
#endif
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
					"ERR 0317: Error restoring Guid-to-Lid "
Packit Service 54dbc3
					"persistent database\n");
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* we need to make sure we did not get duplicates with
Packit Service 54dbc3
		   current lmc */
Packit Service 54dbc3
		lid_mgr_validate_db(p_mgr);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return status;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static uint16_t trim_lid(IN uint16_t lid)
Packit Service 54dbc3
{
Packit Service 54dbc3
	if (lid > IB_LID_UCAST_END_HO || lid < IB_LID_UCAST_START_HO)
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
	return lid;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 initialize the manager for a new sweep:
Packit Service 54dbc3
 scans the known persistent assignment and port_lid_tbl
Packit Service 54dbc3
 re-calculate all empty ranges.
Packit Service 54dbc3
 cleanup invalid port_lid_tbl entries
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static int lid_mgr_init_sweep(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
Packit Service 54dbc3
	uint16_t max_defined_lid, max_persistent_lid, max_discovered_lid;
Packit Service 54dbc3
	uint16_t disc_min_lid, disc_max_lid, db_min_lid, db_max_lid;
Packit Service 54dbc3
	int status = 0;
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
	boolean_t is_free;
Packit Service 54dbc3
	osm_lid_mgr_range_t *p_range = NULL;
Packit Service 54dbc3
	osm_port_t *p_port;
Packit Service 54dbc3
	cl_qmap_t *p_port_guid_tbl;
Packit Service 54dbc3
	uint8_t lmc_num_lids = (uint8_t) (1 << p_mgr->p_subn->opt.lmc);
Packit Service 54dbc3
	uint16_t lmc_mask, req_lid, num_lids, lid;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
Packit Service 54dbc3
Packit Service 54dbc3
	/* We must discard previous guid2lid db if this is the first master
Packit Service 54dbc3
	 * sweep and reassign_lids option is TRUE.
Packit Service 54dbc3
	 * If we came out of standby and honor_guid2lid_file option is TRUE, we
Packit Service 54dbc3
	 * must restore guid2lid db. Otherwise if honor_guid2lid_file option is
Packit Service 54dbc3
	 * FALSE we must discard previous guid2lid db.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_mgr->p_subn->first_time_master_sweep == TRUE &&
Packit Service 54dbc3
	    p_mgr->p_subn->opt.reassign_lids == TRUE) {
Packit Service 54dbc3
		osm_db_clear(p_mgr->p_g2l);
Packit Service 54dbc3
		memset(p_mgr->used_lids, 0, sizeof(p_mgr->used_lids));
Packit Service 54dbc3
	} else if (p_mgr->p_subn->coming_out_of_standby == TRUE) {
Packit Service 54dbc3
		osm_db_clear(p_mgr->p_g2l);
Packit Service 54dbc3
		memset(p_mgr->used_lids, 0, sizeof(p_mgr->used_lids));
Packit Service 54dbc3
		if (p_mgr->p_subn->opt.honor_guid2lid_file == FALSE)
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"Ignore guid2lid file when coming out of standby\n");
Packit Service 54dbc3
		else {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"Honor current guid2lid file when coming out "
Packit Service 54dbc3
				"of standby\n");
Packit Service 54dbc3
			if (osm_db_restore(p_mgr->p_g2l))
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
					"ERR 0306: "
Packit Service 54dbc3
					"Error restoring Guid-to-Lid "
Packit Service 54dbc3
					"persistent database. Ignoring it\n");
Packit Service 54dbc3
			lid_mgr_validate_db(p_mgr);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* we need to cleanup the empty ranges list */
Packit Service 54dbc3
	while ((p_item = cl_qlist_remove_head(&p_mgr->free_ranges)) !=
Packit Service 54dbc3
	       cl_qlist_end(&p_mgr->free_ranges))
Packit Service 54dbc3
		free((osm_lid_mgr_range_t *) p_item);
Packit Service 54dbc3
Packit Service 54dbc3
	/* first clean up the port_by_lid_tbl */
Packit Service 54dbc3
	for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++)
Packit Service 54dbc3
		cl_ptr_vector_set(p_discovered_vec, lid, NULL);
Packit Service 54dbc3
Packit Service 54dbc3
	/* we if are in the first sweep and in reassign lids mode
Packit Service 54dbc3
	   we should ignore all the available info and simply define one
Packit Service 54dbc3
	   huge empty range */
Packit Service 54dbc3
	if (p_mgr->p_subn->first_time_master_sweep == TRUE &&
Packit Service 54dbc3
	    p_mgr->p_subn->opt.reassign_lids == TRUE) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Skipping all lids as we are reassigning them\n");
Packit Service 54dbc3
		p_range = malloc(sizeof(osm_lid_mgr_range_t));
Packit Service 54dbc3
		if (p_range)
Packit Service 54dbc3
			p_range->min_lid = 1;
Packit Service 54dbc3
		goto AfterScanningLids;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* go over all discovered ports and mark their entries */
Packit Service 54dbc3
	p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
Packit Service 54dbc3
Packit Service 54dbc3
	for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
Packit Service 54dbc3
	     p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl);
Packit Service 54dbc3
	     p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
Packit Service 54dbc3
		osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
Packit Service 54dbc3
		disc_min_lid = trim_lid(disc_min_lid);
Packit Service 54dbc3
		disc_max_lid = trim_lid(disc_max_lid);
Packit Service 54dbc3
		for (lid = disc_min_lid; lid <= disc_max_lid; lid++) {
Packit Service 54dbc3
			if (lid < disc_min_lid + lmc_num_lids)
Packit Service 54dbc3
				cl_ptr_vector_set(p_discovered_vec, lid, p_port);
Packit Service 54dbc3
			else
Packit Service 54dbc3
				cl_ptr_vector_set(p_discovered_vec, lid, NULL);
Packit Service 54dbc3
		}
Packit Service 54dbc3
		/* make sure the guid2lid entry is valid. If not, clean it. */
Packit Service 54dbc3
		if (osm_db_guid2lid_get(p_mgr->p_g2l,
Packit Service 54dbc3
					cl_ntoh64(osm_port_get_guid(p_port)),
Packit Service 54dbc3
					&db_min_lid, &db_max_lid))
Packit Service 54dbc3
			continue;
Packit Service 54dbc3
Packit Service 54dbc3
		if (!p_port->p_node->sw ||
Packit Service 54dbc3
		    osm_switch_sp0_is_lmc_capable(p_port->p_node->sw,
Packit Service 54dbc3
						  p_mgr->p_subn))
Packit Service 54dbc3
			num_lids = lmc_num_lids;
Packit Service 54dbc3
		else
Packit Service 54dbc3
			num_lids = 1;
Packit Service 54dbc3
Packit Service 54dbc3
		if (num_lids != 1 &&
Packit Service 54dbc3
		    ((db_min_lid & lmc_mask) != db_min_lid ||
Packit Service 54dbc3
		     db_max_lid - db_min_lid + 1 < num_lids)) {
Packit Service 54dbc3
			/* Not aligned, or not wide enough, then remove the entry */
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"Cleaning persistent entry for guid:"
Packit Service 54dbc3
				"0x%016" PRIx64 " illegal range:[0x%x:0x%x]\n",
Packit Service 54dbc3
				cl_ntoh64(osm_port_get_guid(p_port)),
Packit Service 54dbc3
				db_min_lid, db_max_lid);
Packit Service 54dbc3
			osm_db_guid2lid_delete(p_mgr->p_g2l,
Packit Service 54dbc3
					       cl_ntoh64
Packit Service 54dbc3
					       (osm_port_get_guid(p_port)));
Packit Service 54dbc3
			for (lid = db_min_lid; lid <= db_max_lid; lid++)
Packit Service 54dbc3
				p_mgr->used_lids[lid] = 0;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Our task is to find free lid ranges.
Packit Service 54dbc3
	   A lid can be used if
Packit Service 54dbc3
	   1. a persistent assignment exists
Packit Service 54dbc3
	   2. the lid is used by a discovered port that does not have a
Packit Service 54dbc3
	   persistent assignment.
Packit Service 54dbc3
Packit Service 54dbc3
	   scan through all lid values of both the persistent table and
Packit Service 54dbc3
	   discovered table.
Packit Service 54dbc3
	   If the lid has an assigned port in the discovered table:
Packit Service 54dbc3
	   * make sure the lid matches the persistent table, or
Packit Service 54dbc3
	   * there is no other persistent assignment for that lid.
Packit Service 54dbc3
	   * else cleanup the port_by_lid_tbl, mark this as empty range.
Packit Service 54dbc3
	   Else if the lid does not have an entry in the persistent table
Packit Service 54dbc3
	   mark it as free.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
Packit Service 54dbc3
	/* find the range of lids to scan */
Packit Service 54dbc3
	max_discovered_lid =
Packit Service 54dbc3
	    (uint16_t) cl_ptr_vector_get_size(p_discovered_vec);
Packit Service 54dbc3
	max_persistent_lid = sizeof(p_mgr->used_lids) - 1;
Packit Service 54dbc3
Packit Service 54dbc3
	/* but the vectors have one extra entry for lid=0 */
Packit Service 54dbc3
	if (max_discovered_lid)
Packit Service 54dbc3
		max_discovered_lid--;
Packit Service 54dbc3
Packit Service 54dbc3
	if (max_persistent_lid > max_discovered_lid)
Packit Service 54dbc3
		max_defined_lid = max_persistent_lid;
Packit Service 54dbc3
	else
Packit Service 54dbc3
		max_defined_lid = max_discovered_lid;
Packit Service 54dbc3
Packit Service 54dbc3
	for (lid = 1; lid <= max_defined_lid; lid++) {
Packit Service 54dbc3
		is_free = TRUE;
Packit Service 54dbc3
		/* first check to see if the lid is used by a persistent assignment */
Packit Service 54dbc3
		if (lid <= max_persistent_lid && p_mgr->used_lids[lid]) {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"0x%04x is not free as its mapped by the "
Packit Service 54dbc3
				"persistent db\n", lid);
Packit Service 54dbc3
			is_free = FALSE;
Packit Service 54dbc3
			/* check this is a discovered port */
Packit Service 54dbc3
		} else if (lid <= max_discovered_lid &&
Packit Service 54dbc3
			   (p_port = cl_ptr_vector_get(p_discovered_vec,
Packit Service 54dbc3
						       lid))) {
Packit Service 54dbc3
			/* we have a port. Now lets see if we can preserve its lid range. */
Packit Service 54dbc3
			/* For that, we need to make sure:
Packit Service 54dbc3
			   1. The port has a (legal) persistency entry. Then the
Packit Service 54dbc3
			   local lid is free (we will use the persistency value).
Packit Service 54dbc3
			   2. Can the port keep its local assignment?
Packit Service 54dbc3
			   a. Make sure the lid is aligned.
Packit Service 54dbc3
			   b. Make sure all needed lids (for the lmc) are free
Packit Service 54dbc3
			   according to persistency table.
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			/* qualify the guid of the port is not persistently
Packit Service 54dbc3
			   mapped to another range */
Packit Service 54dbc3
			if (!osm_db_guid2lid_get(p_mgr->p_g2l,
Packit Service 54dbc3
						 cl_ntoh64
Packit Service 54dbc3
						 (osm_port_get_guid(p_port)),
Packit Service 54dbc3
						 &db_min_lid, &db_max_lid)) {
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
					"0x%04x is free as it was "
Packit Service 54dbc3
					"discovered but mapped by the "
Packit Service 54dbc3
					"persistent db to [0x%04x:0x%04x]\n",
Packit Service 54dbc3
					lid, db_min_lid, db_max_lid);
Packit Service 54dbc3
			} else {
Packit Service 54dbc3
				/* can the port keep its assignment ? */
Packit Service 54dbc3
				/* get the lid range of that port, and the
Packit Service 54dbc3
				   required number of lids we are about to
Packit Service 54dbc3
				   assign to it */
Packit Service 54dbc3
				osm_port_get_lid_range_ho(p_port,
Packit Service 54dbc3
							  &disc_min_lid,
Packit Service 54dbc3
							  &disc_max_lid);
Packit Service 54dbc3
				if (!p_port->p_node->sw ||
Packit Service 54dbc3
				    osm_switch_sp0_is_lmc_capable
Packit Service 54dbc3
				    (p_port->p_node->sw, p_mgr->p_subn)) {
Packit Service 54dbc3
					disc_max_lid =
Packit Service 54dbc3
					    disc_min_lid + lmc_num_lids - 1;
Packit Service 54dbc3
					num_lids = lmc_num_lids;
Packit Service 54dbc3
				} else
Packit Service 54dbc3
					num_lids = 1;
Packit Service 54dbc3
Packit Service 54dbc3
				/* Make sure the lid is aligned */
Packit Service 54dbc3
				if (num_lids != 1
Packit Service 54dbc3
				    && (disc_min_lid & lmc_mask) !=
Packit Service 54dbc3
				    disc_min_lid) {
Packit Service 54dbc3
					/* The lid cannot be used */
Packit Service 54dbc3
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
						"0x%04x is free as it was "
Packit Service 54dbc3
						"discovered but not aligned\n",
Packit Service 54dbc3
						lid);
Packit Service 54dbc3
				} else {
Packit Service 54dbc3
					/* check that all needed lids are not persistently mapped */
Packit Service 54dbc3
					is_free = FALSE;
Packit Service 54dbc3
					for (req_lid = disc_min_lid + 1;
Packit Service 54dbc3
					     req_lid <= disc_max_lid;
Packit Service 54dbc3
					     req_lid++) {
Packit Service 54dbc3
						if (req_lid <=
Packit Service 54dbc3
						    max_persistent_lid &&
Packit Service 54dbc3
						    p_mgr->used_lids[req_lid]) {
Packit Service 54dbc3
							OSM_LOG(p_mgr->p_log,
Packit Service 54dbc3
								OSM_LOG_DEBUG,
Packit Service 54dbc3
								"0x%04x is free as it was discovered "
Packit Service 54dbc3
								"but mapped\n",
Packit Service 54dbc3
								lid);
Packit Service 54dbc3
							is_free = TRUE;
Packit Service 54dbc3
							break;
Packit Service 54dbc3
						}
Packit Service 54dbc3
					}
Packit Service 54dbc3
Packit Service 54dbc3
					if (is_free == FALSE) {
Packit Service 54dbc3
						/* This port will use its local lid, and consume the entire required lid range.
Packit Service 54dbc3
						   Thus we can skip that range. */
Packit Service 54dbc3
						/* If the disc_max_lid is greater then lid, we can skip right to it,
Packit Service 54dbc3
						   since we've done all neccessary checks on the lids in between. */
Packit Service 54dbc3
						if (disc_max_lid > lid)
Packit Service 54dbc3
							lid = disc_max_lid;
Packit Service 54dbc3
					}
Packit Service 54dbc3
				}
Packit Service 54dbc3
			}
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		if (is_free) {
Packit Service 54dbc3
			if (p_range)
Packit Service 54dbc3
				p_range->max_lid = lid;
Packit Service 54dbc3
			else {
Packit Service 54dbc3
				p_range = malloc(sizeof(osm_lid_mgr_range_t));
Packit Service 54dbc3
				if (p_range) {
Packit Service 54dbc3
					p_range->min_lid = lid;
Packit Service 54dbc3
					p_range->max_lid = lid;
Packit Service 54dbc3
				}
Packit Service 54dbc3
			}
Packit Service 54dbc3
		/* this lid is used so we need to finalize the previous free range */
Packit Service 54dbc3
		} else if (p_range) {
Packit Service 54dbc3
			cl_qlist_insert_tail(&p_mgr->free_ranges,
Packit Service 54dbc3
					     &p_range->item);
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"new free lid range [%u:%u]\n",
Packit Service 54dbc3
				p_range->min_lid, p_range->max_lid);
Packit Service 54dbc3
			p_range = NULL;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
AfterScanningLids:
Packit Service 54dbc3
	/* after scanning all known lids we need to extend the last range
Packit Service 54dbc3
	   to the max allowed lid */
Packit Service 54dbc3
	if (!p_range) {
Packit Service 54dbc3
		p_range = malloc(sizeof(osm_lid_mgr_range_t));
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   The p_range can be NULL in one of 2 cases:
Packit Service 54dbc3
		   1. If max_defined_lid == 0. In this case, we want the
Packit Service 54dbc3
		   entire range.
Packit Service 54dbc3
		   2. If all lids discovered in the loop where mapped. In this
Packit Service 54dbc3
		   case, no free range exists and we want to define it after the
Packit Service 54dbc3
		   last mapped lid.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		if (p_range)
Packit Service 54dbc3
			p_range->min_lid = lid;
Packit Service 54dbc3
	}
Packit Service 54dbc3
	if (p_range) {
Packit Service 54dbc3
		p_range->max_lid = p_mgr->p_subn->max_ucast_lid_ho;
Packit Service 54dbc3
		cl_qlist_insert_tail(&p_mgr->free_ranges, &p_range->item);
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"final free lid range [%u:%u]\n",
Packit Service 54dbc3
			p_range->min_lid, p_range->max_lid);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return status;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 check if the given range of lids is free
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static boolean_t lid_mgr_is_range_not_persistent(IN osm_lid_mgr_t * p_mgr,
Packit Service 54dbc3
						 IN uint16_t lid,
Packit Service 54dbc3
						 IN uint16_t num_lids)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint16_t i;
Packit Service 54dbc3
Packit Service 54dbc3
	for (i = lid; i < lid + num_lids; i++)
Packit Service 54dbc3
		if (p_mgr->used_lids[i])
Packit Service 54dbc3
			return FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	return TRUE;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
find a free lid range
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void lid_mgr_find_free_lid_range(IN osm_lid_mgr_t * p_mgr,
Packit Service 54dbc3
					IN uint8_t num_lids,
Packit Service 54dbc3
					OUT uint16_t * p_min_lid,
Packit Service 54dbc3
					OUT uint16_t * p_max_lid)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint16_t lid;
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
	cl_list_item_t *p_next_item;
Packit Service 54dbc3
	osm_lid_mgr_range_t *p_range = NULL;
Packit Service 54dbc3
	uint8_t lmc_num_lids;
Packit Service 54dbc3
	uint16_t lmc_mask;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "LMC = %u, number LIDs = %u\n",
Packit Service 54dbc3
		p_mgr->p_subn->opt.lmc, num_lids);
Packit Service 54dbc3
Packit Service 54dbc3
	lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc);
Packit Service 54dbc3
	lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Search the list of free lid ranges for a range which is big enough
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_item = cl_qlist_head(&p_mgr->free_ranges);
Packit Service 54dbc3
	while (p_item != cl_qlist_end(&p_mgr->free_ranges)) {
Packit Service 54dbc3
		p_next_item = cl_qlist_next(p_item);
Packit Service 54dbc3
		p_range = (osm_lid_mgr_range_t *) p_item;
Packit Service 54dbc3
Packit Service 54dbc3
		lid = p_range->min_lid;
Packit Service 54dbc3
Packit Service 54dbc3
		/* if we require more then one lid we must align to LMC */
Packit Service 54dbc3
		if (num_lids > 1) {
Packit Service 54dbc3
			if ((lid & lmc_mask) != lid)
Packit Service 54dbc3
				lid = (lid + lmc_num_lids) & lmc_mask;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* but we can be out of the range */
Packit Service 54dbc3
		if (lid + num_lids - 1 <= p_range->max_lid) {
Packit Service 54dbc3
			/* ok let us use that range */
Packit Service 54dbc3
			if (lid + num_lids - 1 == p_range->max_lid) {
Packit Service 54dbc3
				/* we consumed the entire range */
Packit Service 54dbc3
				cl_qlist_remove_item(&p_mgr->free_ranges,
Packit Service 54dbc3
						     p_item);
Packit Service 54dbc3
				free(p_item);
Packit Service 54dbc3
			} else
Packit Service 54dbc3
				/* only update the available range */
Packit Service 54dbc3
				p_range->min_lid = lid + num_lids;
Packit Service 54dbc3
Packit Service 54dbc3
			*p_min_lid = lid;
Packit Service 54dbc3
			*p_max_lid = (uint16_t) (lid + num_lids - 1);
Packit Service 54dbc3
			return;
Packit Service 54dbc3
		}
Packit Service 54dbc3
		p_item = p_next_item;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Couldn't find a free range of lids.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	*p_min_lid = *p_max_lid = 0;
Packit Service 54dbc3
	/* if we run out of lids, give an error and abort! */
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0307: "
Packit Service 54dbc3
		"OPENSM RAN OUT OF LIDS!!!\n");
Packit Service 54dbc3
	CL_ASSERT(0);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void lid_mgr_cleanup_discovered_port_lid_range(IN osm_lid_mgr_t * p_mgr,
Packit Service 54dbc3
						      IN osm_port_t * p_port)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
Packit Service 54dbc3
	uint16_t lid, min_lid, max_lid;
Packit Service 54dbc3
	uint16_t max_tbl_lid =
Packit Service 54dbc3
	    (uint16_t) (cl_ptr_vector_get_size(p_discovered_vec));
Packit Service 54dbc3
Packit Service 54dbc3
	osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
Packit Service 54dbc3
	min_lid = trim_lid(min_lid);
Packit Service 54dbc3
	max_lid = trim_lid(max_lid);
Packit Service 54dbc3
	for (lid = min_lid; lid <= max_lid; lid++)
Packit Service 54dbc3
		if (lid < max_tbl_lid &&
Packit Service 54dbc3
		    p_port == cl_ptr_vector_get(p_discovered_vec, lid))
Packit Service 54dbc3
			cl_ptr_vector_set(p_discovered_vec, lid, NULL);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 0.1 if the port info lid matches the guid2lid return 0
Packit Service 54dbc3
 0.2 if the port info has a lid and that range is empty in
Packit Service 54dbc3
     port_lid_tbl, return 0 and update the port_lid_tbl and
Packit Service 54dbc3
     guid2lid
Packit Service 54dbc3
 0.3 else find an empty space in port_lid_tbl, update the
Packit Service 54dbc3
 port_lid_tbl and guid2lid, return 1 to flag a change required.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static int lid_mgr_get_port_lid(IN osm_lid_mgr_t * p_mgr,
Packit Service 54dbc3
				IN osm_port_t * p_port,
Packit Service 54dbc3
				OUT uint16_t * p_min_lid,
Packit Service 54dbc3
				OUT uint16_t * p_max_lid)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint16_t lid, min_lid, max_lid;
Packit Service 54dbc3
	uint64_t guid;
Packit Service 54dbc3
	uint8_t num_lids = (1 << p_mgr->p_subn->opt.lmc);
Packit Service 54dbc3
	int lid_changed = 0;
Packit Service 54dbc3
	uint16_t lmc_mask;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/* get the lid from the guid2lid */
Packit Service 54dbc3
	guid = cl_ntoh64(osm_port_get_guid(p_port));
Packit Service 54dbc3
Packit Service 54dbc3
	/* if the port is a base switch port 0 then we only need one lid */
Packit Service 54dbc3
	if (p_port->p_node->sw &&
Packit Service 54dbc3
	    !osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn))
Packit Service 54dbc3
		num_lids = 1;
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_mgr->p_subn->first_time_master_sweep == TRUE &&
Packit Service 54dbc3
	    p_mgr->p_subn->opt.reassign_lids == TRUE)
Packit Service 54dbc3
		goto AssignLid;
Packit Service 54dbc3
Packit Service 54dbc3
	lmc_mask = ~(num_lids - 1);
Packit Service 54dbc3
Packit Service 54dbc3
	/* if the port matches the guid2lid */
Packit Service 54dbc3
	if (!osm_db_guid2lid_get(p_mgr->p_g2l, guid, &min_lid, &max_lid)) {
Packit Service 54dbc3
		*p_min_lid = min_lid;
Packit Service 54dbc3
		*p_max_lid = min_lid + num_lids - 1;
Packit Service 54dbc3
		if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port)))
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64
Packit Service 54dbc3
				" matches its known lid:%u\n", guid, min_lid);
Packit Service 54dbc3
		else {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"0x%016" PRIx64 " with lid:%u "
Packit Service 54dbc3
				"does not match its known lid:%u\n",
Packit Service 54dbc3
				guid, cl_ntoh16(osm_port_get_base_lid(p_port)),
Packit Service 54dbc3
				min_lid);
Packit Service 54dbc3
			lid_mgr_cleanup_discovered_port_lid_range(p_mgr,
Packit Service 54dbc3
								  p_port);
Packit Service 54dbc3
			/* we still need to send the setting to the target port */
Packit Service 54dbc3
			lid_changed = 1;
Packit Service 54dbc3
		}
Packit Service 54dbc3
		goto NewLidSet;
Packit Service 54dbc3
	} else
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"0x%016" PRIx64 " has no persistent lid assigned\n",
Packit Service 54dbc3
			guid);
Packit Service 54dbc3
Packit Service 54dbc3
	/* if the port info carries a lid it must be lmc aligned and not mapped
Packit Service 54dbc3
	   by the persistent storage  */
Packit Service 54dbc3
	min_lid = cl_ntoh16(osm_port_get_base_lid(p_port));
Packit Service 54dbc3
Packit Service 54dbc3
	/* we want to ignore the discovered lid if we are also on first sweep of
Packit Service 54dbc3
	   reassign lids flow */
Packit Service 54dbc3
	if (min_lid) {
Packit Service 54dbc3
		/* make sure lid is valid */
Packit Service 54dbc3
		if ((min_lid & lmc_mask) == min_lid) {
Packit Service 54dbc3
			/* is it free */
Packit Service 54dbc3
			if (lid_mgr_is_range_not_persistent
Packit Service 54dbc3
			    (p_mgr, min_lid, num_lids)) {
Packit Service 54dbc3
				*p_min_lid = min_lid;
Packit Service 54dbc3
				*p_max_lid = min_lid + num_lids - 1;
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
					"0x%016" PRIx64
Packit Service 54dbc3
					" lid range:[%u-%u] is free\n",
Packit Service 54dbc3
					guid, *p_min_lid, *p_max_lid);
Packit Service 54dbc3
				goto NewLidSet;
Packit Service 54dbc3
			} else
Packit Service 54dbc3
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
					"0x%016" PRIx64 " existing lid "
Packit Service 54dbc3
					"range:[%u:%u] is not free\n",
Packit Service 54dbc3
					guid, min_lid, min_lid + num_lids - 1);
Packit Service 54dbc3
		} else
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"0x%016" PRIx64 " existing lid range:"
Packit Service 54dbc3
				"[%u:%u] is not lmc aligned\n",
Packit Service 54dbc3
				guid, min_lid, min_lid + num_lids - 1);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
AssignLid:
Packit Service 54dbc3
	/* first cleanup the existing discovered lid range */
Packit Service 54dbc3
	lid_mgr_cleanup_discovered_port_lid_range(p_mgr, p_port);
Packit Service 54dbc3
Packit Service 54dbc3
	/* find an empty space */
Packit Service 54dbc3
	lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, p_max_lid);
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"0x%016" PRIx64 " assigned a new lid range:[%u-%u]\n",
Packit Service 54dbc3
		guid, *p_min_lid, *p_max_lid);
Packit Service 54dbc3
	lid_changed = 1;
Packit Service 54dbc3
Packit Service 54dbc3
NewLidSet:
Packit Service 54dbc3
	/* update the guid2lid db and used_lids */
Packit Service 54dbc3
	osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid);
Packit Service 54dbc3
	for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
Packit Service 54dbc3
		p_mgr->used_lids[lid] = 1;
Packit Service 54dbc3
Packit Service 54dbc3
	/* make sure the assigned lids are marked in port_lid_tbl */
Packit Service 54dbc3
	for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
Packit Service 54dbc3
		cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return lid_changed;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 Set to INIT the remote port of the given physical port
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
static void lid_mgr_set_remote_pi_state_to_init(IN osm_lid_mgr_t * p_mgr,
Packit Service 54dbc3
						IN osm_physp_t * p_physp)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_rem_physp == NULL)
Packit Service 54dbc3
		return;
Packit Service 54dbc3
Packit Service 54dbc3
	/* but in some rare cases the remote side might be non responsive */
Packit Service 54dbc3
	ib_port_info_set_port_state(&p_rem_physp->port_info, IB_LINK_INIT);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int lid_mgr_set_physp_pi(IN osm_lid_mgr_t * p_mgr,
Packit Service 54dbc3
				IN osm_port_t * p_port,
Packit Service 54dbc3
				IN osm_physp_t * p_physp, IN ib_net16_t lid)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint8_t payload[IB_SMP_DATA_SIZE];
Packit Service 54dbc3
	ib_port_info_t *p_pi = (ib_port_info_t *) payload;
Packit Service 54dbc3
	const ib_port_info_t *p_old_pi;
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	uint8_t mtu;
Packit Service 54dbc3
	uint8_t op_vls;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
	boolean_t send_set = FALSE;
Packit Service 54dbc3
	boolean_t send_client_rereg = FALSE;
Packit Service 54dbc3
	boolean_t update_mkey = FALSE;
Packit Service 54dbc3
	int ret = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Don't bother doing anything if this Physical Port is not valid.
Packit Service 54dbc3
	   This allows simplified code in the caller.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (!p_physp)
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
	port_num = osm_physp_get_port_num(p_physp);
Packit Service 54dbc3
	p_node = osm_physp_get_node_ptr(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Switch ports that are not numbered 0 should not be set
Packit Service 54dbc3
		   with the following attributes as they are set later
Packit Service 54dbc3
		   (during NO_CHANGE state in link mgr).
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Skipping switch port %u, GUID 0x%016" PRIx64 "\n",
Packit Service 54dbc3
			port_num, cl_ntoh64(osm_physp_get_port_guid(p_physp)));
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_old_pi = &p_physp->port_info;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   First, copy existing parameters from the PortInfo attribute we
Packit Service 54dbc3
	   already have for this node.
Packit Service 54dbc3
Packit Service 54dbc3
	   Second, update with default values that we know must be set for
Packit Service 54dbc3
	   every Physical Port and the LID and set the neighbor MTU field
Packit Service 54dbc3
	   appropriately.
Packit Service 54dbc3
Packit Service 54dbc3
	   Third, send the SMP to this physical port.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
Packit Service 54dbc3
	memcpy(payload, p_old_pi, sizeof(ib_port_info_t));
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Should never write back a value that is bigger then 3 in
Packit Service 54dbc3
	   the PortPhysicalState field, so cannot simply copy!
Packit Service 54dbc3
Packit Service 54dbc3
	   Actually we want to write there:
Packit Service 54dbc3
	   port physical state - no change
Packit Service 54dbc3
	   link down default state = polling
Packit Service 54dbc3
	   port state - no change
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_pi->state_info2 = 0x02;
Packit Service 54dbc3
	ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE);
Packit Service 54dbc3
Packit Service 54dbc3
	if (ib_port_info_get_link_down_def_state(p_pi) !=
Packit Service 54dbc3
	    ib_port_info_get_link_down_def_state(p_old_pi))
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	/* didn't get PortInfo before */
Packit Service 54dbc3
	if (!ib_port_info_get_port_state(p_old_pi))
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	p_pi->m_key = p_mgr->p_subn->opt.m_key;
Packit Service 54dbc3
	if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key))) {
Packit Service 54dbc3
		update_mkey = TRUE;
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
Packit Service 54dbc3
	if (memcmp(&p_pi->subnet_prefix, &p_old_pi->subnet_prefix,
Packit Service 54dbc3
		   sizeof(p_pi->subnet_prefix)))
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	p_port->lid = lid;
Packit Service 54dbc3
	p_pi->base_lid = lid;
Packit Service 54dbc3
	if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid,
Packit Service 54dbc3
		   sizeof(p_pi->base_lid))) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		 * Reset stored base_lid.
Packit Service 54dbc3
		 * On successful send, we'll update it when we'll get a reply.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		osm_physp_set_base_lid(p_physp, 0);
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
		p_mgr->dirty = TRUE;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   We are updating the ports with our local sm_base_lid
Packit Service 54dbc3
	   if for some reason currently received SM LID is different from our SM LID,
Packit Service 54dbc3
	   need to send client reregister to this port
Packit Service 54dbc3
	*/
Packit Service 54dbc3
	p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
Packit Service 54dbc3
	if (memcmp(&p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid,
Packit Service 54dbc3
		   sizeof(p_pi->master_sm_base_lid))) {
Packit Service 54dbc3
		send_client_rereg = TRUE;
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
Packit Service 54dbc3
	if (memcmp(&p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period,
Packit Service 54dbc3
		   sizeof(p_pi->m_key_lease_period)))
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	p_pi->mkey_lmc = 0;
Packit Service 54dbc3
	ib_port_info_set_mpb(p_pi, p_mgr->p_subn->opt.m_key_protect_bits);
Packit Service 54dbc3
	if (ib_port_info_get_mpb(p_pi) != ib_port_info_get_mpb(p_old_pi))
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   we want to set the timeout for both the switch port 0
Packit Service 54dbc3
	   and the CA ports
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	ib_port_info_set_timeout(p_pi, p_mgr->p_subn->opt.subnet_timeout);
Packit Service 54dbc3
	if (ib_port_info_get_timeout(p_pi) !=
Packit Service 54dbc3
	    ib_port_info_get_timeout(p_old_pi))
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	if (port_num != 0) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   CAs don't have a port 0, and for switch port 0,
Packit Service 54dbc3
		   the state bits are ignored.
Packit Service 54dbc3
		   This is not the switch management port
Packit Service 54dbc3
		 */
Packit Service 54dbc3
Packit Service 54dbc3
		/* p_pi->mkey_lmc is initialized earlier */
Packit Service 54dbc3
		ib_port_info_set_lmc(p_pi, p_mgr->p_subn->opt.lmc);
Packit Service 54dbc3
		if (ib_port_info_get_lmc(p_pi) !=
Packit Service 54dbc3
		    ib_port_info_get_lmc(p_old_pi))
Packit Service 54dbc3
			send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		/* calc new op_vls and mtu */
Packit Service 54dbc3
		op_vls = osm_physp_calc_link_op_vls(p_mgr->p_log, p_mgr->p_subn,
Packit Service 54dbc3
					      p_physp,
Packit Service 54dbc3
					      ib_port_info_get_op_vls(p_old_pi));
Packit Service 54dbc3
		mtu = osm_physp_calc_link_mtu(p_mgr->p_log, p_physp,
Packit Service 54dbc3
					      ib_port_info_get_neighbor_mtu(p_old_pi));
Packit Service 54dbc3
Packit Service 54dbc3
		ib_port_info_set_neighbor_mtu(p_pi, mtu);
Packit Service 54dbc3
Packit Service 54dbc3
		if (ib_port_info_get_neighbor_mtu(p_pi) !=
Packit Service 54dbc3
		    ib_port_info_get_neighbor_mtu(p_old_pi))
Packit Service 54dbc3
			send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		ib_port_info_set_op_vls(p_pi, op_vls);
Packit Service 54dbc3
		if (ib_port_info_get_op_vls(p_pi) !=
Packit Service 54dbc3
		    ib_port_info_get_op_vls(p_old_pi))
Packit Service 54dbc3
			send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Several timeout mechanisms:
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		ib_port_info_set_phy_and_overrun_err_thd(p_pi,
Packit Service 54dbc3
							 p_mgr->p_subn->opt.
Packit Service 54dbc3
							 local_phy_errors_threshold,
Packit Service 54dbc3
							 p_mgr->p_subn->opt.
Packit Service 54dbc3
							 overrun_errors_threshold);
Packit Service 54dbc3
Packit Service 54dbc3
		if (p_pi->error_threshold != p_old_pi->error_threshold)
Packit Service 54dbc3
			send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   To reset the port state machine we can send
Packit Service 54dbc3
		   PortInfo.State = DOWN. (see: 7.2.7 p171 lines:10-19)
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		if (mtu != ib_port_info_get_neighbor_mtu(p_old_pi) ||
Packit Service 54dbc3
		    op_vls != ib_port_info_get_op_vls(p_old_pi)) {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"Sending Link Down to GUID 0x%016"
Packit Service 54dbc3
				PRIx64 " port %d due to op_vls or "
Packit Service 54dbc3
				"mtu change. MTU:%u,%u VL_CAP:%u,%u\n",
Packit Service 54dbc3
				cl_ntoh64(osm_physp_get_port_guid(p_physp)),
Packit Service 54dbc3
				port_num, mtu,
Packit Service 54dbc3
				ib_port_info_get_neighbor_mtu(p_old_pi),
Packit Service 54dbc3
				op_vls, ib_port_info_get_op_vls(p_old_pi));
Packit Service 54dbc3
Packit Service 54dbc3
			/*
Packit Service 54dbc3
			   we need to make sure the internal DB will follow the
Packit Service 54dbc3
			   fact that the remote port is also going through
Packit Service 54dbc3
			   "down" state into "init"...
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			lid_mgr_set_remote_pi_state_to_init(p_mgr, p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
			ib_port_info_set_port_state(p_pi, IB_LINK_DOWN);
Packit Service 54dbc3
			if (ib_port_info_get_port_state(p_pi) !=
Packit Service 54dbc3
			    ib_port_info_get_port_state(p_old_pi))
Packit Service 54dbc3
				send_set = TRUE;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	} else if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) {
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		 * Configure Enh. SP0:
Packit Service 54dbc3
		 * Set MTU according to the mtu_cap.
Packit Service 54dbc3
		 * Set LMC if lmc_esp0 is defined.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		ib_port_info_set_neighbor_mtu(p_pi,
Packit Service 54dbc3
					      ib_port_info_get_mtu_cap
Packit Service 54dbc3
					      (p_old_pi));
Packit Service 54dbc3
		if (ib_port_info_get_neighbor_mtu(p_pi) !=
Packit Service 54dbc3
		    ib_port_info_get_neighbor_mtu(p_old_pi))
Packit Service 54dbc3
			send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Updating neighbor_mtu on switch GUID 0x%016" PRIx64
Packit Service 54dbc3
			" port 0 to:%u\n",
Packit Service 54dbc3
			cl_ntoh64(osm_physp_get_port_guid(p_physp)),
Packit Service 54dbc3
			ib_port_info_get_neighbor_mtu(p_pi));
Packit Service 54dbc3
Packit Service 54dbc3
		/* Configure LMC on enhanced SP0 */
Packit Service 54dbc3
		if (p_mgr->p_subn->opt.lmc_esp0) {
Packit Service 54dbc3
			/* p_pi->mkey_lmc is initialized earlier */
Packit Service 54dbc3
			ib_port_info_set_lmc(p_pi, p_mgr->p_subn->opt.lmc);
Packit Service 54dbc3
			if (ib_port_info_get_lmc(p_pi) !=
Packit Service 54dbc3
			    ib_port_info_get_lmc(p_old_pi))
Packit Service 54dbc3
				send_set = TRUE;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	context.pi_context.node_guid = osm_node_get_node_guid(p_node);
Packit Service 54dbc3
	context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
Packit Service 54dbc3
	context.pi_context.set_method = TRUE;
Packit Service 54dbc3
	context.pi_context.light_sweep = FALSE;
Packit Service 54dbc3
	context.pi_context.active_transition = FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	  For ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11:
Packit Service 54dbc3
	  need to set the cli_rereg bit when current SM LID at the Host
Packit Service 54dbc3
	  is different from our SM LID,
Packit Service 54dbc3
	  also if we are in first_time_master_sweep,
Packit Service 54dbc3
	  also if this port was just now discovered, then we should also set
Packit Service 54dbc3
	  the cli_rereg bit (we know that the port was just discovered
Packit Service 54dbc3
	  if its is_new field is set).
Packit Service 54dbc3
	*/
Packit Service 54dbc3
	if  ((send_client_rereg ||
Packit Service 54dbc3
	    p_mgr->p_subn->first_time_master_sweep == TRUE || p_port->is_new)
Packit Service 54dbc3
	    && !p_mgr->p_subn->opt.no_clients_rereg
Packit Service 54dbc3
	    && (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG)) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Setting client rereg on %s, port %d\n",
Packit Service 54dbc3
			p_port->p_node->print_desc, p_port->p_physp->port_num);
Packit Service 54dbc3
		ib_port_info_set_client_rereg(p_pi, 1);
Packit Service 54dbc3
		context.pi_context.client_rereg = TRUE;
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		ib_port_info_set_client_rereg(p_pi, 0);
Packit Service 54dbc3
		context.pi_context.client_rereg = FALSE;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* We need to send the PortInfo Set request with the new sm_lid
Packit Service 54dbc3
	   in the following cases:
Packit Service 54dbc3
	   1. There is a change in the values (send_set == TRUE)
Packit Service 54dbc3
	   2. first_time_master_sweep flag on the subnet is TRUE. This means the
Packit Service 54dbc3
	   SM just became master, and it then needs to send a PortInfo Set to
Packit Service 54dbc3
	   every port.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_mgr->p_subn->first_time_master_sweep == TRUE)
Packit Service 54dbc3
		send_set = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!send_set)
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
	status = osm_req_set(p_mgr->sm, osm_physp_get_dr_path_ptr(p_physp),
Packit Service 54dbc3
			     payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
Packit Service 54dbc3
			     cl_hton32(osm_physp_get_port_num(p_physp)),
Packit Service 54dbc3
			     FALSE, ib_port_info_get_m_key(&p_physp->port_info),
Packit Service 54dbc3
			     0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
	if (status != IB_SUCCESS)
Packit Service 54dbc3
		ret = -1;
Packit Service 54dbc3
	/* If we sent a new mkey above, update our guid2mkey map
Packit Service 54dbc3
	   now, on the assumption that the SubnSet succeeds
Packit Service 54dbc3
	*/
Packit Service 54dbc3
	if (update_mkey)
Packit Service 54dbc3
		osm_db_guid2mkey_set(p_mgr->p_subn->p_g2m,
Packit Service 54dbc3
				     cl_ntoh64(p_physp->port_guid),
Packit Service 54dbc3
				     cl_ntoh64(p_pi->m_key));
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return ret;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 Processes our own node
Packit Service 54dbc3
 Lock must already be held.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static int lid_mgr_process_our_sm_node(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_port_t *p_port;
Packit Service 54dbc3
	uint16_t min_lid_ho;
Packit Service 54dbc3
	uint16_t max_lid_ho;
Packit Service 54dbc3
	int ret;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Acquire our own port object.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_port = osm_get_port_by_guid(p_mgr->p_subn,
Packit Service 54dbc3
				      p_mgr->p_subn->sm_port_guid);
Packit Service 54dbc3
	if (!p_port) {
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0308: "
Packit Service 54dbc3
			"Can't acquire SM's port object, GUID 0x%016" PRIx64
Packit Service 54dbc3
			"\n", cl_ntoh64(p_mgr->p_subn->sm_port_guid));
Packit Service 54dbc3
		ret = -1;
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Determine the LID this SM will use for its own port.
Packit Service 54dbc3
	   Be careful.  With an LMC > 0, the bottom of the LID range becomes
Packit Service 54dbc3
	   unusable, since port hardware will mask off least significant bits,
Packit Service 54dbc3
	   leaving a LID of 0 (invalid).  Therefore, make sure that we always
Packit Service 54dbc3
	   configure the SM with a LID that has non-zero bits, even after
Packit Service 54dbc3
	   LMC masking by hardware.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Current base LID is %u\n", min_lid_ho);
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Update subnet object.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_mgr->p_subn->master_sm_base_lid = cl_hton16(min_lid_ho);
Packit Service 54dbc3
	p_mgr->p_subn->sm_base_lid = cl_hton16(min_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
		"Assigning SM's port 0x%016" PRIx64
Packit Service 54dbc3
		"\n\t\t\t\tto LID range [%u,%u]\n",
Packit Service 54dbc3
		cl_ntoh64(osm_port_get_guid(p_port)), min_lid_ho, max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Set the PortInfo the Physical Port associated with this Port.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	ret = lid_mgr_set_physp_pi(p_mgr, p_port, p_port->p_physp,
Packit Service 54dbc3
				   cl_hton16(min_lid_ho));
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return ret;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
int osm_lid_mgr_process_sm(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	int ret;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_mgr->p_subn->sm_port_guid);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
	/* initialize the port_lid_tbl and empty ranges list following the
Packit Service 54dbc3
	   persistent db */
Packit Service 54dbc3
	lid_mgr_init_sweep(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	ret = lid_mgr_process_our_sm_node(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_RELEASE(p_mgr->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return ret;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 1 go through all ports in the subnet.
Packit Service 54dbc3
 1.1 call lid_mgr_get_port_lid
Packit Service 54dbc3
 1.2 if a change is required send the port info
Packit Service 54dbc3
 2 if any change send the signal PENDING...
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
int osm_lid_mgr_process_subnet(IN osm_lid_mgr_t * p_mgr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_qmap_t *p_port_guid_tbl;
Packit Service 54dbc3
	osm_port_t *p_port;
Packit Service 54dbc3
	ib_net64_t port_guid;
Packit Service 54dbc3
	int lid_changed, ret = 0;
Packit Service 54dbc3
	uint16_t min_lid_ho, max_lid_ho;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_mgr);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_mgr->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_mgr->p_subn->sm_port_guid);
Packit Service 54dbc3
Packit Service 54dbc3
	p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
Packit Service 54dbc3
Packit Service 54dbc3
	for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl);
Packit Service 54dbc3
	     p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl);
Packit Service 54dbc3
	     p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
Packit Service 54dbc3
		port_guid = osm_port_get_guid(p_port);
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Our own port is a special case in that we want to
Packit Service 54dbc3
		   assign a LID to ourselves first, since we have to
Packit Service 54dbc3
		   advertise that LID value to the other ports.
Packit Service 54dbc3
Packit Service 54dbc3
		   For that reason, our node is treated separately and
Packit Service 54dbc3
		   we will not add it to any of these lists.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		if (port_guid == p_mgr->p_subn->sm_port_guid) {
Packit Service 54dbc3
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"Skipping our own port 0x%016" PRIx64 "\n",
Packit Service 54dbc3
				cl_ntoh64(port_guid));
Packit Service 54dbc3
			continue;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   get the port lid range - we need to send it on first active
Packit Service 54dbc3
		   sweep or if there was a change (the result of
Packit Service 54dbc3
		   lid_mgr_get_port_lid)
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		lid_changed = lid_mgr_get_port_lid(p_mgr, p_port,
Packit Service 54dbc3
						   &min_lid_ho, &max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
		/* we can call the function to update the port info as it known
Packit Service 54dbc3
		   to look for any field change and will only send an updated
Packit Service 54dbc3
		   if required */
Packit Service 54dbc3
		OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"Assigned port 0x%016" PRIx64 ", %s LID [%u,%u]\n",
Packit Service 54dbc3
			cl_ntoh64(port_guid), lid_changed ? "new" : "",
Packit Service 54dbc3
			min_lid_ho, max_lid_ho);
Packit Service 54dbc3
Packit Service 54dbc3
		/* the proc returns the fact it sent a set port info */
Packit Service 54dbc3
		if (lid_mgr_set_physp_pi(p_mgr, p_port, p_port->p_physp,
Packit Service 54dbc3
					 cl_hton16(min_lid_ho)))
Packit Service 54dbc3
			ret = -1;
Packit Service 54dbc3
	}			/* all ports */
Packit Service 54dbc3
Packit Service 54dbc3
	/* store the guid to lid table in persistent db */
Packit Service 54dbc3
	osm_db_store(p_mgr->p_g2l, p_mgr->p_subn->opt.fsync_high_avail_files);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_RELEASE(p_mgr->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_mgr->p_log);
Packit Service 54dbc3
	return ret;
Packit Service 54dbc3
}