aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hci/strerror.c1
-rw-r--r--src/include/gpxe/netdevice.h21
-rw-r--r--src/net/netdevice.c30
-rw-r--r--src/usr/ifmgmt.c4
4 files changed, 48 insertions, 8 deletions
diff --git a/src/hci/strerror.c b/src/hci/strerror.c
index 4b16608..216b1e5 100644
--- a/src/hci/strerror.c
+++ b/src/hci/strerror.c
@@ -115,6 +115,7 @@ struct errortab common_errors[] __errortab = {
{ ENOEXEC, "Not an executable image" },
{ ENOMEM, "Out of memory" },
{ ENOSPC, "No space left on device" },
+ { ENOTCONN, "Not connected" },
{ ENOTSUP, "Not supported" },
{ EPERM, "Operation not permitted" },
{ ERANGE, "Out of range" },
diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h
index 43c5aa3..70644af 100644
--- a/src/include/gpxe/netdevice.h
+++ b/src/include/gpxe/netdevice.h
@@ -267,6 +267,12 @@ struct net_device {
* This is the bitwise-OR of zero or more NETDEV_XXX constants.
*/
unsigned int state;
+ /** Link status code
+ *
+ * Zero indicates that the link is up; any other value
+ * indicates the error preventing link-up.
+ */
+ int link_rc;
/** Maximum packet length
*
* This length includes any link-layer headers.
@@ -291,9 +297,6 @@ struct net_device {
/** Network device is open */
#define NETDEV_OPEN 0x0001
-/** Network device has link */
-#define NETDEV_LINK_UP 0x0002
-
/** Link-layer protocol table */
#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
@@ -420,17 +423,18 @@ netdev_settings_init ( struct net_device *netdev ) {
*/
static inline __attribute__ (( always_inline )) void
netdev_link_up ( struct net_device *netdev ) {
- netdev->state |= NETDEV_LINK_UP;
+ netdev->link_rc = 0;
}
/**
- * Mark network device as having link down
+ * Mark network device as having link down due to a specific error
*
* @v netdev Network device
+ * @v rc Link status code
*/
static inline __attribute__ (( always_inline )) void
-netdev_link_down ( struct net_device *netdev ) {
- netdev->state &= ~NETDEV_LINK_UP;
+netdev_link_err ( struct net_device *netdev, int rc ) {
+ netdev->link_rc = rc;
}
/**
@@ -441,9 +445,10 @@ netdev_link_down ( struct net_device *netdev ) {
*/
static inline __attribute__ (( always_inline )) int
netdev_link_ok ( struct net_device *netdev ) {
- return ( netdev->state & NETDEV_LINK_UP );
+ return ( netdev->link_rc == 0 );
}
+extern void netdev_link_down ( struct net_device *netdev );
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
extern void netdev_tx_complete_err ( struct net_device *netdev,
struct io_buffer *iobuf, int rc );
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index c3551ea..e16ebaa 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <gpxe/process.h>
#include <gpxe/init.h>
#include <gpxe/device.h>
+#include <gpxe/errortab.h>
#include <gpxe/netdevice.h>
/** @file
@@ -44,6 +45,34 @@ struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
/** List of open network devices, in reverse order of opening */
struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
+/** Default link status code */
+#define EUNKNOWN_LINK_STATUS EINPROGRESS
+
+/** Human-readable message for the default link status */
+struct errortab netdev_errors[] __errortab = {
+ { EUNKNOWN_LINK_STATUS, "Unknown" },
+};
+
+/**
+ * Mark network device as having link down
+ *
+ * @v netdev Network device
+ */
+void netdev_link_down ( struct net_device *netdev ) {
+
+ switch ( netdev->link_rc ) {
+ case 0:
+ case -EUNKNOWN_LINK_STATUS:
+ netdev->link_rc = -ENOTCONN;
+ break;
+ default:
+ /* Avoid clobbering a more detailed link status code,
+ * if one is already set.
+ */
+ break;
+ }
+}
+
/**
* Record network device statistic
*
@@ -302,6 +331,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) {
netdev = zalloc ( total_len );
if ( netdev ) {
netdev->refcnt.free = free_netdev;
+ netdev->link_rc = -EUNKNOWN_LINK_STATUS;
INIT_LIST_HEAD ( &netdev->tx_queue );
INIT_LIST_HEAD ( &netdev->rx_queue );
netdev_settings_init ( netdev );
diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c
index 9c82503..2c4b3d2 100644
--- a/src/usr/ifmgmt.c
+++ b/src/usr/ifmgmt.c
@@ -94,6 +94,10 @@ void ifstat ( struct net_device *netdev ) {
( netdev_link_ok ( netdev ) ? "up" : "down" ),
netdev->tx_stats.good, netdev->tx_stats.bad,
netdev->rx_stats.good, netdev->rx_stats.bad );
+ if ( ! netdev_link_ok ( netdev ) ) {
+ printf ( " [Link status: %s]\n",
+ strerror ( netdev->link_rc ) );
+ }
ifstat_errors ( &netdev->tx_stats, "TXE" );
ifstat_errors ( &netdev->rx_stats, "RXE" );
}