From 42cf4a720cb85f71d43739b304cc1f25353f68c4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 15 Sep 2010 23:10:15 +0100 Subject: [infiniband] Add node GUID as distinct from the first port GUID iPXE currently uses the first port's port GUID as the node GUID, rather than using the (possibly distinct) real node GUID. This can confuse opensm during the handover to a loaded OS: it thinks the port already belongs to a different node and so discards our port information with a warning message about duplicate ports. Everything is picked up correctly on the second subnet sweep, after opensm has established that the "old" node no longer exists, but this can delay link-up unnecessarily by several seconds. Fix by using the real node GUID. Signed-off-by: Michael Brown --- src/net/infiniband.c | 16 +++----- src/net/infiniband/ib_cm.c | 2 +- src/net/infiniband/ib_sma.c | 15 ++++---- src/net/infiniband/ib_smc.c | 92 +++++++++++++++++++++++++++++++++------------ 4 files changed, 81 insertions(+), 44 deletions(-) (limited to 'src/net') diff --git a/src/net/infiniband.c b/src/net/infiniband.c index d7cbf697a..72dd4855a 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -761,27 +761,21 @@ void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp, */ /** - * Get Infiniband HCA information + * Count Infiniband HCA ports * * @v ibdev Infiniband device - * @ret hca_guid HCA GUID * @ret num_ports Number of ports */ -int ib_get_hca_info ( struct ib_device *ibdev, union ib_guid *hca_guid ) { +int ib_count_ports ( struct ib_device *ibdev ) { struct ib_device *tmp; int num_ports = 0; /* Search for IB devices with the same physical device to - * identify port count and a suitable Node GUID. + * identify port count. */ for_each_ibdev ( tmp ) { - if ( tmp->dev != ibdev->dev ) - continue; - if ( num_ports == 0 ) { - memcpy ( hca_guid, &tmp->gid.s.guid, - sizeof ( *hca_guid ) ); - } - num_ports++; + if ( tmp->dev == ibdev->dev ) + num_ports++; } return num_ports; } diff --git a/src/net/infiniband/ib_cm.c b/src/net/infiniband/ib_cm.c index bbba5727e..1a0646beb 100644 --- a/src/net/infiniband/ib_cm.c +++ b/src/net/infiniband/ib_cm.c @@ -364,7 +364,7 @@ static void ib_cm_path_complete ( struct ib_device *ibdev, req->local_id = htonl ( conn->local_id ); memcpy ( &req->service_id, &conn->service_id, sizeof ( req->service_id ) ); - ib_get_hca_info ( ibdev, &req->local_ca ); + memcpy ( &req->local_ca, &ibdev->node_guid, sizeof ( req->local_ca ) ); req->local_qpn__responder_resources = htonl ( ( qp->qpn << 8 ) | 1 ); req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 ); req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl = diff --git a/src/net/infiniband/ib_sma.c b/src/net/infiniband/ib_sma.c index 45a1e4469..1f3c6d804 100644 --- a/src/net/infiniband/ib_sma.c +++ b/src/net/infiniband/ib_sma.c @@ -58,8 +58,10 @@ static void ib_sma_node_info ( struct ib_device *ibdev, node_info->base_version = IB_MGMT_BASE_VERSION; node_info->class_version = IB_SMP_CLASS_VERSION; node_info->node_type = IB_NODE_TYPE_HCA; - node_info->num_ports = ib_get_hca_info ( ibdev, &node_info->sys_guid ); - memcpy ( &node_info->node_guid, &node_info->sys_guid, + node_info->num_ports = ib_count_ports ( ibdev ); + memcpy ( &node_info->sys_guid, &ibdev->node_guid, + sizeof ( node_info->sys_guid ) ); + memcpy ( &node_info->node_guid, &ibdev->node_guid, sizeof ( node_info->node_guid ) ); memcpy ( &node_info->port_guid, &ibdev->gid.s.guid, sizeof ( node_info->port_guid ) ); @@ -88,22 +90,21 @@ static void ib_sma_node_desc ( struct ib_device *ibdev, union ib_mad *mad, struct ib_address_vector *av ) { struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc; - union ib_guid guid; + union ib_guid *guid = &ibdev->node_guid; char hostname[ sizeof ( node_desc->node_string ) ]; int hostname_len; int rc; /* Fill in information */ memset ( node_desc, 0, sizeof ( *node_desc ) ); - ib_get_hca_info ( ibdev, &guid ); hostname_len = fetch_string_setting ( NULL, &hostname_setting, hostname, sizeof ( hostname ) ); snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ), "iPXE %s%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)", hostname, ( ( hostname_len >= 0 ) ? " " : "" ), - guid.bytes[0], guid.bytes[1], guid.bytes[2], guid.bytes[3], - guid.bytes[4], guid.bytes[5], guid.bytes[6], guid.bytes[7], - ibdev->dev->name ); + guid->bytes[0], guid->bytes[1], guid->bytes[2], + guid->bytes[3], guid->bytes[4], guid->bytes[5], + guid->bytes[6], guid->bytes[7], ibdev->dev->name ); /* Send GetResponse */ mad->hdr.method = IB_MGMT_METHOD_GET_RESP; diff --git a/src/net/infiniband/ib_smc.c b/src/net/infiniband/ib_smc.c index 2e0535aba..8196cb7e3 100644 --- a/src/net/infiniband/ib_smc.c +++ b/src/net/infiniband/ib_smc.c @@ -35,16 +35,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** - * Get port information + * Issue local MAD * * @v ibdev Infiniband device + * @v attr_id Attribute ID, in network byte order + * @v attr_mod Attribute modifier, in network byte order * @v local_mad Method for issuing local MADs * @v mad Management datagram to fill in * @ret rc Return status code */ -static int ib_smc_get_port_info ( struct ib_device *ibdev, - ib_local_mad_t local_mad, - union ib_mad *mad ) { +static int ib_smc_mad ( struct ib_device *ibdev, uint16_t attr_id, + uint32_t attr_mod, ib_local_mad_t local_mad, + union ib_mad *mad ) { int rc; /* Construct MAD */ @@ -53,10 +55,55 @@ static int ib_smc_get_port_info ( struct ib_device *ibdev, mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; mad->hdr.class_version = 1; mad->hdr.method = IB_MGMT_METHOD_GET; - mad->hdr.attr_id = htons ( IB_SMP_ATTR_PORT_INFO ); - mad->hdr.attr_mod = htonl ( ibdev->port ); + mad->hdr.attr_id = attr_id; + mad->hdr.attr_mod = attr_mod; + + /* Issue MAD */ + if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Get node information + * + * @v ibdev Infiniband device + * @v local_mad Method for issuing local MADs + * @v mad Management datagram to fill in + * @ret rc Return status code + */ +static int ib_smc_get_node_info ( struct ib_device *ibdev, + ib_local_mad_t local_mad, + union ib_mad *mad ) { + int rc; + + /* Issue MAD */ + if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_NODE_INFO ), 0, + local_mad, mad ) ) != 0 ) { + DBGC ( ibdev, "IBDEV %p could not get node info: %s\n", + ibdev, strerror ( rc ) ); + return rc; + } + return 0; +} - if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) { +/** + * Get port information + * + * @v ibdev Infiniband device + * @v local_mad Method for issuing local MADs + * @v mad Management datagram to fill in + * @ret rc Return status code + */ +static int ib_smc_get_port_info ( struct ib_device *ibdev, + ib_local_mad_t local_mad, + union ib_mad *mad ) { + int rc; + + /* Issue MAD */ + if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PORT_INFO ), + htonl ( ibdev->port ), local_mad, mad )) !=0){ DBGC ( ibdev, "IBDEV %p could not get port info: %s\n", ibdev, strerror ( rc ) ); return rc; @@ -77,15 +124,9 @@ static int ib_smc_get_guid_info ( struct ib_device *ibdev, union ib_mad *mad ) { int rc; - /* Construct MAD */ - memset ( mad, 0, sizeof ( *mad ) ); - mad->hdr.base_version = IB_MGMT_BASE_VERSION; - mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - mad->hdr.class_version = 1; - mad->hdr.method = IB_MGMT_METHOD_GET; - mad->hdr.attr_id = htons ( IB_SMP_ATTR_GUID_INFO ); - - if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) { + /* Issue MAD */ + if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_GUID_INFO ), 0, + local_mad, mad ) ) != 0 ) { DBGC ( ibdev, "IBDEV %p could not get GUID info: %s\n", ibdev, strerror ( rc ) ); return rc; @@ -106,15 +147,9 @@ static int ib_smc_get_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) { int rc; - /* Construct MAD */ - memset ( mad, 0, sizeof ( *mad ) ); - mad->hdr.base_version = IB_MGMT_BASE_VERSION; - mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - mad->hdr.class_version = 1; - mad->hdr.method = IB_MGMT_METHOD_GET; - mad->hdr.attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ); - - if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) { + /* Issue MAD */ + if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PKEY_TABLE ), 0, + local_mad, mad ) ) != 0 ) { DBGC ( ibdev, "IBDEV %p could not get pkey table: %s\n", ibdev, strerror ( rc ) ); return rc; @@ -131,11 +166,18 @@ static int ib_smc_get_pkey_table ( struct ib_device *ibdev, */ static int ib_smc_get ( struct ib_device *ibdev, ib_local_mad_t local_mad ) { union ib_mad mad; + struct ib_node_info *node_info = &mad.smp.smp_data.node_info; struct ib_port_info *port_info = &mad.smp.smp_data.port_info; struct ib_guid_info *guid_info = &mad.smp.smp_data.guid_info; struct ib_pkey_table *pkey_table = &mad.smp.smp_data.pkey_table; int rc; + /* Node info gives us the node GUID */ + if ( ( rc = ib_smc_get_node_info ( ibdev, local_mad, &mad ) ) != 0 ) + return rc; + memcpy ( &ibdev->node_guid, &node_info->node_guid, + sizeof ( ibdev->node_guid ) ); + /* Port info gives us the link state, the first half of the * port GID and the SM LID. */ -- cgit v1.2.3-55-g7522