static int xenbus_uevent_backend(struct device *dev, struct kobj_uevent_env *env) { struct xenbus_device *xdev; struct xenbus_driver *drv; DPRINTK(""); if (dev == NULL) return -ENODEV; xdev = to_xenbus_device(dev); if (xdev == NULL) return -ENODEV; /* stuff we want to pass to /sbin/hotplug */ add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype); add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename); add_uevent_var(env, "XENBUS_BASE_PATH=%s", xenbus_backend.root); if (dev->driver) { drv = to_xenbus_driver(dev->driver); if (drv && drv->uevent) return drv->uevent(xdev, env); } return 0; }
static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential) { struct xenbus_device *xendev = to_xenbus_device(dev); struct device_driver *drv = data; struct xenbus_driver *xendrv; /* */ if (!dev->driver) return 0; /* */ if (drv && (dev->driver != drv)) return 0; if (ignore_nonessential) { /* */ if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0)) return 0; if ((strncmp(xendev->nodename, "device/vfb", 10) == 0)) return 0; } xendrv = to_xenbus_driver(dev->driver); return (xendev->state < XenbusStateConnected || (xendev->state == XenbusStateConnected && xendrv->is_ready && !xendrv->is_ready(xendev))); }
static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential) { struct xenbus_device *xendev = to_xenbus_device(dev); struct device_driver *drv = data; struct xenbus_driver *xendrv; /* * A device with no driver will never connect. We care only about * devices which should currently be in the process of connecting. */ if (!dev->driver) return 0; /* Is this search limited to a particular driver? */ if (drv && (dev->driver != drv)) return 0; if (ignore_nonessential) { /* With older QEMU, for PVonHVM guests the guest config files * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0'] * which is nonsensical as there is no PV FB (there can be * a PVKB) running as HVM guest. */ if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0)) return 0; if ((strncmp(xendev->nodename, "device/vfb", 10) == 0)) return 0; } xendrv = to_xenbus_driver(dev->driver); return (xendev->state < XenbusStateConnected || (xendev->state == XenbusStateConnected && xendrv->is_ready && !xendrv->is_ready(xendev))); }
static int talk_to_otherend(struct xenbus_device *dev) { struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); free_otherend_watch(dev); free_otherend_details(dev); return drv->read_otherend_details(dev); }
int xenbus_match(struct device *_dev, struct device_driver *_drv) { struct xenbus_driver *drv = to_xenbus_driver(_drv); if (!drv->ids) return 0; return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; }
int xenbus_dev_probe(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); const struct xenbus_device_id *id; int err; DPRINTK("%s", dev->nodename); if (!drv->probe) { err = -ENODEV; goto fail; } id = match_device(drv->ids, dev); if (!id) { err = -ENODEV; goto fail; } err = talk_to_otherend(dev); if (err) { dev_warn(&dev->dev, "xenbus_probe: talk_to_otherend on %s failed.\n", dev->nodename); return err; } err = drv->probe(dev, id); if (err) goto fail; err = watch_otherend(dev); if (err) { dev_warn(&dev->dev, "xenbus_probe: watch_otherend on %s failed.\n", dev->nodename); return err; } return 0; fail: xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); xenbus_switch_state(dev, XenbusStateClosed); #if defined(CONFIG_XEN) || defined(MODULE) return -ENODEV; #else return err; #endif }
/* add for vmdq migrate.When the device is vmdq_vnic ,return */ if(0 == strcmp(xendev->devicetype, VMDQ_VNIC)){ return 0; } int err = xenbus_gather(XBT_NIL, xendev->nodename, id_node, "%i", &xendev->otherend_id, path_node, NULL, &xendev->otherend, NULL); if (err) { xenbus_dev_fatal(xendev, err, "reading other end details from %s", xendev->nodename); return err; } if (strlen(xendev->otherend) == 0 || !xenbus_exists(XBT_NIL, xendev->otherend, "")) { xenbus_dev_fatal(xendev, -ENOENT, "unable to read other end from %s. " "missing or inaccessible.", xendev->nodename); free_otherend_details(xendev); return -ENOENT; } return 0; } PARAVIRT_EXPORT_SYMBOL(xenbus_read_otherend_details); #if defined(CONFIG_XEN) || defined(MODULE) static int read_backend_details(struct xenbus_device *xendev) { return xenbus_read_otherend_details(xendev, "backend-id", "backend"); } static void otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) #else /* !CONFIG_XEN && !MODULE */ void xenbus_otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len, int ignore_on_shutdown) #endif /* CONFIG_XEN || MODULE */ { struct xenbus_device *dev = container_of(watch, struct xenbus_device, otherend_watch); struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); enum xenbus_state state; /* Protect us against watches firing on old details when the otherend details change, say immediately after a resume. */ if (!dev->otherend || strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) { dev_dbg(&dev->dev, "Ignoring watch at %s", vec[XS_WATCH_PATH]); return; } state = xenbus_read_driver_state(dev->otherend); dev_dbg(&dev->dev, "state is %d (%s), %s, %s", state, xenbus_strstate(state), dev->otherend_watch.node, vec[XS_WATCH_PATH]); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) /* * Ignore xenbus transitions during shutdown. This prevents us doing * work that can fail e.g., when the rootfs is gone. */ if (system_state > SYSTEM_RUNNING) { /* If we're frontend, drive the state machine to Closed. */ /* This should cause the backend to release our resources. */ # if defined(CONFIG_XEN) || defined(MODULE) const struct xen_bus_type *bus = container_of(dev->dev.bus, struct xen_bus_type, bus); int ignore_on_shutdown = (bus->levels == 2); # endif if (ignore_on_shutdown && (state == XenbusStateClosing)) xenbus_frontend_closed(dev); return; } #endif if (drv->otherend_changed) drv->otherend_changed(dev, state); }
int xenbus_dev_remove(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); DPRINTK("%s", dev->nodename); free_otherend_watch(dev); free_otherend_details(dev); if (drv->remove) drv->remove(dev); xenbus_switch_state(dev, XenbusStateClosed); return 0; }
static int xenbus_dev_probe(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); const struct xenbus_device_id *id; int err; DPRINTK("%s", dev->nodename); if (!drv->probe) { err = -ENODEV; goto fail; } id = match_device(drv->ids, dev); if (!id) { err = -ENODEV; goto fail; } err = talk_to_otherend(dev); if (err) { printk(KERN_WARNING "xenbus_probe: talk_to_otherend on %s failed.\n", dev->nodename); return err; } err = drv->probe(dev, id); if (err) goto fail; err = watch_otherend(dev); if (err) { printk(KERN_WARNING "xenbus_probe: watch_otherend on %s failed.\n", dev->nodename); return err; } return 0; fail: xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); xenbus_switch_state(dev, XenbusStateClosed); return -ENODEV; }
static int xenbus_hotplug_backend(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { struct xenbus_device *xdev; struct xenbus_driver *drv; int i = 0; int length = 0; DPRINTK(""); if (dev == NULL) return -ENODEV; xdev = to_xenbus_device(dev); if (xdev == NULL) return -ENODEV; /* stuff we want to pass to /sbin/hotplug */ add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length, "XENBUS_TYPE=%s", xdev->devicetype); add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length, "XENBUS_PATH=%s", xdev->nodename); add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length, "XENBUS_BASE_PATH=%s", xenbus_backend.root); /* terminate, set to next free slot, shrink available space */ envp[i] = NULL; envp = &envp[i]; num_envp -= i; buffer = &buffer[length]; buffer_size -= length; if (dev->driver) { drv = to_xenbus_driver(dev->driver); if (drv && drv->uevent) return drv->uevent(xdev, envp, num_envp, buffer, buffer_size); } return 0; }
int xenbus_dev_suspend(struct device *dev) { int err = 0; struct xenbus_driver *drv; struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); DPRINTK("%s", xdev->nodename); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); if (drv->suspend) err = drv->suspend(xdev); if (err) pr_warn("suspend %s failed: %i\n", dev_name(dev), err); return 0; }
static int resume_dev(struct device *dev, void *data) { int err; struct xenbus_driver *drv; struct xenbus_device *xdev; DPRINTK(""); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); xdev = container_of(dev, struct xenbus_device, dev); err = talk_to_otherend(xdev); if (err) { printk(KERN_WARNING "xenbus: resume (talk_to_otherend) %s failed: %i\n", dev_name(dev), err); return err; } xdev->state = XenbusStateInitialising; if (drv->resume) { err = drv->resume(xdev); if (err) { printk(KERN_WARNING "xenbus: resume %s failed: %i\n", dev_name(dev), err); return err; } } err = watch_otherend(xdev); if (err) { printk(KERN_WARNING "xenbus_probe: resume (watch_otherend) %s failed: " "%d.\n", dev_name(dev), err); return err; } return 0; }
static int suspend_dev(struct device *dev, void *data) { int err = 0; struct xenbus_driver *drv; struct xenbus_device *xdev; DPRINTK(""); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); xdev = container_of(dev, struct xenbus_device, dev); if (drv->suspend) err = drv->suspend(xdev); if (err) printk(KERN_WARNING "xenbus: suspend %s failed: %i\n", dev_name(dev), err); return 0; }
static int suspend_cancel_dev(struct device *dev, void *data) { int err = 0; struct xenbus_driver *drv; struct xenbus_device *xdev; DPRINTK(""); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); xdev = container_of(dev, struct xenbus_device, dev); if (drv->suspend_cancel) err = drv->suspend_cancel(xdev); if (err) pr_warning("xenbus: suspend_cancel %s failed: %i\n", dev_name(dev), err); return 0; }
int xenbus_dev_suspend(struct device *dev, pm_message_t state) { int err = 0; struct xenbus_driver *drv; struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); DPRINTK("%s", xdev->nodename); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); if (drv->suspend) err = drv->suspend(xdev, state); if (err) printk(KERN_WARNING "xenbus: suspend %s failed: %i\n", dev_name(dev), err); return 0; }
static void otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) { struct xenbus_device *dev = container_of(watch, struct xenbus_device, otherend_watch); struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); enum xenbus_state state; /* Protect us against watches firing on old details when the otherend details change, say immediately after a resume. */ if (!dev->otherend || strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) { dev_dbg(&dev->dev, "Ignoring watch at %s\n", vec[XS_WATCH_PATH]); return; } state = xenbus_read_driver_state(dev->otherend); dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n", state, xenbus_strstate(state), dev->otherend_watch.node, vec[XS_WATCH_PATH]); /* * Ignore xenbus transitions during shutdown. This prevents us doing * work that can fail e.g., when the rootfs is gone. */ if (system_state > SYSTEM_RUNNING) { struct xen_bus_type *bus = bus; bus = container_of(dev->dev.bus, struct xen_bus_type, bus); /* If we're frontend, drive the state machine to Closed. */ /* This should cause the backend to release our resources. */ if ((bus == &xenbus_frontend) && (state == XenbusStateClosing)) xenbus_frontend_closed(dev); return; } if (drv->otherend_changed) drv->otherend_changed(dev, state); }
static int is_disconnected_device(struct device *dev, void *data) { struct xenbus_device *xendev = to_xenbus_device(dev); struct device_driver *drv = data; struct xenbus_driver *xendrv; /* * A device with no driver will never connect. We care only about * devices which should currently be in the process of connecting. */ if (!dev->driver) return 0; /* Is this search limited to a particular driver? */ if (drv && (dev->driver != drv)) return 0; xendrv = to_xenbus_driver(dev->driver); return (xendev->state != XenbusStateConnected || (xendrv->is_ready && !xendrv->is_ready(xendev))); }
int xenbus_dev_resume(struct device *dev) #endif { int err; struct xenbus_driver *drv; struct xenbus_device *xdev = container_of(dev, struct xenbus_device, dev); DPRINTK("%s", xdev->nodename); if (dev->driver == NULL) return 0; drv = to_xenbus_driver(dev->driver); err = talk_to_otherend(xdev); if (err) { pr_warning("xenbus: resume (talk_to_otherend) %s failed: %i\n", dev_name(dev), err); return err; } xdev->state = XenbusStateInitialising; if (drv->resume) { err = drv->resume(xdev); if (err) { pr_warning("xenbus: resume %s failed: %i\n", dev_name(dev), err); return err; } } err = watch_otherend(xdev); if (err) { pr_warning("xenbus_probe: resume (watch_otherend) %s failed:" " %d\n", dev_name(dev), err); return err; } return 0; }
void xenbus_otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len, int ignore_on_shutdown) { struct xenbus_device *dev = container_of(watch, struct xenbus_device, otherend_watch); struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver); enum xenbus_state state; /* Protect us against watches firing on old details when the otherend details change, say immediately after a resume. */ if (!dev->otherend || strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) { dev_dbg(&dev->dev, "Ignoring watch at %s\n", vec[XS_WATCH_PATH]); return; } state = xenbus_read_driver_state(dev->otherend); dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n", state, xenbus_strstate(state), dev->otherend_watch.node, vec[XS_WATCH_PATH]); /* * Ignore xenbus transitions during shutdown. This prevents us doing * work that can fail e.g., when the rootfs is gone. */ if (system_state > SYSTEM_RUNNING) { if (ignore_on_shutdown && (state == XenbusStateClosing)) xenbus_frontend_closed(dev); return; } if (drv->otherend_changed) drv->otherend_changed(dev, state); }
static int xenbus_uevent_backend(struct device *dev, struct kobj_uevent_env *env) { struct xenbus_device *xdev; struct xenbus_driver *drv; struct xen_bus_type *bus; DPRINTK(""); if (dev == NULL) return -ENODEV; xdev = to_xenbus_device(dev); bus = container_of(xdev->dev.bus, struct xen_bus_type, bus); if (add_uevent_var(env, "MODALIAS=xen-backend:%s", xdev->devicetype)) return -ENOMEM; /* stuff we want to pass to /sbin/hotplug */ if (add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype)) return -ENOMEM; if (add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename)) return -ENOMEM; if (add_uevent_var(env, "XENBUS_BASE_PATH=%s", bus->root)) return -ENOMEM; if (dev->driver) { drv = to_xenbus_driver(dev->driver); if (drv && drv->uevent) return drv->uevent(xdev, env); } return 0; }