aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/net/netvsc.c13
-rw-r--r--src/include/ipxe/netdevice.h1
-rw-r--r--src/net/netdev_settings.c7
-rw-r--r--src/net/netdevice.c63
4 files changed, 66 insertions, 18 deletions
diff --git a/src/drivers/net/netvsc.c b/src/drivers/net/netvsc.c
index 5be52fb..f753868 100644
--- a/src/drivers/net/netvsc.c
+++ b/src/drivers/net/netvsc.c
@@ -852,16 +852,9 @@ static int netvsc_reset ( struct vmbus_device *vmdev ) {
struct net_device *netdev = rndis->netdev;
int rc;
- /* A closed device holds no NetVSC (or RNDIS) state, so there
- * is nothing to reset.
- */
- if ( ! netdev_is_open ( netdev ) )
- return 0;
-
- /* Close and reopen device to reset any stale state */
- netdev_close ( netdev );
- if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
- DBGC ( netvsc, "NETVSC %s could not reopen: %s\n",
+ /* Reset network device */
+ if ( ( rc = netdev_reset ( netdev ) ) != 0 ) {
+ DBGC ( netvsc, "NETVSC %s could not reset: %s\n",
netvsc->name, strerror ( rc ) );
return rc;
}
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
index af932c2..0c6fe9c 100644
--- a/src/include/ipxe/netdevice.h
+++ b/src/include/ipxe/netdevice.h
@@ -723,6 +723,7 @@ extern struct net_device * alloc_netdev ( size_t priv_size );
extern int register_netdev ( struct net_device *netdev );
extern int netdev_open ( struct net_device *netdev );
extern void netdev_close ( struct net_device *netdev );
+extern int netdev_reset ( struct net_device *netdev );
extern void unregister_netdev ( struct net_device *netdev );
extern void netdev_irq ( struct net_device *netdev, int enable );
extern struct net_device * find_netdev ( const char *name );
diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c
index fb98663..2c08a6a 100644
--- a/src/net/netdev_settings.c
+++ b/src/net/netdev_settings.c
@@ -453,11 +453,10 @@ static int apply_netdev_settings ( void ) {
netdev->name, mtu );
}
- /* Close and reopen network device if MTU has increased */
+ /* Reset network device if MTU has increased */
if ( netdev_is_open ( netdev ) && ( mtu > old_mtu ) ) {
- netdev_close ( netdev );
- if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
- DBGC ( netdev, "NETDEV %s could not reopen: "
+ if ( ( rc = netdev_reset ( netdev ) ) != 0 ) {
+ DBGC ( netdev, "NETDEV %s could not reset: "
"%s\n", netdev->name, strerror ( rc ) );
return rc;
}
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 07961bf..db33794 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -613,6 +613,23 @@ static void netdev_rx_flush ( struct net_device *netdev ) {
}
/**
+ * Flush device's transmit and receive queues
+ *
+ * @v netdev Network device
+ */
+static void netdev_flush ( struct net_device *netdev ) {
+
+ /* Sanity check */
+ assert ( ! ( netdev->state & NETDEV_OPEN ) );
+
+ /* Flush TX queue */
+ netdev_tx_flush ( netdev );
+
+ /* Flush RX queue */
+ netdev_rx_flush ( netdev );
+}
+
+/**
* Finish network device configuration
*
* @v config Network device configuration
@@ -657,8 +674,7 @@ static void free_netdev ( struct refcnt *refcnt ) {
container_of ( refcnt, struct net_device, refcnt );
stop_timer ( &netdev->link_block );
- netdev_tx_flush ( netdev );
- netdev_rx_flush ( netdev );
+ netdev_flush ( netdev );
clear_settings ( netdev_settings ( netdev ) );
free ( netdev );
}
@@ -880,8 +896,47 @@ void netdev_close ( struct net_device *netdev ) {
netdev->op->close ( netdev );
/* Flush TX and RX queues */
- netdev_tx_flush ( netdev );
- netdev_rx_flush ( netdev );
+ netdev_flush ( netdev );
+}
+
+/**
+ * Reset transmit and receive queues
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+int netdev_reset ( struct net_device *netdev ) {
+ int rc;
+
+ /* Do nothing unless device is open */
+ if ( ! ( netdev->state & NETDEV_OPEN ) )
+ return 0;
+
+ DBGC ( netdev, "NETDEV %s resetting\n", netdev->name );
+
+ /* Mark as closed */
+ netdev->state &= ~NETDEV_OPEN;
+
+ /* Close the device */
+ netdev->op->close ( netdev );
+
+ /* Flush TX and RX queues */
+ netdev_flush ( netdev );
+
+ /* Mark as opened */
+ netdev->state |= NETDEV_OPEN;
+
+ /* Reopen device */
+ if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ netdev->state &= ~NETDEV_OPEN;
+ list_del ( &netdev->open_list );
+ netdev_notify ( netdev );
+ return rc;
}
/**