[infiniband] Report IB link status as IPoIB netdevice status
authorMichael Brown <mcb30@etherboot.org>
Sat, 14 Nov 2009 03:40:29 +0000 (03:40 +0000)
committerMichael Brown <mcb30@etherboot.org>
Mon, 16 Nov 2009 22:14:12 +0000 (22:14 +0000)
src/drivers/net/ipoib.c
src/include/gpxe/infiniband.h
src/net/infiniband.c

index 260d2d0..06e6a2c 100644 (file)
@@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <string.h>
 #include <byteswap.h>
 #include <errno.h>
+#include <gpxe/errortab.h>
 #include <gpxe/if_arp.h>
 #include <gpxe/iobuf.h>
 #include <gpxe/netdevice.h>
@@ -75,6 +76,14 @@ static struct ipoib_mac ipoib_broadcast = {
                          0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
 };
 
+/** Link status for "broadcast join in progress" */
+#define EINPROGRESS_JOINING ( EINPROGRESS | EUNIQ_01 )
+
+/** Human-readable message for the link status */
+struct errortab ipoib_errors[] __errortab = {
+       { EINPROGRESS_JOINING, "Joining" },
+};
+
 /****************************************************************************
  *
  * IPoIB peer cache
@@ -702,17 +711,15 @@ void ipoib_link_state_changed ( struct ib_device *ibdev ) {
        ipoib->broadcast.gid.u.words[2] = htons ( ibdev->pkey );
 
        /* Set net device link state to reflect Infiniband link state */
-       if ( ib_link_ok ( ibdev ) ) {
-               netdev_link_up ( netdev );
-       } else {
-               netdev_link_down ( netdev );
-       }
+       rc = ib_link_rc ( ibdev );
+       netdev_link_err ( netdev, ( rc ? rc : -EINPROGRESS_JOINING ) );
 
        /* Join new broadcast group */
        if ( ib_link_ok ( ibdev ) &&
             ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) ) {
                DBGC ( ipoib, "IPoIB %p could not rejoin broadcast group: "
                       "%s\n", ipoib, strerror ( rc ) );
+               netdev_link_err ( netdev, rc );
                return;
        }
 }
index 69bc69b..fd2a433 100644 (file)
@@ -463,6 +463,7 @@ extern void ib_refill_recv ( struct ib_device *ibdev,
                             struct ib_queue_pair *qp );
 extern int ib_open ( struct ib_device *ibdev );
 extern void ib_close ( struct ib_device *ibdev );
+extern int ib_link_rc ( struct ib_device *ibdev );
 extern int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
                             struct ib_gid *gid );
 extern void ib_mcast_detach ( struct ib_device *ibdev,
index cd7deae..0025e5c 100644 (file)
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <errno.h>
 #include <assert.h>
 #include <gpxe/list.h>
+#include <gpxe/errortab.h>
 #include <gpxe/if_arp.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/iobuf.h>
@@ -48,6 +49,16 @@ struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
 /** List of open Infiniband devices, in reverse order of opening */
 static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
 
+/* Disambiguate the various possible EINPROGRESSes */
+#define EINPROGRESS_INIT ( EINPROGRESS | EUNIQ_01 )
+#define EINPROGRESS_ARMED ( EINPROGRESS | EUNIQ_02 )
+
+/** Human-readable message for the link statuses */
+struct errortab infiniband_errors[] __errortab = {
+       { EINPROGRESS_INIT, "Initialising" },
+       { EINPROGRESS_ARMED, "Armed" },
+};
+
 /***************************************************************************
  *
  * Completion queues
@@ -607,6 +618,22 @@ void ib_close ( struct ib_device *ibdev ) {
        }
 }
 
+/**
+ * Get link state
+ *
+ * @v ibdev            Infiniband device
+ * @ret rc             Link status code
+ */
+int ib_link_rc ( struct ib_device *ibdev ) {
+       switch ( ibdev->port_state ) {
+       case IB_PORT_STATE_DOWN:        return -ENOTCONN;
+       case IB_PORT_STATE_INIT:        return -EINPROGRESS_INIT;
+       case IB_PORT_STATE_ARMED:       return -EINPROGRESS_ARMED;
+       case IB_PORT_STATE_ACTIVE:      return 0;
+       default:                        return -EINVAL;
+       }
+}
+
 /***************************************************************************
  *
  * Multicast
@@ -838,6 +865,7 @@ struct ib_device * alloc_ibdev ( size_t priv_size ) {
                ib_set_drvdata ( ibdev, drv_priv );
                INIT_LIST_HEAD ( &ibdev->cqs );
                INIT_LIST_HEAD ( &ibdev->qps );
+               ibdev->port_state = IB_PORT_STATE_DOWN;
                ibdev->lid = IB_LID_NONE;
                ibdev->pkey = IB_PKEY_NONE;
        }