From bbc530c0dde2385d85631cdc9ac82ebd0bdea763 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 14 Nov 2009 03:40:29 +0000 Subject: [PATCH] [infiniband] Report IB link status as IPoIB netdevice status --- src/drivers/net/ipoib.c | 17 ++++++++++++----- src/include/gpxe/infiniband.h | 1 + src/net/infiniband.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 260d2d0ee..06e6a2cfe 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -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; } } diff --git a/src/include/gpxe/infiniband.h b/src/include/gpxe/infiniband.h index 69bc69b5d..fd2a433d6 100644 --- a/src/include/gpxe/infiniband.h +++ b/src/include/gpxe/infiniband.h @@ -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, diff --git a/src/net/infiniband.c b/src/net/infiniband.c index cd7deae25..0025e5c46 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -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; }