|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* This software is available to you under a choice of one of two
|
|
Packit |
13e616 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
13e616 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
13e616 |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
13e616 |
* OpenIB.org BSD license below:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
13e616 |
* without modification, are permitted provided that the following
|
|
Packit |
13e616 |
* conditions are met:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions of source code must retain the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer in the documentation and/or other materials
|
|
Packit |
13e616 |
* provided with the distribution.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
13e616 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
13e616 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
13e616 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
13e616 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
13e616 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
13e616 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
13e616 |
* SOFTWARE.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Abstract:
|
|
Packit |
13e616 |
* Implementation of osm_link_mgr_t.
|
|
Packit |
13e616 |
* This file implements the Link Manager object.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if HAVE_CONFIG_H
|
|
Packit |
13e616 |
# include <config.h>
|
|
Packit |
13e616 |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#include <string.h>
|
|
Packit |
13e616 |
#include <iba/ib_types.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_LINK_MGR_C
|
|
Packit |
13e616 |
#include <opensm/osm_sm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_node.h>
|
|
Packit |
13e616 |
#include <opensm/osm_switch.h>
|
|
Packit |
13e616 |
#include <opensm/osm_helper.h>
|
|
Packit |
13e616 |
#include <opensm/osm_msgdef.h>
|
|
Packit |
13e616 |
#include <opensm/osm_opensm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_db_pack.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_opensm_t *p_osm = sm->p_subn->p_osm;
|
|
Packit |
13e616 |
struct osm_routing_engine *re = p_osm->routing_engine_used;
|
|
Packit |
13e616 |
ib_net16_t slid;
|
|
Packit |
13e616 |
ib_net16_t smlid;
|
|
Packit |
13e616 |
uint8_t sl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!(re && re->path_sl &&
|
|
Packit |
13e616 |
(slid = osm_physp_get_base_lid(p_physp)))) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Use default SL if routing engine does not provide a
|
|
Packit |
13e616 |
* path SL lookup callback.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return sm->p_subn->opt.sm_sl;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
smlid = sm->p_subn->sm_base_lid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Call into routing engine to find proper SL */
|
|
Packit |
13e616 |
sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl,
|
|
Packit |
13e616 |
slid, smlid);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return sl;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int link_mgr_set_physp_pi(osm_sm_t * sm, IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN uint8_t port_state)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint8_t payload[IB_SMP_DATA_SIZE], payload2[IB_SMP_DATA_SIZE];
|
|
Packit |
13e616 |
ib_port_info_t *p_pi = (ib_port_info_t *) payload;
|
|
Packit |
13e616 |
ib_mlnx_ext_port_info_t *p_epi = (ib_mlnx_ext_port_info_t *) payload2;
|
|
Packit |
13e616 |
const ib_port_info_t *p_old_pi;
|
|
Packit |
13e616 |
const ib_mlnx_ext_port_info_t *p_old_epi;
|
|
Packit |
13e616 |
osm_madw_context_t context;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
ib_api_status_t status;
|
|
Packit |
13e616 |
uint8_t port_num, mtu, op_vls, smsl = OSM_DEFAULT_SL;
|
|
Packit |
13e616 |
boolean_t esp0 = FALSE, send_set = FALSE, send_set2 = FALSE;
|
|
Packit |
13e616 |
osm_physp_t *p_remote_physp, *physp0 = NULL;
|
|
Packit |
13e616 |
int issue_ext = 0, fdr10_change = 0;
|
|
Packit |
13e616 |
int ret = 0;
|
|
Packit |
13e616 |
ib_net32_t attr_mod, cap_mask;
|
|
Packit |
13e616 |
boolean_t update_mkey = FALSE;
|
|
Packit |
13e616 |
ib_net64_t m_key = 0;
|
|
Packit Service |
5cdc0c |
ib_net16_t capability_mask2;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = osm_physp_get_node_ptr(p_physp);
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_old_pi = &p_physp->port_info;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_num = osm_physp_get_port_num(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memcpy(payload, p_old_pi, sizeof(ib_port_info_t));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
|
|
Packit |
13e616 |
port_num == 0) {
|
|
Packit |
13e616 |
/* Need to make sure LID and SMLID fields in PortInfo are not 0 */
|
|
Packit |
13e616 |
if (!p_pi->base_lid) {
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(sm->p_subn,
|
|
Packit |
13e616 |
osm_physp_get_port_guid(p_physp));
|
|
Packit |
13e616 |
CL_ASSERT(p_port);
|
|
Packit |
13e616 |
p_pi->base_lid = p_port->lid;
|
|
Packit |
13e616 |
sm->lid_mgr.dirty = TRUE;
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we are initializing the ports with our local sm_base_lid */
|
|
Packit |
13e616 |
p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid;
|
|
Packit |
13e616 |
if (p_pi->master_sm_base_lid != p_old_pi->master_sm_base_lid)
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
physp0 = osm_node_get_physp_ptr(p_node, 0);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (port_num == 0) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
CAs don't have a port 0, and for switch port 0,
|
|
Packit |
13e616 |
we need to check if this is enhanced or base port 0.
|
|
Packit |
13e616 |
For base port 0 the following parameters are not valid
|
|
Packit |
13e616 |
(IBA 1.2.1 p.830 table 146).
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (!p_node->sw) {
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: "
|
|
Packit |
13e616 |
"Cannot find switch by guid: 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(p_node->node_info.node_guid));
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)
|
|
Packit |
13e616 |
== FALSE) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Even for base port 0 we might have to set smsl
|
|
Packit |
13e616 |
(if we are using lash routing) */
|
|
Packit |
13e616 |
smsl = link_mgr_get_smsl(sm, p_physp);
|
|
Packit |
13e616 |
if (smsl != ib_port_info_get_master_smsl(p_old_pi)) {
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Setting SMSL to %d on port 0 GUID 0x%016"
|
|
Packit |
13e616 |
PRIx64 "\n", smsl,
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_physp)));
|
|
Packit |
13e616 |
/* Enter if base lid and master_sm_lid didn't change */
|
|
Packit |
13e616 |
} else if (send_set == FALSE) {
|
|
Packit |
13e616 |
/* This means the switch doesn't support
|
|
Packit |
13e616 |
enhanced port 0 and we don't need to
|
|
Packit |
13e616 |
change SMSL. Can skip it. */
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Skipping port 0, GUID 0x%016" PRIx64
|
|
Packit |
13e616 |
"\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_physp)));
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
esp0 = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Should never write back a value that is bigger then 3 in
|
|
Packit |
13e616 |
the PortPhysicalState field - so can not simply copy!
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Actually we want to write there:
|
|
Packit |
13e616 |
port physical state - no change,
|
|
Packit |
13e616 |
link down default state = polling
|
|
Packit |
13e616 |
port state - as requested.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_pi->state_info2 = 0x02;
|
|
Packit |
13e616 |
ib_port_info_set_port_state(p_pi, port_state);
|
|
Packit |
13e616 |
|
|
Packit Service |
5cdc0c |
/* Determine ports' M_Key and CapabilityMask2 */
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH &&
|
|
Packit Service |
5cdc0c |
osm_physp_get_port_num(p_physp) != 0) {
|
|
Packit |
13e616 |
m_key = ib_port_info_get_m_key(&physp0->port_info);
|
|
Packit Service |
5cdc0c |
capability_mask2 = physp0->port_info.capability_mask2;
|
|
Packit Service |
5cdc0c |
} else {
|
|
Packit |
13e616 |
m_key = ib_port_info_get_m_key(p_pi);
|
|
Packit Service |
5cdc0c |
capability_mask2 = p_pi->capability_mask2;
|
|
Packit Service |
5cdc0c |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Check whether this is base port0 smsl handling only */
|
|
Packit |
13e616 |
if (port_num == 0 && esp0 == FALSE) {
|
|
Packit |
13e616 |
ib_port_info_set_master_smsl(p_pi, smsl);
|
|
Packit |
13e616 |
goto Send;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_port_info_get_link_down_def_state(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_link_down_def_state(p_old_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* didn't get PortInfo before */
|
|
Packit |
13e616 |
if (!ib_port_info_get_port_state(p_old_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we only change port fields if we do not change state */
|
|
Packit |
13e616 |
if (port_state == IB_LINK_NO_CHANGE) {
|
|
Packit |
13e616 |
/* The following fields are relevant only for CA port, router, or Enh. SP0 */
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
|
|
Packit |
13e616 |
port_num == 0) {
|
|
Packit |
13e616 |
p_pi->m_key = sm->p_subn->opt.m_key;
|
|
Packit |
13e616 |
if (memcmp(&p_pi->m_key, &p_old_pi->m_key,
|
|
Packit |
13e616 |
sizeof(p_pi->m_key))) {
|
|
Packit |
13e616 |
update_mkey = TRUE;
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix;
|
|
Packit |
13e616 |
if (memcmp(&p_pi->subnet_prefix,
|
|
Packit |
13e616 |
&p_old_pi->subnet_prefix,
|
|
Packit |
13e616 |
sizeof(p_pi->subnet_prefix)))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
smsl = link_mgr_get_smsl(sm, p_physp);
|
|
Packit |
13e616 |
if (smsl != ib_port_info_get_master_smsl(p_old_pi)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_port_info_set_master_smsl(p_pi, smsl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Setting SMSL to %d on GUID 0x%016"
|
|
Packit |
13e616 |
PRIx64 ", port %d\n", smsl,
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_physp)), port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_pi->m_key_lease_period =
|
|
Packit |
13e616 |
sm->p_subn->opt.m_key_lease_period;
|
|
Packit |
13e616 |
if (memcmp(&p_pi->m_key_lease_period,
|
|
Packit |
13e616 |
&p_old_pi->m_key_lease_period,
|
|
Packit |
13e616 |
sizeof(p_pi->m_key_lease_period)))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_pi->mkey_lmc = 0;
|
|
Packit |
13e616 |
ib_port_info_set_mpb(p_pi, sm->p_subn->opt.m_key_protect_bits);
|
|
Packit |
13e616 |
if (esp0 == FALSE || sm->p_subn->opt.lmc_esp0)
|
|
Packit |
13e616 |
ib_port_info_set_lmc(p_pi, sm->p_subn->opt.lmc);
|
|
Packit |
13e616 |
if (ib_port_info_get_lmc(p_old_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_lmc(p_pi) ||
|
|
Packit |
13e616 |
ib_port_info_get_mpb(p_old_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_mpb(p_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_port_info_set_timeout(p_pi,
|
|
Packit |
13e616 |
sm->p_subn->opt.
|
|
Packit |
13e616 |
subnet_timeout);
|
|
Packit |
13e616 |
if (ib_port_info_get_timeout(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_timeout(p_old_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Several timeout mechanisms:
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_remote_physp = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
if (port_num != 0 && p_remote_physp) {
|
|
Packit |
13e616 |
if (osm_node_get_type(osm_physp_get_node_ptr(p_physp))
|
|
Packit |
13e616 |
== IB_NODE_TYPE_ROUTER) {
|
|
Packit |
13e616 |
ib_port_info_set_hoq_lifetime(p_pi,
|
|
Packit |
13e616 |
sm->p_subn->
|
|
Packit |
13e616 |
opt.
|
|
Packit |
13e616 |
leaf_head_of_queue_lifetime);
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
if (osm_node_get_type
|
|
Packit |
13e616 |
(osm_physp_get_node_ptr(p_physp)) ==
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
/* Is remote end CA or router (a leaf port) ? */
|
|
Packit |
13e616 |
if (osm_node_get_type
|
|
Packit |
13e616 |
(osm_physp_get_node_ptr(p_remote_physp)) !=
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
ib_port_info_set_hoq_lifetime(p_pi,
|
|
Packit |
13e616 |
sm->
|
|
Packit |
13e616 |
p_subn->
|
|
Packit |
13e616 |
opt.
|
|
Packit |
13e616 |
leaf_head_of_queue_lifetime);
|
|
Packit |
13e616 |
ib_port_info_set_vl_stall_count(p_pi,
|
|
Packit |
13e616 |
sm->
|
|
Packit |
13e616 |
p_subn->
|
|
Packit |
13e616 |
opt.
|
|
Packit |
13e616 |
leaf_vl_stall_count);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
ib_port_info_set_hoq_lifetime(p_pi,
|
|
Packit |
13e616 |
sm->
|
|
Packit |
13e616 |
p_subn->
|
|
Packit |
13e616 |
opt.
|
|
Packit |
13e616 |
head_of_queue_lifetime);
|
|
Packit |
13e616 |
ib_port_info_set_vl_stall_count(p_pi,
|
|
Packit |
13e616 |
sm->
|
|
Packit |
13e616 |
p_subn->
|
|
Packit |
13e616 |
opt.
|
|
Packit |
13e616 |
vl_stall_count);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (ib_port_info_get_hoq_lifetime(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_hoq_lifetime(p_old_pi) ||
|
|
Packit |
13e616 |
ib_port_info_get_vl_stall_count(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_vl_stall_count(p_old_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_port_info_set_phy_and_overrun_err_thd(p_pi,
|
|
Packit |
13e616 |
sm->p_subn->opt.
|
|
Packit |
13e616 |
local_phy_errors_threshold,
|
|
Packit |
13e616 |
sm->p_subn->opt.
|
|
Packit |
13e616 |
overrun_errors_threshold);
|
|
Packit |
13e616 |
if (p_pi->error_threshold != p_old_pi->error_threshold)
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Set the easy common parameters for all port types,
|
|
Packit |
13e616 |
then determine the neighbor MTU.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (sm->p_subn->opt.force_link_width &&
|
|
Packit |
13e616 |
(sm->p_subn->opt.force_link_width < IB_LINK_WIDTH_ACTIVE_2X ||
|
|
Packit Service |
5cdc0c |
(capability_mask2 &
|
|
Packit |
13e616 |
IB_PORT_CAP2_IS_LINK_WIDTH_2X_SUPPORTED)) &&
|
|
Packit |
13e616 |
(sm->p_subn->opt.force_link_width != IB_LINK_WIDTH_SET_LWS ||
|
|
Packit |
13e616 |
p_pi->link_width_enabled != p_pi->link_width_supported)) {
|
|
Packit |
13e616 |
p_pi->link_width_enabled = sm->p_subn->opt.force_link_width;
|
|
Packit |
13e616 |
if (p_pi->link_width_enabled != p_old_pi->link_width_enabled)
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->opt.force_link_speed &&
|
|
Packit |
13e616 |
(sm->p_subn->opt.force_link_speed != IB_LINK_SPEED_SET_LSS ||
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_enabled(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_sup(p_pi))) {
|
|
Packit |
13e616 |
ib_port_info_set_link_speed_enabled(p_pi,
|
|
Packit |
13e616 |
sm->p_subn->opt.
|
|
Packit |
13e616 |
force_link_speed);
|
|
Packit |
13e616 |
if (p_pi->link_speed != p_old_pi->link_speed)
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sm->p_subn->opt.fdr10 &&
|
|
Packit |
13e616 |
p_physp->ext_port_info.link_speed_supported & FDR10) {
|
|
Packit |
13e616 |
if (sm->p_subn->opt.fdr10 == 1) { /* enable */
|
|
Packit |
13e616 |
if (!(p_physp->ext_port_info.link_speed_enabled & FDR10))
|
|
Packit |
13e616 |
fdr10_change = 1;
|
|
Packit |
13e616 |
} else { /* disable */
|
|
Packit |
13e616 |
if (p_physp->ext_port_info.link_speed_enabled & FDR10)
|
|
Packit |
13e616 |
fdr10_change = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (fdr10_change) {
|
|
Packit |
13e616 |
p_old_epi = &p_physp->ext_port_info;
|
|
Packit |
13e616 |
memcpy(payload2, p_old_epi,
|
|
Packit |
13e616 |
sizeof(ib_mlnx_ext_port_info_t));
|
|
Packit |
13e616 |
p_epi->state_change_enable = 0x01;
|
|
Packit |
13e616 |
if (sm->p_subn->opt.fdr10 == 1)
|
|
Packit |
13e616 |
p_epi->link_speed_enabled = FDR10;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
p_epi->link_speed_enabled = 0;
|
|
Packit |
13e616 |
send_set2 = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH &&
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_physp) != 0) {
|
|
Packit |
13e616 |
cap_mask = physp0->port_info.capability_mask;
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
cap_mask = p_pi->capability_mask;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS)
|
|
Packit |
13e616 |
issue_ext = 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Do peer ports support extended link speeds ? */
|
|
Packit |
13e616 |
if (port_num != 0 && p_remote_physp) {
|
|
Packit |
13e616 |
osm_physp_t *rphysp0;
|
|
Packit |
13e616 |
ib_net32_t rem_cap_mask;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_remote_physp->p_node) ==
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
rphysp0 = osm_node_get_physp_ptr(p_remote_physp->p_node, 0);
|
|
Packit |
13e616 |
rem_cap_mask = rphysp0->port_info.capability_mask;
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
rem_cap_mask = p_remote_physp->port_info.capability_mask;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS &&
|
|
Packit |
13e616 |
rem_cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) {
|
|
Packit |
13e616 |
if (sm->p_subn->opt.force_link_speed_ext &&
|
|
Packit |
13e616 |
(sm->p_subn->opt.force_link_speed_ext != IB_LINK_SPEED_EXT_SET_LSES ||
|
|
Packit |
13e616 |
p_pi->link_speed_ext_enabled !=
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_ext_sup(p_pi))) {
|
|
Packit |
13e616 |
p_pi->link_speed_ext_enabled = sm->p_subn->opt.force_link_speed_ext;
|
|
Packit |
13e616 |
if (p_pi->link_speed_ext_enabled !=
|
|
Packit |
13e616 |
p_old_pi->link_speed_ext_enabled)
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* calc new op_vls and mtu */
|
|
Packit |
13e616 |
op_vls =
|
|
Packit |
13e616 |
osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp,
|
|
Packit |
13e616 |
ib_port_info_get_op_vls(p_old_pi));
|
|
Packit |
13e616 |
mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp,
|
|
Packit |
13e616 |
ib_port_info_get_neighbor_mtu(p_old_pi));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_port_info_set_neighbor_mtu(p_pi, mtu);
|
|
Packit |
13e616 |
if (ib_port_info_get_neighbor_mtu(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_neighbor_mtu(p_old_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_port_info_set_op_vls(p_pi, op_vls);
|
|
Packit |
13e616 |
if (ib_port_info_get_op_vls(p_pi) !=
|
|
Packit |
13e616 |
ib_port_info_get_op_vls(p_old_pi))
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* provide the vl_high_limit from the qos mgr */
|
|
Packit |
13e616 |
if (sm->p_subn->opt.qos &&
|
|
Packit |
13e616 |
p_physp->vl_high_limit != p_old_pi->vl_high_limit) {
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
p_pi->vl_high_limit = p_physp->vl_high_limit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Send:
|
|
Packit |
13e616 |
context.pi_context.active_transition = FALSE;
|
|
Packit |
13e616 |
if (port_state != IB_LINK_NO_CHANGE &&
|
|
Packit |
13e616 |
port_state != ib_port_info_get_port_state(p_old_pi)) {
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
if (port_state == IB_LINK_ACTIVE)
|
|
Packit |
13e616 |
context.pi_context.active_transition = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
context.pi_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit |
13e616 |
context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
|
|
Packit |
13e616 |
context.pi_context.set_method = TRUE;
|
|
Packit |
13e616 |
context.pi_context.light_sweep = FALSE;
|
|
Packit |
13e616 |
context.pi_context.client_rereg = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* We need to send the PortInfoSet request with the new sm_lid
|
|
Packit |
13e616 |
in the following cases:
|
|
Packit |
13e616 |
1. There is a change in the values (send_set == TRUE)
|
|
Packit |
13e616 |
2. This is a switch external port (so it wasn't handled yet by
|
|
Packit |
13e616 |
osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE,
|
|
Packit |
13e616 |
which means the SM just became master, and it then needs to send at
|
|
Packit |
13e616 |
PortInfoSet to every port.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num
|
|
Packit |
13e616 |
&& sm->p_subn->first_time_master_sweep == TRUE)
|
|
Packit |
13e616 |
send_set = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!send_set)
|
|
Packit |
13e616 |
goto SEND_EPI;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
attr_mod = cl_hton32(port_num);
|
|
Packit |
13e616 |
if (issue_ext)
|
|
Packit |
13e616 |
attr_mod |= cl_hton32(1 << 31); /* AM SMSupportExtendedSpeeds */
|
|
Packit |
13e616 |
status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
|
|
Packit |
13e616 |
payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
|
|
Packit |
13e616 |
attr_mod, FALSE, m_key,
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
if (status)
|
|
Packit |
13e616 |
ret = -1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* If we sent a new mkey above, update our guid2mkey map
|
|
Packit |
13e616 |
now, on the assumption that the SubnSet succeeds
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (update_mkey)
|
|
Packit |
13e616 |
osm_db_guid2mkey_set(sm->p_subn->p_g2m,
|
|
Packit |
13e616 |
cl_ntoh64(p_physp->port_guid),
|
|
Packit |
13e616 |
cl_ntoh64(p_pi->m_key));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
SEND_EPI:
|
|
Packit |
13e616 |
if (send_set2) {
|
|
Packit |
13e616 |
status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
|
|
Packit |
13e616 |
payload2, sizeof(payload2),
|
|
Packit |
13e616 |
IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
|
|
Packit |
13e616 |
cl_hton32(port_num), FALSE, m_key,
|
|
Packit |
13e616 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit |
13e616 |
if (status)
|
|
Packit |
13e616 |
ret = -1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return ret;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int link_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node,
|
|
Packit |
13e616 |
IN const uint8_t link_state)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_physp_t *p_physp, *p_physp_remote;
|
|
Packit |
13e616 |
uint32_t i, num_physp;
|
|
Packit |
13e616 |
int ret = 0;
|
|
Packit |
13e616 |
uint8_t current_state;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Node 0x%" PRIx64 " going to %s\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_node_get_node_guid(p_node)),
|
|
Packit |
13e616 |
ib_get_port_state_str(link_state));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Set the PortInfo for every Physical Port associated
|
|
Packit |
13e616 |
with this Port. Start iterating with port 1, since the linkstate
|
|
Packit |
13e616 |
is not applicable to the management port on switches.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
num_physp = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
for (i = 0; i < num_physp; i++) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Don't bother doing anything if this Physical Port is not valid.
|
|
Packit |
13e616 |
or if the state of the port is already better then the
|
|
Packit |
13e616 |
specified state.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i);
|
|
Packit |
13e616 |
if (!p_physp)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
current_state = osm_physp_get_port_state(p_physp);
|
|
Packit |
13e616 |
if (current_state == IB_LINK_DOWN)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Set PortState to DOWN in case Remote Physical Port is
|
|
Packit |
13e616 |
unreachable. We have to check this for all ports, except
|
|
Packit |
13e616 |
port zero.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_physp_remote = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
if ((i != 0) && (!p_physp_remote ||
|
|
Packit |
13e616 |
!osm_physp_is_valid(p_physp_remote))) {
|
|
Packit |
13e616 |
if (current_state != IB_LINK_INIT)
|
|
Packit |
13e616 |
link_mgr_set_physp_pi(sm, p_physp, IB_LINK_DOWN);
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Normally we only send state update if state is lower
|
|
Packit |
13e616 |
then required state. However, we need to send update if
|
|
Packit |
13e616 |
no state change required.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (link_state != IB_LINK_NO_CHANGE &&
|
|
Packit |
13e616 |
link_state <= current_state)
|
|
Packit |
13e616 |
OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Physical port %u already %s. Skipping\n",
|
|
Packit |
13e616 |
p_physp->port_num,
|
|
Packit |
13e616 |
ib_get_port_state_str(current_state));
|
|
Packit |
13e616 |
else if (link_mgr_set_physp_pi(sm, p_physp, link_state))
|
|
Packit |
13e616 |
ret = -1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return ret;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
int osm_link_mgr_process(osm_sm_t * sm, IN const uint8_t link_state)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_qmap_t *p_node_guid_tbl;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
int ret = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node_guid_tbl = &sm->p_subn->node_guid_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl);
|
|
Packit |
13e616 |
p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl);
|
|
Packit |
13e616 |
p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item))
|
|
Packit |
13e616 |
if (link_mgr_process_node(sm, p_node, link_state))
|
|
Packit |
13e616 |
ret = -1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_PLOCK_RELEASE(sm->p_lock);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit |
13e616 |
return ret;
|
|
Packit |
13e616 |
}
|