Blame opensm/osm_port_info_rcv.c

Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2009 HNR Consulting. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2013 Oracle and/or its affiliates. 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_pi_rcv_t.
Packit Service 54dbc3
 * This object represents the PortInfo Receiver object.
Packit Service 54dbc3
 * This object is part of the opensm family of objects.
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 <string.h>
Packit Service 54dbc3
#include <stdlib.h>
Packit Service 54dbc3
#include <iba/ib_types.h>
Packit Service 54dbc3
#include <complib/cl_qmap.h>
Packit Service 54dbc3
#include <complib/cl_passivelock.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_PORT_INFO_RCV_C
Packit Service 54dbc3
#include <vendor/osm_vendor_api.h>
Packit Service 54dbc3
#include <opensm/osm_madw.h>
Packit Service 54dbc3
#include <opensm/osm_log.h>
Packit Service 54dbc3
#include <opensm/osm_node.h>
Packit Service 54dbc3
#include <opensm/osm_subnet.h>
Packit Service 54dbc3
#include <opensm/osm_mad_pool.h>
Packit Service 54dbc3
#include <opensm/osm_msgdef.h>
Packit Service 54dbc3
#include <opensm/osm_helper.h>
Packit Service 54dbc3
#include <opensm/osm_pkey.h>
Packit Service 54dbc3
#include <opensm/osm_remote_sm.h>
Packit Service 54dbc3
#include <opensm/osm_opensm.h>
Packit Service 54dbc3
#include <opensm/osm_ucast_mgr.h>
Packit Service 54dbc3
Packit Service 54dbc3
static void pi_rcv_check_and_fix_lid(osm_log_t * log, ib_port_info_t * pi,
Packit Service 54dbc3
				     osm_physp_t * p)
Packit Service 54dbc3
{
Packit Service 54dbc3
	if (PF(cl_ntoh16(pi->base_lid) > IB_LID_UCAST_END_HO)) {
Packit Service 54dbc3
		OSM_LOG(log, OSM_LOG_ERROR, "ERR 0F04: "
Packit Service 54dbc3
			"Got invalid base LID %u from the network. "
Packit Service 54dbc3
			"Corrected to %u\n", cl_ntoh16(pi->base_lid),
Packit Service 54dbc3
			cl_ntoh16(p->port_info.base_lid));
Packit Service 54dbc3
		pi->base_lid = p->port_info.base_lid;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void pi_rcv_process_endport(IN osm_sm_t * sm, IN osm_physp_t * p_physp,
Packit Service 54dbc3
				   IN const ib_port_info_t * p_pi)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	ib_net64_t port_guid;
Packit Service 54dbc3
	int extended;
Packit Service 54dbc3
	uint8_t rate, mtu, mpb;
Packit Service 54dbc3
	unsigned data_vls;
Packit Service 54dbc3
	cl_qmap_t *p_sm_tbl;
Packit Service 54dbc3
	osm_remote_sm_t *p_sm;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	port_guid = osm_physp_get_port_guid(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	/* HACK extended port 0 should be handled too! */
Packit Service 54dbc3
	if (osm_physp_get_port_num(p_physp) != 0 &&
Packit Service 54dbc3
	    ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN) {
Packit Service 54dbc3
		/* track the minimal endport MTU, rate, and operational VLs */
Packit Service 54dbc3
		mtu = ib_port_info_get_mtu_cap(p_pi);
Packit Service 54dbc3
		if (mtu < sm->p_subn->min_ca_mtu) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
				"Setting endport minimal MTU to:%u defined by port:0x%"
Packit Service 54dbc3
				PRIx64 "\n", mtu, cl_ntoh64(port_guid));
Packit Service 54dbc3
			sm->p_subn->min_ca_mtu = mtu;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
Packit Service 54dbc3
		rate = ib_port_info_compute_rate(p_pi, extended);
Packit Service 54dbc3
		if (ib_path_compare_rates(rate, sm->p_subn->min_ca_rate) < 0) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
				"Setting endport minimal rate to:%u defined by port:0x%"
Packit Service 54dbc3
				PRIx64 "\n", rate, cl_ntoh64(port_guid));
Packit Service 54dbc3
			sm->p_subn->min_ca_rate = rate;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1);
Packit Service 54dbc3
		if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1))
Packit Service 54dbc3
			data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1);
Packit Service 54dbc3
		if (data_vls >= IB_MAX_NUM_VLS)
Packit Service 54dbc3
			data_vls = IB_MAX_NUM_VLS - 1;
Packit Service 54dbc3
		if ((uint8_t)data_vls < sm->p_subn->min_data_vls) {
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
				"Setting endport minimal data VLs to:%u defined by port:0x%"
Packit Service 54dbc3
				PRIx64 "\n", data_vls, cl_ntoh64(port_guid));
Packit Service 54dbc3
			sm->p_subn->min_data_vls = data_vls;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* Check M_Key vs M_Key protect, can we control the port ? */
Packit Service 54dbc3
	mpb = ib_port_info_get_mpb(p_pi);
Packit Service 54dbc3
	if (mpb > 0 && p_pi->m_key == 0) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_INFO,
Packit Service 54dbc3
			"Port 0x%" PRIx64 " has unknown M_Key, protection level %u\n",
Packit Service 54dbc3
			cl_ntoh64(port_guid), mpb);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (port_guid != sm->p_subn->sm_port_guid) {
Packit Service 54dbc3
		p_sm_tbl = &sm->p_subn->sm_guid_tbl;
Packit Service 54dbc3
		if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) {
Packit Service 54dbc3
			/*
Packit Service 54dbc3
			 * Before querying the SM - we want to make sure we
Packit Service 54dbc3
			 * clean its state, so if the querying fails we
Packit Service 54dbc3
			 * recognize that this SM is not active.
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			p_sm =
Packit Service 54dbc3
			    (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl,
Packit Service 54dbc3
							    port_guid);
Packit Service 54dbc3
			if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
Packit Service 54dbc3
				/* clean it up */
Packit Service 54dbc3
				p_sm->smi.pri_state =
Packit Service 54dbc3
				    0xF0 & p_sm->smi.pri_state;
Packit Service 54dbc3
			if (sm->p_subn->opt.ignore_other_sm)
Packit Service 54dbc3
				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
					"Ignoring SM on port 0x%" PRIx64 "\n",
Packit Service 54dbc3
					cl_ntoh64(port_guid));
Packit Service 54dbc3
			else {
Packit Service 54dbc3
				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
					"Detected another SM. Requesting SMInfo "
Packit Service 54dbc3
					"from port 0x%" PRIx64 "\n",
Packit Service 54dbc3
					cl_ntoh64(port_guid));
Packit Service 54dbc3
Packit Service 54dbc3
				/*
Packit Service 54dbc3
				   This port indicates it's an SM and
Packit Service 54dbc3
				   it's not our own port.
Packit Service 54dbc3
				   Acquire the SMInfo Attribute.
Packit Service 54dbc3
				 */
Packit Service 54dbc3
				memset(&context, 0, sizeof(context));
Packit Service 54dbc3
				context.smi_context.set_method = FALSE;
Packit Service 54dbc3
				context.smi_context.port_guid = port_guid;
Packit Service 54dbc3
				status = osm_req_get(sm,
Packit Service 54dbc3
						     osm_physp_get_dr_path_ptr
Packit Service 54dbc3
						     (p_physp),
Packit Service 54dbc3
						     IB_MAD_ATTR_SM_INFO, 0,
Packit Service 54dbc3
						     FALSE,
Packit Service 54dbc3
						     ib_port_info_get_m_key(&p_physp->port_info),
Packit Service 54dbc3
						     0, CL_DISP_MSGID_NONE,
Packit Service 54dbc3
						     &context);
Packit Service 54dbc3
Packit Service 54dbc3
				if (status != IB_SUCCESS)
Packit Service 54dbc3
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
						"ERR 0F05: "
Packit Service 54dbc3
						"Failure requesting SMInfo (%s) "
Packit Service 54dbc3
						"from port 0x%" PRIx64 "\n",
Packit Service 54dbc3
						ib_get_err_str(status),
Packit Service 54dbc3
						cl_ntoh64(port_guid));
Packit Service 54dbc3
			}
Packit Service 54dbc3
		} else {
Packit Service 54dbc3
			p_sm =
Packit Service 54dbc3
			    (osm_remote_sm_t *) cl_qmap_remove(p_sm_tbl,
Packit Service 54dbc3
							       port_guid);
Packit Service 54dbc3
			if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
Packit Service 54dbc3
				free(p_sm);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void pi_rcv_process_switch_port0(IN osm_sm_t * sm,
Packit Service 54dbc3
					IN osm_node_t * p_node,
Packit Service 54dbc3
					IN osm_physp_t * p_physp,
Packit Service 54dbc3
					IN ib_port_info_t * p_pi)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	uint8_t port, num_ports;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_physp->need_update)
Packit Service 54dbc3
		sm->p_subn->ignore_existing_lfts = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Update the PortInfo attribute */
Packit Service 54dbc3
	osm_physp_set_port_info(p_physp, p_pi, sm);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Determine if base switch port 0 */
Packit Service 54dbc3
	if (p_node->sw &&
Packit Service 54dbc3
	    !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
Packit Service 54dbc3
		/* PortState is not used on BSP0 but just in case it is DOWN */
Packit Service 54dbc3
		p_physp->port_info = *p_pi;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Now, query PortInfo for the switch external ports */
Packit Service 54dbc3
	num_ports = osm_node_get_num_physp(p_node);
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 = FALSE;
Packit Service 54dbc3
	context.pi_context.light_sweep = FALSE;
Packit Service 54dbc3
	context.pi_context.active_transition = FALSE;
Packit Service 54dbc3
	context.pi_context.client_rereg = FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	for (port = 1; port < num_ports; port++) {
Packit Service 54dbc3
		status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
Packit Service 54dbc3
				     IB_MAD_ATTR_PORT_INFO, cl_hton32(port),
Packit Service 54dbc3
				     FALSE,
Packit Service 54dbc3
				     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
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F16: "
Packit Service 54dbc3
				"Failure initiating PortInfo request (%s)\n",
Packit Service 54dbc3
				ib_get_err_str(status));
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	pi_rcv_process_endport(sm, p_physp, p_pi);
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 The plock must be held before calling this function.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
static void pi_rcv_process_switch_ext_port(IN osm_sm_t * sm,
Packit Service 54dbc3
					   IN osm_node_t * p_node,
Packit Service 54dbc3
					   IN osm_physp_t * p_physp,
Packit Service 54dbc3
					   IN ib_port_info_t * p_pi)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status = IB_SUCCESS;
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	osm_physp_t *p_remote_physp, *physp0;
Packit Service 54dbc3
	osm_node_t *p_remote_node;
Packit Service 54dbc3
	ib_net64_t m_key;
Packit Service 54dbc3
	unsigned data_vls;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
	uint8_t remote_port_num;
Packit Service 54dbc3
	osm_dr_path_t path;
Packit Service 54dbc3
	int mlnx_epi_supported = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Check the state of the physical port.
Packit Service 54dbc3
	   If there appears to be something on the other end of the wire,
Packit Service 54dbc3
	   then ask for NodeInfo.  Ignore the switch management port.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	port_num = osm_physp_get_port_num(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	if (sm->p_subn->opt.fdr10)
Packit Service 54dbc3
		mlnx_epi_supported = is_mlnx_ext_port_info_supported(
Packit Service 54dbc3
						ib_node_info_get_vendor_id(&p_node->node_info),
Packit Service 54dbc3
						p_node->node_info.device_id);
Packit Service 54dbc3
Packit Service 54dbc3
	/* if in_sweep_hop_0 is TRUE, then this means the SM is on the switch,
Packit Service 54dbc3
	   and we got switchInfo of our local switch. Do not continue
Packit Service 54dbc3
	   probing through the switch. */
Packit Service 54dbc3
	switch (ib_port_info_get_port_state(p_pi)) {
Packit Service 54dbc3
	case IB_LINK_DOWN:
Packit Service 54dbc3
		p_remote_physp = osm_physp_get_remote(p_physp);
Packit Service 54dbc3
		if (p_remote_physp) {
Packit Service 54dbc3
			p_remote_node =
Packit Service 54dbc3
			    osm_physp_get_node_ptr(p_remote_physp);
Packit Service 54dbc3
			remote_port_num =
Packit Service 54dbc3
			    osm_physp_get_port_num(p_remote_physp);
Packit Service 54dbc3
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
				"Unlinking local node 0x%" PRIx64
Packit Service 54dbc3
				", port %u"
Packit Service 54dbc3
				"\n\t\t\t\tand remote node 0x%" PRIx64
Packit Service 54dbc3
				", port %u\n",
Packit Service 54dbc3
				cl_ntoh64(osm_node_get_node_guid
Packit Service 54dbc3
					  (p_node)), port_num,
Packit Service 54dbc3
				cl_ntoh64(osm_node_get_node_guid
Packit Service 54dbc3
					  (p_remote_node)),
Packit Service 54dbc3
				remote_port_num);
Packit Service 54dbc3
Packit Service 54dbc3
			if (sm->ucast_mgr.cache_valid)
Packit Service 54dbc3
				osm_ucast_cache_add_link(&sm->ucast_mgr,
Packit Service 54dbc3
							 p_physp,
Packit Service 54dbc3
							 p_remote_physp);
Packit Service 54dbc3
Packit Service 54dbc3
			osm_node_unlink(p_node, (uint8_t) port_num,
Packit Service 54dbc3
					p_remote_node,
Packit Service 54dbc3
					(uint8_t) remote_port_num);
Packit Service 54dbc3
Packit Service 54dbc3
		}
Packit Service 54dbc3
		break;
Packit Service 54dbc3
Packit Service 54dbc3
	case IB_LINK_INIT:
Packit Service 54dbc3
	case IB_LINK_ARMED:
Packit Service 54dbc3
	case IB_LINK_ACTIVE:
Packit Service 54dbc3
		physp0 = osm_node_get_physp_ptr(p_node, 0);
Packit Service 54dbc3
		if (mlnx_epi_supported) {
Packit Service 54dbc3
			m_key = ib_port_info_get_m_key(&physp0->port_info);
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 = FALSE;
Packit Service 54dbc3
			context.pi_context.light_sweep = FALSE;
Packit Service 54dbc3
			context.pi_context.active_transition = FALSE;
Packit Service 54dbc3
			context.pi_context.client_rereg = FALSE;
Packit Service 54dbc3
			status = osm_req_get(sm,
Packit Service 54dbc3
					     osm_physp_get_dr_path_ptr(p_physp),
Packit Service 54dbc3
					     IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
Packit Service 54dbc3
					     cl_hton32(port_num), FALSE, m_key,
Packit Service 54dbc3
					     0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
			if (status != IB_SUCCESS)
Packit Service 54dbc3
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F11: "
Packit Service 54dbc3
					"Failure initiating MLNX ExtPortInfo request (%s)\n",
Packit Service 54dbc3
					ib_get_err_str(status));
Packit Service 54dbc3
		}
Packit Service 54dbc3
		if (sm->p_subn->in_sweep_hop_0 == FALSE) {
Packit Service 54dbc3
			/*
Packit Service 54dbc3
			   To avoid looping forever, only probe the port if it
Packit Service 54dbc3
			   is NOT the port that responded to the SMP.
Packit Service 54dbc3
Packit Service 54dbc3
			   Request node info from the other end of this link:
Packit Service 54dbc3
			   1) Copy the current path from the parent node.
Packit Service 54dbc3
			   2) Extend the path to the next hop thru this port.
Packit Service 54dbc3
			   3) Request node info with the new path
Packit Service 54dbc3
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			if (p_pi->local_port_num !=
Packit Service 54dbc3
			    osm_physp_get_port_num(p_physp)) {
Packit Service 54dbc3
				path = *osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
				if (osm_dr_path_extend(&path,
Packit Service 54dbc3
						       osm_physp_get_port_num
Packit Service 54dbc3
						       (p_physp))) {
Packit Service 54dbc3
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
						"ERR 0F08: "
Packit Service 54dbc3
						"DR path with hop count %d couldn't be extended\n",
Packit Service 54dbc3
						path.hop_count);
Packit Service 54dbc3
					break;
Packit Service 54dbc3
				}
Packit Service 54dbc3
Packit Service 54dbc3
				memset(&context, 0, sizeof(context));
Packit Service 54dbc3
				context.ni_context.node_guid =
Packit Service 54dbc3
				    osm_node_get_node_guid(p_node);
Packit Service 54dbc3
				context.ni_context.port_num =
Packit Service 54dbc3
				    osm_physp_get_port_num(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
				status = osm_req_get(sm, &path,
Packit Service 54dbc3
						     IB_MAD_ATTR_NODE_INFO, 0,
Packit Service 54dbc3
						     TRUE, 0, 0,
Packit Service 54dbc3
						     CL_DISP_MSGID_NONE,
Packit Service 54dbc3
						     &context);
Packit Service 54dbc3
Packit Service 54dbc3
				if (status != IB_SUCCESS)
Packit Service 54dbc3
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
						"ERR 0F02: "
Packit Service 54dbc3
						"Failure initiating NodeInfo request (%s)\n",
Packit Service 54dbc3
						ib_get_err_str(status));
Packit Service 54dbc3
			} else
Packit Service 54dbc3
				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
					"Skipping SMP responder port %u\n",
Packit Service 54dbc3
					p_pi->local_port_num);
Packit Service 54dbc3
		}
Packit Service 54dbc3
		break;
Packit Service 54dbc3
Packit Service 54dbc3
	default:
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F03: "
Packit Service 54dbc3
			"Unknown link state = %u, port = %u\n",
Packit Service 54dbc3
			ib_port_info_get_port_state(p_pi),
Packit Service 54dbc3
			p_pi->local_port_num);
Packit Service 54dbc3
		break;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	if (ib_port_info_get_port_state(p_pi) > IB_LINK_INIT && p_node->sw &&
Packit Service 54dbc3
	    !ib_switch_info_get_state_change(&p_node->sw->switch_info) &&
Packit Service 54dbc3
	    p_node->sw->need_update == 1)
Packit Service 54dbc3
		p_node->sw->need_update = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	if (p_physp->need_update)
Packit Service 54dbc3
		sm->p_subn->ignore_existing_lfts = TRUE;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Update the PortInfo attribute.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	osm_physp_set_port_info(p_physp, p_pi, sm);
Packit Service 54dbc3
Packit Service 54dbc3
	if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN)
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
	p_remote_physp = osm_physp_get_remote(p_physp);
Packit Service 54dbc3
	if (p_remote_physp) {
Packit Service 54dbc3
		p_remote_node = osm_physp_get_node_ptr(p_remote_physp);
Packit Service 54dbc3
		if (p_remote_node->sw) {
Packit Service 54dbc3
			data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1);
Packit Service 54dbc3
			if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1))
Packit Service 54dbc3
				data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1);
Packit Service 54dbc3
			if (data_vls >= IB_MAX_NUM_VLS)
Packit Service 54dbc3
				data_vls = IB_MAX_NUM_VLS - 1;
Packit Service 54dbc3
			if ((uint8_t)data_vls < sm->p_subn->min_sw_data_vls) {
Packit Service 54dbc3
				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
					"Setting switch port minimal data VLs "
Packit Service 54dbc3
					"to:%u defined by node:0x%"
Packit Service 54dbc3
					PRIx64 ", port:%u\n", data_vls,
Packit Service 54dbc3
					cl_ntoh64(osm_node_get_node_guid(p_node)),
Packit Service 54dbc3
					port_num);
Packit Service 54dbc3
				sm->p_subn->min_sw_data_vls = data_vls;
Packit Service 54dbc3
			}
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void pi_rcv_process_ca_or_router_port(IN osm_sm_t * sm,
Packit Service 54dbc3
					     IN osm_node_t * p_node,
Packit Service 54dbc3
					     IN osm_physp_t * p_physp,
Packit Service 54dbc3
					     IN ib_port_info_t * p_pi)
Packit Service 54dbc3
{
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	UNUSED_PARAM(p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_physp_set_port_info(p_physp, p_pi, sm);
Packit Service 54dbc3
Packit Service 54dbc3
	pi_rcv_process_endport(sm, p_physp, p_pi);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
#define IBM_VENDOR_ID  (0x5076)
Packit Service 54dbc3
static void get_pkey_table(IN osm_log_t * p_log, IN osm_sm_t * sm,
Packit Service 54dbc3
			   IN osm_node_t * p_node, IN osm_physp_t * p_physp)
Packit Service 54dbc3
{
Packit Service 54dbc3
Packit Service 54dbc3
	osm_madw_context_t context;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	osm_dr_path_t path;
Packit Service 54dbc3
	osm_physp_t *physp0;
Packit Service 54dbc3
	ib_net64_t m_key;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
	uint16_t block_num, max_blocks;
Packit Service 54dbc3
	uint32_t attr_mod_ho;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	path = *osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	context.pkey_context.node_guid = osm_node_get_node_guid(p_node);
Packit Service 54dbc3
	context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp);
Packit Service 54dbc3
	context.pkey_context.set_method = FALSE;
Packit Service 54dbc3
Packit Service 54dbc3
	port_num = p_physp->port_num;
Packit Service 54dbc3
Packit Service 54dbc3
	if (!p_node->sw || port_num == 0)
Packit Service 54dbc3
		/* The maximum blocks is defined by the node info partition cap
Packit Service 54dbc3
		   for CA, router, and switch management ports. */
Packit Service 54dbc3
		max_blocks =
Packit Service 54dbc3
		    (cl_ntoh16(p_node->node_info.partition_cap) +
Packit Service 54dbc3
		     IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
Packit Service 54dbc3
		    / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
Packit Service 54dbc3
	else {
Packit Service 54dbc3
		/* This is a switch, and not a management port. The maximum blocks
Packit Service 54dbc3
		   is defined in the switch info partition enforcement cap. */
Packit Service 54dbc3
Packit Service 54dbc3
		/* Check for IBM eHCA firmware defect in reporting partition enforcement cap */
Packit Service 54dbc3
		if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) ==
Packit Service 54dbc3
		    IBM_VENDOR_ID)
Packit Service 54dbc3
			p_node->sw->switch_info.enforce_cap = 0;
Packit Service 54dbc3
Packit Service 54dbc3
		/* Bail out if this is a switch with no partition enforcement capability */
Packit Service 54dbc3
		if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0)
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
		max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) +
Packit Service 54dbc3
			      IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
Packit Service 54dbc3
			      1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp->pkeys.rcv_blocks_cnt = max_blocks;
Packit Service 54dbc3
	for (block_num = 0; block_num < max_blocks; block_num++) {
Packit Service 54dbc3
		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
Packit Service 54dbc3
		    osm_physp_get_port_num(p_physp) == 0) {
Packit Service 54dbc3
			attr_mod_ho = block_num;
Packit Service 54dbc3
			m_key = ib_port_info_get_m_key(&p_physp->port_info);
Packit Service 54dbc3
		} else {
Packit Service 54dbc3
			attr_mod_ho = block_num | (port_num << 16);
Packit Service 54dbc3
			physp0 = osm_node_get_physp_ptr(p_node, 0);
Packit Service 54dbc3
			m_key = ib_port_info_get_m_key(&physp0->port_info);
Packit Service 54dbc3
		}
Packit Service 54dbc3
		status = osm_req_get(sm, &path, IB_MAD_ATTR_P_KEY_TABLE,
Packit Service 54dbc3
				     cl_hton32(attr_mod_ho), FALSE,
Packit Service 54dbc3
				     m_key, 0, CL_DISP_MSGID_NONE, &context);
Packit Service 54dbc3
Packit Service 54dbc3
		if (status != IB_SUCCESS) {
Packit Service 54dbc3
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0F12: "
Packit Service 54dbc3
				"Failure initiating PKeyTable request (%s)\n",
Packit Service 54dbc3
				ib_get_err_str(status));
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void pi_rcv_get_pkey_slvl_vla_tables(IN osm_sm_t * sm,
Packit Service 54dbc3
					    IN osm_node_t * p_node,
Packit Service 54dbc3
					    IN osm_physp_t * p_physp)
Packit Service 54dbc3
{
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	get_pkey_table(sm->p_log, sm, p_node, p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int osm_pi_rcv_update_self(IN osm_sm_t *sm, IN osm_physp_t *p_physp,
Packit Service 54dbc3
				  IN ib_port_info_t *p_pi)
Packit Service 54dbc3
{
Packit Service 54dbc3
	if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN)
Packit Service 54dbc3
		return 0;
Packit Service 54dbc3
Packit Service 54dbc3
	if (sm->p_subn->need_update || p_physp->need_update > 1 ||
Packit Service 54dbc3
	    ib_port_info_get_port_state(p_pi) == IB_LINK_INIT)
Packit Service 54dbc3
		return 1;
Packit Service 54dbc3
Packit Service 54dbc3
	return 0;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static void pi_rcv_process_set(IN osm_sm_t * sm, IN osm_node_t * p_node,
Packit Service 54dbc3
			       IN uint8_t port_num, IN osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_physp_t *p_physp;
Packit Service 54dbc3
	ib_net64_t port_guid;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	ib_port_info_t *p_pi;
Packit Service 54dbc3
	osm_pi_context_t *p_context;
Packit Service 54dbc3
	osm_log_level_t level;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_context = osm_madw_get_pi_context_ptr(p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
	CL_ASSERT(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	port_guid = osm_physp_get_port_guid(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_pi = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
Packit Service 54dbc3
	/* check for error */
Packit Service 54dbc3
	if (cl_ntoh16(p_smp->status) & 0x7fff) {
Packit Service 54dbc3
		/* If port already ACTIVE, don't treat status 7 as error */
Packit Service 54dbc3
		if (p_context->active_transition &&
Packit Service 54dbc3
		    (cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c) {
Packit Service 54dbc3
			level = OSM_LOG_INFO;
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_INFO,
Packit Service 54dbc3
				"Received error status 0x%x for SetResp() during ACTIVE transition\n",
Packit Service 54dbc3
				cl_ntoh16(p_smp->status) & 0x7fff);
Packit Service 54dbc3
			/* Should there be a subsequent Get to validate that port is ACTIVE ? */
Packit Service 54dbc3
		} else {
Packit Service 54dbc3
			level = OSM_LOG_ERROR;
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F10: "
Packit Service 54dbc3
				"Received error status for SetResp()\n");
Packit Service 54dbc3
		}
Packit Service 54dbc3
		osm_dump_port_info_v2(sm->p_log, osm_node_get_node_guid(p_node),
Packit Service 54dbc3
				      port_guid, port_num, p_pi, FILE_ID, level);
Packit Service 54dbc3
	} else
Packit Service 54dbc3
		osm_physp_set_port_info(p_physp, p_pi, sm);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"Received logical SetResp() for GUID 0x%" PRIx64
Packit Service 54dbc3
		", port num %u"
Packit Service 54dbc3
		"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
Packit Service 54dbc3
		" TID 0x%" PRIx64 "\n",
Packit Service 54dbc3
		cl_ntoh64(port_guid), port_num,
Packit Service 54dbc3
		cl_ntoh64(osm_node_get_node_guid(p_node)),
Packit Service 54dbc3
		cl_ntoh64(p_smp->trans_id));
Packit Service 54dbc3
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static int osm_pi_rcv_update_neighbor(IN osm_physp_t *p_physp)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_physp_t *p_rem_physp = p_physp->p_remote_physp;
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Our own port - this is the only case where CA port
Packit Service 54dbc3
	 * is discovered before its' neighbor port
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (!p_rem_physp)
Packit Service 54dbc3
		return p_physp->need_update;
Packit Service 54dbc3
Packit Service 54dbc3
	p_node = osm_physp_get_node_ptr(p_rem_physp);
Packit Service 54dbc3
	CL_ASSERT(p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	/* CA/RTR to CA/RTR connection */
Packit Service 54dbc3
	if (!p_node->sw)
Packit Service 54dbc3
		return p_physp->need_update;
Packit Service 54dbc3
Packit Service 54dbc3
	return (ib_switch_info_get_state_change(&p_node->sw->switch_info) ? 1 : p_physp->need_update);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_pi_rcv_process(IN void *context, IN void *data)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_sm_t *sm = context;
Packit Service 54dbc3
	osm_madw_t *p_madw = data;
Packit Service 54dbc3
	ib_port_info_t *p_pi;
Packit Service 54dbc3
	ib_smp_t *p_smp;
Packit Service 54dbc3
	osm_port_t *p_port;
Packit Service 54dbc3
	osm_physp_t *p_physp;
Packit Service 54dbc3
	osm_dr_path_t *p_dr_path;
Packit Service 54dbc3
	osm_node_t *p_node;
Packit Service 54dbc3
	osm_pi_context_t *p_context;
Packit Service 54dbc3
	ib_net64_t port_guid, node_guid;
Packit Service 54dbc3
	uint8_t port_num;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(sm);
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(sm->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit Service 54dbc3
	p_context = osm_madw_get_pi_context_ptr(p_madw);
Packit Service 54dbc3
	p_pi = ib_smp_get_payload_ptr(p_smp);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Attribute modifier has already been validated upon MAD receive,
Packit Service 54dbc3
	 * which means that port_num has to be valid - it originated from
Packit Service 54dbc3
	 * the request attribute modifier.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod);
Packit Service 54dbc3
Packit Service 54dbc3
	port_guid = p_context->port_guid;
Packit Service 54dbc3
	node_guid = p_context->node_guid;
Packit Service 54dbc3
Packit Service 54dbc3
	osm_dump_port_info_v2(sm->p_log, node_guid, port_guid, port_num, p_pi,
Packit Service 54dbc3
			      FILE_ID, OSM_LOG_DEBUG);
Packit Service 54dbc3
Packit Service 54dbc3
	/* On receipt of client reregister, clear the reregister bit so
Packit Service 54dbc3
	   reregistering won't be sent again and again */
Packit Service 54dbc3
	if (p_context->set_method &&
Packit Service 54dbc3
	    (ib_port_info_get_client_rereg(p_pi) || p_context->client_rereg)) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"Client reregister received on response\n");
Packit Service 54dbc3
		ib_port_info_set_client_rereg(p_pi, 0);
Packit Service 54dbc3
		p_context->client_rereg = FALSE;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   we might get a response during a light sweep looking for a change in
Packit Service 54dbc3
	   the status of a remote port that did not respond in earlier sweeps.
Packit Service 54dbc3
	   So if the context of the Get was light_sweep - we do not need to
Packit Service 54dbc3
	   do anything with the response - just flag that we need a heavy sweep
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_context->light_sweep == TRUE) {
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"Got light sweep response from remote port of parent node "
Packit Service 54dbc3
			"GUID 0x%" PRIx64 " port 0x%016" PRIx64
Packit Service 54dbc3
			", Commencing heavy sweep\n",
Packit Service 54dbc3
			cl_ntoh64(node_guid), cl_ntoh64(port_guid));
Packit Service 54dbc3
		sm->p_subn->force_heavy_sweep = TRUE;
Packit Service 54dbc3
		sm->p_subn->ignore_existing_lfts = TRUE;
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
Packit Service 54dbc3
	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
Packit Service 54dbc3
	if (PF(!p_port)) {
Packit Service 54dbc3
		CL_PLOCK_RELEASE(sm->p_lock);
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: "
Packit Service 54dbc3
			"No port object for port with GUID 0x%" PRIx64
Packit Service 54dbc3
			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
Packit Service 54dbc3
			", TID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			cl_ntoh64(port_guid),
Packit Service 54dbc3
			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	p_node = p_port->p_node;
Packit Service 54dbc3
	CL_ASSERT(p_node);
Packit Service 54dbc3
Packit Service 54dbc3
	if (PF(p_pi->local_port_num > p_node->node_info.num_ports)) {
Packit Service 54dbc3
		CL_PLOCK_RELEASE(sm->p_lock);
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F15: "
Packit Service 54dbc3
			"Received PortInfo for port GUID 0x%" PRIx64 " is "
Packit Service 54dbc3
			"non-compliant and is being ignored since the "
Packit Service 54dbc3
			"local port num %u > num ports %u\n",
Packit Service 54dbc3
			cl_ntoh64(port_guid), p_pi->local_port_num,
Packit Service 54dbc3
			p_node->node_info.num_ports);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   If we were setting the PortInfo, then receiving
Packit Service 54dbc3
	   this attribute was not part of sweeping the subnet.
Packit Service 54dbc3
	   In this case, just update the PortInfo attribute.
Packit Service 54dbc3
Packit Service 54dbc3
	   In an unfortunate blunder, the IB spec defines the
Packit Service 54dbc3
	   return method for Set() as a GetResp().  Thus, we can't
Packit Service 54dbc3
	   use the method (what would have been SetResp()) to determine
Packit Service 54dbc3
	   our course of action.  So, we have to carry this extra
Packit Service 54dbc3
	   boolean around to determine if we were doing Get() or Set().
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_context->set_method)
Packit Service 54dbc3
		pi_rcv_process_set(sm, p_node, port_num, p_madw);
Packit Service 54dbc3
	else {
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   This PortInfo arrived because we did a Get() method,
Packit Service 54dbc3
		   most likely due to a subnet sweep in progress.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
Packit Service 54dbc3
			"Discovered port num %u with GUID 0x%" PRIx64
Packit Service 54dbc3
			" for parent node GUID 0x%" PRIx64
Packit Service 54dbc3
			", TID 0x%" PRIx64 "\n",
Packit Service 54dbc3
			port_num, cl_ntoh64(port_guid),
Packit Service 54dbc3
			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
Packit Service 54dbc3
Packit Service 54dbc3
		p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit Service 54dbc3
Packit Service 54dbc3
		CL_ASSERT(p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
		/* Update the directed route path to this port
Packit Service 54dbc3
		   in case the old path is no longer usable. */
Packit Service 54dbc3
		p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
Packit Service 54dbc3
		osm_dr_path_init(p_dr_path, p_smp->hop_count,
Packit Service 54dbc3
				 p_smp->initial_path);
Packit Service 54dbc3
Packit Service 54dbc3
		p_physp->need_update = osm_pi_rcv_update_self(sm, p_physp, p_pi);
Packit Service 54dbc3
Packit Service 54dbc3
		switch (osm_node_get_type(p_node)) {
Packit Service 54dbc3
		case IB_NODE_TYPE_CA:
Packit Service 54dbc3
		case IB_NODE_TYPE_ROUTER:
Packit Service 54dbc3
			if (!p_node->physp_discovered[port_num]) {
Packit Service 54dbc3
				p_port->discovery_count++;
Packit Service 54dbc3
				p_node->physp_discovered[port_num] = 1;
Packit Service 54dbc3
			}
Packit Service 54dbc3
			p_physp->need_update = osm_pi_rcv_update_neighbor(p_physp);
Packit Service 54dbc3
			pi_rcv_process_ca_or_router_port(sm, p_node, p_physp,
Packit Service 54dbc3
							 p_pi);
Packit Service 54dbc3
			break;
Packit Service 54dbc3
		case IB_NODE_TYPE_SWITCH:
Packit Service 54dbc3
			if (!p_node->physp_discovered[port_num]) {
Packit Service 54dbc3
				p_port->discovery_count++;
Packit Service 54dbc3
				p_node->physp_discovered[port_num] = 1;
Packit Service 54dbc3
			}
Packit Service 54dbc3
			if (port_num == 0)
Packit Service 54dbc3
				pi_rcv_process_switch_port0(sm, p_node,
Packit Service 54dbc3
							    p_physp, p_pi);
Packit Service 54dbc3
			else
Packit Service 54dbc3
				pi_rcv_process_switch_ext_port(sm, p_node,
Packit Service 54dbc3
							       p_physp, p_pi);
Packit Service 54dbc3
Packit Service 54dbc3
			if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) {
Packit Service 54dbc3
				CL_PLOCK_RELEASE(sm->p_lock);
Packit Service 54dbc3
				goto Exit;
Packit Service 54dbc3
			}
Packit Service 54dbc3
			break;
Packit Service 54dbc3
		default:
Packit Service 54dbc3
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: "
Packit Service 54dbc3
				"Unknown node type %u with GUID 0x%" PRIx64
Packit Service 54dbc3
				"\n", osm_node_get_type(p_node),
Packit Service 54dbc3
				cl_ntoh64(node_guid));
Packit Service 54dbc3
			break;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Get the tables on the physp.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		if (p_physp->need_update || (p_node->sw &&
Packit Service 54dbc3
					     p_node->sw->need_update))
Packit Service 54dbc3
			pi_rcv_get_pkey_slvl_vla_tables(sm, p_node, p_physp);
Packit Service 54dbc3
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	CL_PLOCK_RELEASE(sm->p_lock);
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   Release the lock before jumping here!!
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	OSM_LOG_EXIT(sm->p_log);
Packit Service 54dbc3
}