static int blkback_remove(struct xenbus_device *dev) { struct backend_info *be = dev->data; DPRINTK(""); if (be->backend_watch.node) { unregister_xenbus_watch(&be->backend_watch); kfree(be->backend_watch.node); be->backend_watch.node = NULL; } if (be->blkif) { if (be->blkif->xenblkd) kthread_stop(be->blkif->xenblkd); blkif_free(be->blkif); be->blkif = NULL; } device_remove_file(&dev->dev, &dev_attr_physical_device); device_remove_file(&dev->dev, &dev_attr_mode); kfree(be); dev->data = NULL; return 0; }
static int xen_blkbk_remove(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); DPRINTK(""); if (be->major || be->minor) xenvbd_sysfs_delif(dev); if (be->backend_watch.node) { unregister_xenbus_watch(&be->backend_watch); kfree(be->backend_watch.node); be->backend_watch.node = NULL; } if (be->blkif) { xen_blkif_disconnect(be->blkif); xen_vbd_free(&be->blkif->vbd); xen_blkif_free(be->blkif); be->blkif = NULL; } kfree(be->mode); kfree(be); dev_set_drvdata(&dev->dev, NULL); return 0; }
static void free_otherend_watch(struct xenbus_device *dev) { if (dev->otherend_watch.node) { unregister_xenbus_watch(&dev->otherend_watch); kfree(dev->otherend_watch.node); dev->otherend_watch.node = NULL; } }
static void unregister_hotplug_status_watch(struct backend_info *be) { if (be->have_hotplug_status_watch) { unregister_xenbus_watch(&be->hotplug_status_watch); kfree(be->hotplug_status_watch.node); } be->have_hotplug_status_watch = 0; }
static void xen_unregister_mcast_ctrl_watch(struct xenvif *vif) { if (vif->mcast_ctrl_watch.node) { unregister_xenbus_watch(&vif->mcast_ctrl_watch); kfree(vif->mcast_ctrl_watch.node); vif->mcast_ctrl_watch.node = NULL; } }
static void xen_unregister_credit_watch(struct xenvif *vif) { if (vif->credit_watch.node) { unregister_xenbus_watch(&vif->credit_watch); kfree(vif->credit_watch.node); vif->credit_watch.node = NULL; } }
static void free_otherend_watch(struct xenbus_device *dev) { if (dev->otherend_watch.node) { unregister_xenbus_watch(&dev->otherend_watch); kmem_free((void *)dev->otherend_watch.node, strlen(dev->otherend_watch.node) + 1); dev->otherend_watch.node = NULL; } }
/* Asynch callback to check for /local/domain/<DOMID>/name */ static void check_dom(struct xs_handle *h, struct xenbus_watch *w, const char *bepath_im) { char *domid; domid = get_dom_domid(h); if (domid == NULL) return; add_blockdevice_probe_watch(h, domid); free(domid); unregister_xenbus_watch(h, w); }
static void free_pdev(struct xen_pcibk_device *pdev) { if (pdev->be_watching) { unregister_xenbus_watch(&pdev->be_watch); pdev->be_watching = 0; } xen_pcibk_disconnect(pdev); xen_pcibk_release_devices(pdev); dev_set_drvdata(&pdev->xdev->dev, NULL); pdev->xdev = NULL; kfree(pdev); }
static int netback_remove(struct xenbus_device *dev) { struct backend_info *be = dev->data; if (be->backend_watch.node) { unregister_xenbus_watch(&be->backend_watch); kfree(be->backend_watch.node); be->backend_watch.node = NULL; } if (be->netif) { netif_disconnect(be->netif); be->netif = NULL; } kfree(be); dev->data = NULL; return 0; }
static void free_pdev(struct xen_pcibk_device *pdev) { if (pdev->be_watching) { unregister_xenbus_watch(&pdev->be_watch); pdev->be_watching = 0; } xen_pcibk_disconnect(pdev); /* N.B. This calls pcistub_put_pci_dev which does the FLR on all * of the PCIe devices. */ xen_pcibk_release_devices(pdev); dev_set_drvdata(&pdev->xdev->dev, NULL); pdev->xdev = NULL; kfree(pdev); }
static int tpmback_remove(struct xenbus_device *dev) { struct backend_info *be = dev->data; if (!be) return 0; if (be->backend_watch.node) { unregister_xenbus_watch(&be->backend_watch); kfree(be->backend_watch.node); be->backend_watch.node = NULL; } if (be->tpmif) { vtpm_release_packets(be->tpmif, 0); tpmif_put(be->tpmif); be->tpmif = NULL; } kfree(be); dev->data = NULL; return 0; }
/* * Reset frontend if it is in Connected or Closed state. * Wait for backend to catch up. * State Connected happens during kdump, Closed after kexec. */ static void xenbus_reset_frontend(char *fe, char *be, int be_state) { struct xenbus_watch be_watch; printk(KERN_DEBUG "XENBUS: backend %s %s\n", be, xenbus_strstate(be_state)); memset(&be_watch, 0, sizeof(be_watch)); be_watch.node = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/state", be); if (!be_watch.node) return; be_watch.callback = xenbus_reset_backend_state_changed; backend_state = XenbusStateUnknown; printk(KERN_INFO "XENBUS: triggering reconnect on %s\n", be); register_xenbus_watch(&be_watch); /* fall through to forward backend to state XenbusStateInitialising */ switch (be_state) { case XenbusStateConnected: xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosing); xenbus_reset_wait_for_backend(be, XenbusStateClosing); case XenbusStateClosing: xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosed); xenbus_reset_wait_for_backend(be, XenbusStateClosed); case XenbusStateClosed: xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateInitialising); xenbus_reset_wait_for_backend(be, XenbusStateInitWait); } unregister_xenbus_watch(&be_watch); printk(KERN_INFO "XENBUS: reconnect done on %s\n", be); kfree(be_watch.node); }
int netback_accel_remove(struct xenbus_device *dev) { struct backend_info *binfo; struct netback_accel *bend; int frontend_state; binfo = (struct backend_info *) dev->dev.driver_data; bend = (struct netback_accel *) binfo->netback_accel_priv; DPRINTK("%s: dev %p bend %p\n", __FUNCTION__, dev, bend); BUG_ON(bend == NULL); mutex_lock(&bend_list_mutex); unlink_bend(bend); mutex_unlock(&bend_list_mutex); mutex_lock(&bend->bend_mutex); /* Reject any requests to connect. */ bend->removing = 1; /* * Switch to closing to tell the other end that we're going * away. */ if (bend->backend_state != XenbusStateClosing) { bend->backend_state = XenbusStateClosing; net_accel_update_state(dev, XenbusStateClosing); } frontend_state = (int)XenbusStateUnknown; xenbus_scanf(XBT_NIL, dev->otherend, "accelstate", "%d", &frontend_state); mutex_unlock(&bend->bend_mutex); /* * Wait until this end goes to the closed state. This happens * in response to the other end going to the closed state. * Don't bother doing this if the other end is already closed * because if it is then there is nothing to do. */ if (frontend_state != (int)XenbusStateClosed && frontend_state != (int)XenbusStateUnknown) wait_event(bend->state_wait_queue, bend->backend_state == XenbusStateClosed); unregister_xenbus_watch(&bend->domu_accel_watch); kfree(bend->domu_accel_watch.node); unregister_xenbus_watch(&bend->config_accel_watch); kfree(bend->config_accel_watch.node); /* * Flush the scheduled work queue before freeing bend to get * rid of any pending netback_accel_msg_rx_handler() */ flush_scheduled_work(); mutex_lock(&bend->bend_mutex); /* Tear down the vnic if it was set up. */ if (bend->vnic_is_setup) { bend->vnic_is_setup = 0; cleanup_vnic(bend); } bend->backend_state = XenbusStateUnknown; net_accel_update_state(dev, XenbusStateUnknown); netback_accel_debugfs_remove(bend); unpublish_frontend_name(dev); kfree(bend->nicname); binfo->netback_accel_priv = NULL; mutex_unlock(&bend->bend_mutex); kfree(bend); return 0; }
int netback_accel_probe(struct xenbus_device *dev) { struct netback_accel *bend; struct backend_info *binfo; int err; DPRINTK("%s: passed device %s\n", __FUNCTION__, dev->nodename); /* Allocate structure to store all our state... */ bend = kzalloc(sizeof(struct netback_accel), GFP_KERNEL); if (bend == NULL) { DPRINTK("%s: no memory for bend\n", __FUNCTION__); return -ENOMEM; } mutex_init(&bend->bend_mutex); mutex_lock(&bend->bend_mutex); /* ...and store it where we can get at it */ binfo = (struct backend_info *) dev->dev.driver_data; binfo->netback_accel_priv = bend; /* And vice-versa */ bend->hdev_data = dev; DPRINTK("%s: Adding bend %p to list\n", __FUNCTION__, bend); init_waitqueue_head(&bend->state_wait_queue); bend->vnic_is_setup = 0; bend->frontend_state = XenbusStateUnknown; bend->backend_state = XenbusStateClosed; bend->removing = 0; sscanf(dev->nodename, NODENAME_PATH_FMT, &bend->far_end, &bend->vif_num); err = read_nicname(dev, bend); if (err) { /* * Technically not an error, just means we're not * supposed to accelerate this */ DPRINTK("failed to get device name\n"); goto fail_nicname; } /* * Look up the device name in the list of NICs provided by * driverlink to get the hardware type. */ err = netback_accel_sf_hwtype(bend); if (err) { /* * Technically not an error, just means we're not * supposed to accelerate this, probably belongs to * some other backend */ DPRINTK("failed to match device name\n"); goto fail_init_type; } err = publish_frontend_name(dev); if (err) goto fail_publish; err = netback_accel_debugfs_create(bend); if (err) goto fail_debugfs; mutex_unlock(&bend->bend_mutex); err = setup_config_accel_watch(dev, bend); if (err) goto fail_config_watch; err = setup_domu_accel_watch(dev, bend); if (err) goto fail_domu_watch; /* * Indicate to the other end that we're ready to start unless * the watch has already fired. */ mutex_lock(&bend->bend_mutex); if (bend->backend_state == XenbusStateClosed) { bend->backend_state = XenbusStateInitialising; net_accel_update_state(dev, XenbusStateInitialising); } mutex_unlock(&bend->bend_mutex); mutex_lock(&bend_list_mutex); link_bend(bend); mutex_unlock(&bend_list_mutex); return 0; fail_domu_watch: unregister_xenbus_watch(&bend->config_accel_watch); kfree(bend->config_accel_watch.node); fail_config_watch: /* * Flush the scheduled work queue before freeing bend to get * rid of any pending netback_accel_msg_rx_handler() */ flush_scheduled_work(); mutex_lock(&bend->bend_mutex); net_accel_update_state(dev, XenbusStateUnknown); netback_accel_debugfs_remove(bend); fail_debugfs: unpublish_frontend_name(dev); fail_publish: /* No need to reverse netback_accel_sf_hwtype. */ fail_init_type: kfree(bend->nicname); fail_nicname: binfo->netback_accel_priv = NULL; mutex_unlock(&bend->bend_mutex); kfree(bend); return err; }
static int xenbus_resume(device_t dev) { device_t *kids; struct xenbus_device_ivars *ivars; int i, count, error; char *statepath; xb_init_comms(); xs_resume(); /* * We must re-examine each device and find the new path for * its backend. */ if (device_get_children(dev, &kids, &count) == 0) { for (i = 0; i < count; i++) { if (device_get_state(kids[i]) == DS_NOTPRESENT) continue; ivars = device_get_ivars(kids[i]); unregister_xenbus_watch( &ivars->xd_otherend_watch); ivars->xd_state = XenbusStateInitialising; /* * Find the new backend details and * re-register our watch. */ free(ivars->xd_otherend_path, M_DEVBUF); error = xenbus_gather(XBT_NIL, ivars->xd_node, "backend-id", "%i", &ivars->xd_otherend_id, "backend", NULL, &ivars->xd_otherend_path, NULL); if (error) return (error); DEVICE_RESUME(kids[i]); statepath = malloc(strlen(ivars->xd_otherend_path) + strlen("/state") + 1, M_DEVBUF, M_WAITOK); sprintf(statepath, "%s/state", ivars->xd_otherend_path); free(ivars->xd_otherend_watch.node, M_DEVBUF); ivars->xd_otherend_watch.node = statepath; register_xenbus_watch( &ivars->xd_otherend_watch); #if 0 /* * Can't do this yet since we are running in * the xenwatch thread and if we sleep here, * we will stop delivering watch notifications * and the device will never come back online. */ sx_xlock(&ivars->xd_lock); while (ivars->xd_state != XenbusStateClosed && ivars->xd_state != XenbusStateConnected) sx_sleep(&ivars->xd_state, &ivars->xd_lock, 0, "xdresume", 0); sx_xunlock(&ivars->xd_lock); #endif } free(kids, M_TEMP); } return (0); }