# HG changeset patch # User root@xxxxxxxxxxxxxxxxxxxxx # Node ID 22b408023c8e0cb882fcc9f52ebcd70f40330c46 # Parent 56ad5efabe2601bd72f9e2ea0d0a9606f50ac259 This patch reorganizes network frontend device unregister and removal, so that occur in the right order and succeed. On Closing state we: stop queue, unbind irq and finally unregister device On removal: end foreign access to TX and RX pages and free_netdev (doing the last stage of destroying an allocated device) Tested with save/restore. Working OK. Makes xm-test network "03_attach_detach_multiple_pos" pass. Signed-off-by: Murillo F. Bernardes diff -r 56ad5efabe26 -r 22b408023c8e linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Dec 27 00:16:54 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Dec 27 18:55:48 2005 @@ -1188,33 +1188,13 @@ DPRINTK("%s\n", dev->nodename); - netif_free(info); - kfree(info); + netif_disconnect_backend(info); + free_netdev(info->netdev); return 0; } - -static void netif_free(struct netfront_info *info) -{ - netif_disconnect_backend(info); - close_netdev(info); -} - - static void close_netdev(struct netfront_info *info) -{ - if (info->netdev) { -#ifdef CONFIG_PROC_FS - xennet_proc_delif(info->netdev); -#endif - unregister_netdev(info->netdev); - info->netdev = NULL; - } -} - - -static void netif_disconnect_backend(struct netfront_info *info) { /* Stop old i/f to prevent errors whilst we rebuild the state. */ spin_lock_irq(&info->tx_lock); @@ -1224,18 +1204,33 @@ spin_unlock(&info->rx_lock); spin_unlock_irq(&info->tx_lock); +#ifdef CONFIG_PROC_FS + xennet_proc_delif(info->netdev); +#endif + + if (info->irq) + unbind_from_irqhandler(info->irq, info->netdev); + info->evtchn = info->irq = 0; + + unregister_netdev(info->netdev); +} + +static void netif_disconnect_backend(struct netfront_info *info) +{ end_access(info->tx_ring_ref, info->tx.sring); end_access(info->rx_ring_ref, info->rx.sring); info->tx_ring_ref = GRANT_INVALID_REF; info->rx_ring_ref = GRANT_INVALID_REF; info->tx.sring = NULL; info->rx.sring = NULL; - - if (info->irq) - unbind_from_irqhandler(info->irq, info->netdev); - info->evtchn = info->irq = 0; -} - +} + +static void netif_free(struct netfront_info *info) +{ + close_netdev(info); + netif_disconnect_backend(info); + free_netdev(info->netdev); +} static void end_access(int ref, void *page) {