diff options
-rw-r--r-- | src/drivers/net/netvsc.c | 13 | ||||
-rw-r--r-- | src/include/ipxe/netdevice.h | 1 | ||||
-rw-r--r-- | src/net/netdev_settings.c | 7 | ||||
-rw-r--r-- | src/net/netdevice.c | 63 |
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; } /** |