diff options
-rw-r--r-- | src/arch/i386/drivers/net/undinet.c | 3 | ||||
-rw-r--r-- | src/drivers/net/e1000/e1000.c | 3 | ||||
-rw-r--r-- | src/drivers/net/ipoib.c | 20 | ||||
-rw-r--r-- | src/drivers/net/legacy.c | 3 | ||||
-rwxr-xr-x | src/drivers/net/mtnic.c | 3 | ||||
-rw-r--r-- | src/drivers/net/natsemi.c | 3 | ||||
-rw-r--r-- | src/drivers/net/pnic.c | 3 | ||||
-rw-r--r-- | src/drivers/net/rtl8139.c | 3 | ||||
-rw-r--r-- | src/include/gpxe/errfile.h | 1 | ||||
-rw-r--r-- | src/include/gpxe/netdevice.h | 34 | ||||
-rw-r--r-- | src/include/usr/ifmgmt.h | 1 | ||||
-rw-r--r-- | src/usr/autoboot.c | 11 | ||||
-rw-r--r-- | src/usr/ifmgmt.c | 24 |
13 files changed, 110 insertions, 2 deletions
diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index 07bec56..512c60e 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -708,6 +708,9 @@ int undinet_probe ( struct undi_device *undi ) { undinic->hacks |= UNDI_HACK_EB54; } + /* Mark as link up; we don't handle link state */ + netdev_link_up ( netdev ); + /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err_register; diff --git a/src/drivers/net/e1000/e1000.c b/src/drivers/net/e1000/e1000.c index 739217c..a9aa508 100644 --- a/src/drivers/net/e1000/e1000.c +++ b/src/drivers/net/e1000/e1000.c @@ -876,6 +876,9 @@ e1000_probe ( struct pci_device *pdev, e1000_get_hw_control ( adapter ); + /* Mark as link up; we don't yet handle link state */ + netdev_link_up ( netdev ); + if ( ( err = register_netdev ( netdev ) ) != 0) goto err_register; diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 3b915bf..e3baa14 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -471,6 +471,12 @@ static int ipoib_transmit ( struct net_device *netdev, } iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) ); + /* Attempting transmission while link is down will put the + * queue pair into an error state, so don't try it. + */ + if ( ! ibdev->link_up ) + return -ENETUNREACH; + /* Construct address vector */ memset ( &av, 0, sizeof ( av ) ); av.qkey = IB_GLOBAL_QKEY; @@ -790,6 +796,10 @@ static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) { return rc; } + /* We will set link up on the network device when we receive + * the broadcast join response. + */ + return 0; } @@ -907,16 +917,24 @@ static struct net_device_operations ipoib_operations = { */ static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) { struct ib_device *ibdev = ipoib->ibdev; + struct net_device *netdev = ipoib->netdev; struct ipoib_mac *mac; /* Calculate GID portion of MAC address based on port GID */ - mac = ( ( struct ipoib_mac * ) ipoib->netdev->ll_addr ); + mac = ( ( struct ipoib_mac * ) netdev->ll_addr ); memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) ); /* Calculate broadcast GID based on partition key */ memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid, sizeof ( ipoib->broadcast_gid ) ); ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey ); + + /* Set net device link state to reflect Infiniband link state */ + if ( ibdev->link_up ) { + netdev_link_up ( netdev ); + } else { + netdev_link_down ( netdev ); + } } /** diff --git a/src/drivers/net/legacy.c b/src/drivers/net/legacy.c index 32460ad..cbec3cf 100644 --- a/src/drivers/net/legacy.c +++ b/src/drivers/net/legacy.c @@ -112,6 +112,9 @@ int legacy_probe ( void *hwdev, */ dev->desc.irq = nic.irqno; + /* Mark as link up; legacy devices don't handle link state */ + netdev_link_up ( netdev ); + if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err_register; diff --git a/src/drivers/net/mtnic.c b/src/drivers/net/mtnic.c index 536fcb8..5750706 100755 --- a/src/drivers/net/mtnic.c +++ b/src/drivers/net/mtnic.c @@ -1731,6 +1731,9 @@ mtnic_probe(struct pci_device *pci, mac = mac >> 8; } + /* Mark as link up; we don't yet handle link state */ + netdev_link_up ( dev ); + if (register_netdev(dev)) { eprintf("Netdev registration failed\n"); return MTNIC_ERROR; diff --git a/src/drivers/net/natsemi.c b/src/drivers/net/natsemi.c index 98a5ff8..028b905 100644 --- a/src/drivers/net/natsemi.c +++ b/src/drivers/net/natsemi.c @@ -205,6 +205,9 @@ static int natsemi_probe (struct pci_device *pci, last = last1; } + /* Mark as link up; we don't yet handle link state */ + netdev_link_up ( netdev ); + if ((rc = register_netdev (netdev)) != 0) goto err_register_netdev; diff --git a/src/drivers/net/pnic.c b/src/drivers/net/pnic.c index b431ec5..c7f0867 100644 --- a/src/drivers/net/pnic.c +++ b/src/drivers/net/pnic.c @@ -250,6 +250,9 @@ static int pnic_probe ( struct pci_device *pci, status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0, netdev->ll_addr, ETH_ALEN, NULL ); + /* Mark as link up; PNIC has no concept of link state */ + netdev_link_up ( netdev ); + /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err; diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c index c432884..509047a 100644 --- a/src/drivers/net/rtl8139.c +++ b/src/drivers/net/rtl8139.c @@ -518,6 +518,9 @@ static int rtl_probe ( struct pci_device *pci, rtl_reset ( netdev ); rtl_init_eeprom ( netdev ); nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN ); + + /* Mark as link up; we don't yet handle link state */ + netdev_link_up ( netdev ); /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h index ae8b148..011ff1f 100644 --- a/src/include/gpxe/errfile.h +++ b/src/include/gpxe/errfile.h @@ -151,6 +151,7 @@ #define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 ) #define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 ) #define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 ) +#define ERRFILE_ifmgmt ( ERRFILE_OTHER | 0x000e0000 ) /** @} */ diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h index d8cb84d..1ef648e 100644 --- a/src/include/gpxe/netdevice.h +++ b/src/include/gpxe/netdevice.h @@ -254,6 +254,9 @@ struct net_device { /** Network device is open */ #define NETDEV_OPEN 0x0001 +/** Network device has link */ +#define NETDEV_LINK_UP 0x0002 + /** Declare a link-layer protocol */ #define __ll_protocol __table ( struct ll_protocol, ll_protocols, 01 ) @@ -352,6 +355,37 @@ netdev_settings ( struct net_device *netdev ) { return &netdev->settings.settings; } +/** + * Mark network device as having link up + * + * @v netdev Network device + */ +static inline __attribute__ (( always_inline )) void +netdev_link_up ( struct net_device *netdev ) { + netdev->state |= NETDEV_LINK_UP; +} + +/** + * Mark network device as having link down + * + * @v netdev Network device + */ +static inline __attribute__ (( always_inline )) void +netdev_link_down ( struct net_device *netdev ) { + netdev->state &= ~NETDEV_LINK_UP; +} + +/** + * Check link state of network device + * + * @v netdev Network device + * @ret link_up Link is up + */ +static inline __attribute__ (( always_inline )) int +netdev_link_ok ( struct net_device *netdev ) { + return ( netdev->state & NETDEV_LINK_UP ); +} + 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/include/usr/ifmgmt.h b/src/include/usr/ifmgmt.h index c7d35da..7b49d34 100644 --- a/src/include/usr/ifmgmt.h +++ b/src/include/usr/ifmgmt.h @@ -12,5 +12,6 @@ struct net_device; extern int ifopen ( struct net_device *netdev ); extern void ifclose ( struct net_device *netdev ); extern void ifstat ( struct net_device *netdev ); +extern int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ); #endif /* _USR_IFMGMT_H */ diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index c1a61ec..cff6e95 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -38,6 +38,9 @@ * */ +/** Time to wait for link-up */ +#define LINK_WAIT_MS 15000 + /** * Identify the boot network device * @@ -136,6 +139,14 @@ static int netboot ( struct net_device *netdev ) { return rc; ifstat ( netdev ); + /* Wait for link-up */ + printf ( "Waiting for link-up on %s...", netdev->name ); + if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 ) { + printf ( " no link detected\n" ); + return rc; + } + printf ( " ok\n" ); + /* Configure device via DHCP */ if ( ( rc = dhcp ( netdev ) ) != 0 ) return rc; diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c index 5f4323d..9c88ab5 100644 --- a/src/usr/ifmgmt.c +++ b/src/usr/ifmgmt.c @@ -18,8 +18,11 @@ #include <string.h> #include <stdio.h> +#include <unistd.h> +#include <errno.h> #include <gpxe/netdevice.h> #include <gpxe/device.h> +#include <gpxe/process.h> #include <usr/ifmgmt.h> /** @file @@ -61,9 +64,28 @@ void ifclose ( struct net_device *netdev ) { * @v netdev Network device */ void ifstat ( struct net_device *netdev ) { - printf ( "%s: %s on %s (%s) TX:%d TXE:%d RX:%d RXE:%d\n", + printf ( "%s: %s on %s (%s)\n" + " [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n", netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name, ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ), + ( netdev_link_ok ( netdev ) ? "up" : "down" ), netdev->stats.tx_ok, netdev->stats.tx_err, netdev->stats.rx_ok, netdev->stats.rx_err ); } + +/** + * Wait for link-up + * + * @v netdev Network device + * @v max_wait_ms Maximum time to wait, in ms + */ +int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) { + while ( 1 ) { + if ( netdev_link_ok ( netdev ) ) + return 0; + if ( max_wait_ms-- == 0 ) + return -ETIMEDOUT; + step(); + mdelay ( 1 ); + } +} |