]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[infiniband] Add node GUID as distinct from the first port GUID
authorMichael Brown <mcb30@ipxe.org>
Wed, 15 Sep 2010 22:10:15 +0000 (23:10 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 16 Sep 2010 02:30:45 +0000 (03:30 +0100)
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 <mcb30@ipxe.org>
src/drivers/infiniband/linda.c
src/drivers/infiniband/qib7322.c
src/include/ipxe/infiniband.h
src/net/infiniband.c
src/net/infiniband/ib_cm.c
src/net/infiniband/ib_sma.c
src/net/infiniband/ib_smc.c

index 12a09a04710d19d4146ce7d45d1c707127d954e4..f3987d6ee74a1c1736b459f582addf93edbe7cbe 100644 (file)
@@ -2364,8 +2364,10 @@ static int linda_probe ( struct pci_device *pci,
                goto err_init_i2c;
 
        /* Read EEPROM parameters */
-       if ( ( rc = linda_read_eeprom ( linda, &ibdev->gid.s.guid ) ) != 0 )
+       if ( ( rc = linda_read_eeprom ( linda, &ibdev->node_guid ) ) != 0 )
                goto err_read_eeprom;
+       memcpy ( &ibdev->gid.s.guid, &ibdev->node_guid,
+                sizeof ( ibdev->gid.s.guid ) );
 
        /* Initialise send datapath */
        if ( ( rc = linda_init_send ( linda ) ) != 0 )
index b1902cfa98249231da54b1cc434ec7f82496d04b..e8c63a1f432f896418339ca7b54d0399ff50d2ea 100644 (file)
@@ -2357,6 +2357,8 @@ static int qib7322_probe ( struct pci_device *pci,
                        IB_LINK_WIDTH_4X; /* 1x does not work */
                ibdev->link_speed_enabled = ibdev->link_speed_supported =
                        IB_LINK_SPEED_SDR; /* to avoid need for link tuning */
+               memcpy ( &ibdev->node_guid, &qib7322->guid,
+                        sizeof ( ibdev->node_guid ) );
                memcpy ( &ibdev->gid.s.guid, &qib7322->guid,
                         sizeof ( ibdev->gid.s.guid ) );
                assert ( ( ibdev->gid.s.guid.bytes[7] & i ) == 0 );
index aa67dd4aba2904daf2aece94527fc1f3f04d60e5..fc04dc873869a1ba6c9d49929ede34690d67e864 100644 (file)
@@ -404,7 +404,9 @@ struct ib_device {
        uint8_t link_speed_enabled;
        /** Link speed active */
        uint8_t link_speed_active;
-       /** Port GID */
+       /** Node GUID */
+       union ib_guid node_guid;
+       /** Port GID (comprising GID prefix and port GUID) */
        union ib_gid gid;
        /** Port LID */
        uint16_t lid;
@@ -503,8 +505,7 @@ extern int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
                             union ib_gid *gid );
 extern void ib_mcast_detach ( struct ib_device *ibdev,
                              struct ib_queue_pair *qp, union ib_gid *gid );
-extern int ib_get_hca_info ( struct ib_device *ibdev,
-                            union ib_guid *hca_guid );
+extern int ib_count_ports ( struct ib_device *ibdev );
 extern int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad );
 extern int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad );
 extern struct ib_device * alloc_ibdev ( size_t priv_size );
index d7cbf697ad1205ba2f7dec3bab34dc8c37e7b119..72dd4855ad6715dd95a734cf676ab36b36399e57 100644 (file)
@@ -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;
 }
index bbba5727e3484deb6dd43ad0656fef009dc9ee0b..1a0646beba2fa03321bf4e9eba99c7d9e88c5aab 100644 (file)
@@ -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 =
index 45a1e44698b6100b1b5b8283f610c5de5ece22f6..1f3c6d8041d4de979deadb24bd31316694ab93bc 100644 (file)
@@ -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;
index 2e0535abafcd57535cc41fe25ab498d89ed0071c..8196cb7e39c3f82aba86596f54b81ba42005ee80 100644 (file)
@@ -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.
         */