unsigned long rx_ring_ref, unsigned int tx_evtchn,
                   unsigned int rx_evtchn);
 void xenvif_disconnect(struct xenvif *vif);
+void xenvif_free(struct xenvif *vif);
 
 int xenvif_xenbus_init(void);
 void xenvif_xenbus_fini(void);
 
        }
 
        netdev_dbg(dev, "Successfully created xenvif\n");
+
+       __module_get(THIS_MODULE);
+
        return vif;
 }
 
        if (vif->tx_irq)
                return 0;
 
-       __module_get(THIS_MODULE);
-
        err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
        if (err < 0)
                goto err;
 
 void xenvif_disconnect(struct xenvif *vif)
 {
-       /* Disconnect funtion might get called by generic framework
-        * even before vif connects, so we need to check if we really
-        * need to do a module_put.
-        */
-       int need_module_put = 0;
-
        if (netif_carrier_ok(vif->dev))
                xenvif_carrier_off(vif);
 
                        unbind_from_irqhandler(vif->tx_irq, vif);
                        unbind_from_irqhandler(vif->rx_irq, vif);
                }
-               /* vif->irq is valid, we had a module_get in
-                * xenvif_connect.
-                */
-               need_module_put = 1;
+               vif->tx_irq = 0;
        }
 
        if (vif->task)
                kthread_stop(vif->task);
 
+       xenvif_unmap_frontend_rings(vif);
+}
+
+void xenvif_free(struct xenvif *vif)
+{
        netif_napi_del(&vif->napi);
 
        unregister_netdev(vif->dev);
 
-       xenvif_unmap_frontend_rings(vif);
-
        free_netdev(vif->dev);
 
-       if (need_module_put)
-               module_put(THIS_MODULE);
+       module_put(THIS_MODULE);
 }
 
        if (be->vif) {
                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
                xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
-               xenvif_disconnect(be->vif);
+               xenvif_free(be->vif);
                be->vif = NULL;
        }
        kfree(be);
 {
        struct backend_info *be = dev_get_drvdata(&dev->dev);
 
+       if (be->vif)
+               xenvif_disconnect(be->vif);
+}
+
+static void destroy_backend(struct xenbus_device *dev)
+{
+       struct backend_info *be = dev_get_drvdata(&dev->dev);
+
        if (be->vif) {
+               kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
                xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
-               xenvif_disconnect(be->vif);
+               xenvif_free(be->vif);
                be->vif = NULL;
        }
 }
        case XenbusStateConnected:
                if (dev->state == XenbusStateConnected)
                        break;
-               backend_create_xenvif(be);
                if (be->vif)
                        connect(be);
                break;
 
        case XenbusStateClosing:
-               if (be->vif)
-                       kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
                disconnect_backend(dev);
                xenbus_switch_state(dev, XenbusStateClosing);
                break;
                xenbus_switch_state(dev, XenbusStateClosed);
                if (xenbus_dev_is_online(dev))
                        break;
+               destroy_backend(dev);
                /* fall through if not online */
        case XenbusStateUnknown:
                device_unregister(&dev->dev);