diff options
Diffstat (limited to 'drivers/xen/xenbus')
-rw-r--r-- | drivers/xen/xenbus/xenbus_client.c | 16 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_comms.c | 4 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_probe.c | 151 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_probe.h | 5 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_probe_backend.c | 12 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_probe_frontend.c | 128 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_xs.c | 4 |
7 files changed, 101 insertions, 219 deletions
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 1906125..cdacf92 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -33,9 +33,7 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/vmalloc.h> -#include <linux/export.h> #include <asm/xen/hypervisor.h> -#include <asm/xen/page.h> #include <xen/interface/xen.h> #include <xen/interface/event_channel.h> #include <xen/events.h> @@ -437,26 +435,25 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn); int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) { struct gnttab_map_grant_ref op = { - .flags = GNTMAP_host_map | GNTMAP_contains_pte, + .flags = GNTMAP_host_map, .ref = gnt_ref, .dom = dev->otherend_id, }; struct vm_struct *area; - pte_t *pte; *vaddr = NULL; - area = alloc_vm_area(PAGE_SIZE, &pte); + area = xen_alloc_vm_area(PAGE_SIZE); if (!area) return -ENOMEM; - op.host_addr = arbitrary_virt_to_machine(pte).maddr; + op.host_addr = (unsigned long)area->addr; if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) BUG(); if (op.status != GNTST_okay) { - free_vm_area(area); + xen_free_vm_area(area); xenbus_dev_fatal(dev, op.status, "mapping in shared page %d from domain %d", gnt_ref, dev->otherend_id); @@ -529,7 +526,6 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) struct gnttab_unmap_grant_ref op = { .host_addr = (unsigned long)vaddr, }; - unsigned int level; /* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr) * method so that we don't have to muck with vmalloc internals here. @@ -551,14 +547,12 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) } op.handle = (grant_handle_t)area->phys_addr; - op.host_addr = arbitrary_virt_to_machine( - lookup_address((unsigned long)vaddr, &level)).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) BUG(); if (op.status == GNTST_okay) - free_vm_area(area); + xen_free_vm_area(area); else xenbus_dev_error(dev, op.status, "unmapping page at handle %d error %d", diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index 2eff7a6..090c61e 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -212,9 +212,7 @@ int xb_init_comms(void) printk(KERN_WARNING "XENBUS response ring is not quiescent " "(%08x:%08x): fixing up\n", intf->rsp_cons, intf->rsp_prod); - /* breaks kdump */ - if (!reset_devices) - intf->rsp_cons = intf->rsp_prod; + intf->rsp_cons = intf->rsp_prod; } if (xenbus_irq) { diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 1b178c6..7397695 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -46,7 +46,6 @@ #include <linux/mutex.h> #include <linux/io.h> #include <linux/slab.h> -#include <linux/module.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -310,7 +309,8 @@ void xenbus_unregister_driver(struct xenbus_driver *drv) } EXPORT_SYMBOL_GPL(xenbus_unregister_driver); -struct xb_find_info { +struct xb_find_info +{ struct xenbus_device *dev; const char *nodename; }; @@ -378,32 +378,26 @@ static void xenbus_dev_release(struct device *dev) kfree(to_xenbus_device(dev)); } -static ssize_t nodename_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t xendev_show_nodename(struct device *dev, + struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); } +static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); -static ssize_t devtype_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t xendev_show_devtype(struct device *dev, + struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); } +static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); -static ssize_t modalias_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t xendev_show_modalias(struct device *dev, + struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s:%s\n", dev->bus->name, - to_xenbus_device(dev)->devicetype); + return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype); } - -struct device_attribute xenbus_dev_attrs[] = { - __ATTR_RO(nodename), - __ATTR_RO(devtype), - __ATTR_RO(modalias), - __ATTR_NULL -}; -EXPORT_SYMBOL_GPL(xenbus_dev_attrs); +static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); int xenbus_probe_node(struct xen_bus_type *bus, const char *type, @@ -455,7 +449,25 @@ int xenbus_probe_node(struct xen_bus_type *bus, if (err) goto fail; + err = device_create_file(&xendev->dev, &dev_attr_nodename); + if (err) + goto fail_unregister; + + err = device_create_file(&xendev->dev, &dev_attr_devtype); + if (err) + goto fail_remove_nodename; + + err = device_create_file(&xendev->dev, &dev_attr_modalias); + if (err) + goto fail_remove_devtype; + return 0; +fail_remove_devtype: + device_remove_file(&xendev->dev, &dev_attr_devtype); +fail_remove_nodename: + device_remove_file(&xendev->dev, &dev_attr_nodename); +fail_unregister: + device_unregister(&xendev->dev); fail: kfree(xendev); return err; @@ -639,7 +651,7 @@ int xenbus_dev_cancel(struct device *dev) EXPORT_SYMBOL_GPL(xenbus_dev_cancel); /* A flag to determine if xenstored is 'ready' (i.e. has started) */ -int xenstored_ready; +int xenstored_ready = 0; int register_xenstore_notifier(struct notifier_block *nb) @@ -684,74 +696,64 @@ static int __init xenbus_probe_initcall(void) device_initcall(xenbus_probe_initcall); -/* Set up event channel for xenstored which is run as a local process - * (this is normally used only in dom0) - */ -static int __init xenstored_local_init(void) +static int __init xenbus_init(void) { int err = 0; unsigned long page = 0; - struct evtchn_alloc_unbound alloc_unbound; - /* Allocate Xenstore page */ - page = get_zeroed_page(GFP_KERNEL); - if (!page) - goto out_err; + DPRINTK(""); - xen_store_mfn = xen_start_info->store_mfn = - pfn_to_mfn(virt_to_phys((void *)page) >> - PAGE_SHIFT); + err = -ENODEV; + if (!xen_domain()) + return err; - /* Next allocate a local port which xenstored can bind to */ - alloc_unbound.dom = DOMID_SELF; - alloc_unbound.remote_dom = DOMID_SELF; + /* + * Domain0 doesn't have a store_evtchn or store_mfn yet. + */ + if (xen_initial_domain()) { + struct evtchn_alloc_unbound alloc_unbound; - err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, - &alloc_unbound); - if (err == -ENOSYS) - goto out_err; + /* Allocate Xenstore page */ + page = get_zeroed_page(GFP_KERNEL); + if (!page) + goto out_error; - BUG_ON(err); - xen_store_evtchn = xen_start_info->store_evtchn = - alloc_unbound.port; + xen_store_mfn = xen_start_info->store_mfn = + pfn_to_mfn(virt_to_phys((void *)page) >> + PAGE_SHIFT); - return 0; - - out_err: - if (page != 0) - free_page(page); - return err; -} + /* Next allocate a local port which xenstored can bind to */ + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = 0; -static int __init xenbus_init(void) -{ - int err = 0; + err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, + &alloc_unbound); + if (err == -ENOSYS) + goto out_error; - if (!xen_domain()) - return -ENODEV; + BUG_ON(err); + xen_store_evtchn = xen_start_info->store_evtchn = + alloc_unbound.port; - if (xen_hvm_domain()) { - uint64_t v = 0; - err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); - if (err) - goto out_error; - xen_store_evtchn = (int)v; - err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); - if (err) - goto out_error; - xen_store_mfn = (unsigned long)v; - xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); + xen_store_interface = mfn_to_virt(xen_store_mfn); } else { - xen_store_evtchn = xen_start_info->store_evtchn; - xen_store_mfn = xen_start_info->store_mfn; - if (xen_store_evtchn) - xenstored_ready = 1; - else { - err = xenstored_local_init(); + if (xen_hvm_domain()) { + uint64_t v = 0; + err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); + if (err) + goto out_error; + xen_store_evtchn = (int)v; + err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); if (err) goto out_error; + xen_store_mfn = (unsigned long)v; + xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); + } else { + xen_store_evtchn = xen_start_info->store_evtchn; + xen_store_mfn = xen_start_info->store_mfn; + xen_store_interface = mfn_to_virt(xen_store_mfn); + xenstored_ready = 1; } - xen_store_interface = mfn_to_virt(xen_store_mfn); } /* Initialize the interface to xenstore. */ @@ -770,7 +772,12 @@ static int __init xenbus_init(void) proc_mkdir("xen", NULL); #endif -out_error: + return 0; + + out_error: + if (page != 0) + free_page(page); + return err; } diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h index 9b1de4e..888b990 100644 --- a/drivers/xen/xenbus/xenbus_probe.h +++ b/drivers/xen/xenbus/xenbus_probe.h @@ -36,7 +36,8 @@ #define XEN_BUS_ID_SIZE 20 -struct xen_bus_type { +struct xen_bus_type +{ char *root; unsigned int levels; int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename); @@ -47,8 +48,6 @@ struct xen_bus_type { struct bus_type bus; }; -extern struct device_attribute xenbus_dev_attrs[]; - extern int xenbus_match(struct device *_dev, struct device_driver *_drv); extern int xenbus_dev_probe(struct device *_dev); extern int xenbus_dev_remove(struct device *_dev); diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index c3c7cd1..6cf467b 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -42,7 +42,6 @@ #include <linux/fcntl.h> #include <linux/mm.h> #include <linux/notifier.h> -#include <linux/export.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -105,9 +104,8 @@ static int xenbus_uevent_backend(struct device *dev, 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; + if (xdev == NULL) + return -ENODEV; /* stuff we want to pass to /sbin/hotplug */ if (add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype)) @@ -185,6 +183,10 @@ static void frontend_changed(struct xenbus_watch *watch, xenbus_otherend_changed(watch, vec, len, 0); } +static struct device_attribute xenbus_backend_dev_attrs[] = { + __ATTR_NULL +}; + static struct xen_bus_type xenbus_backend = { .root = "backend", .levels = 3, /* backend/type/<frontend>/<id> */ @@ -198,7 +200,7 @@ static struct xen_bus_type xenbus_backend = { .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, .shutdown = xenbus_dev_shutdown, - .dev_attrs = xenbus_dev_attrs, + .dev_attrs = xenbus_backend_dev_attrs, }, }; diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 2ce95c0..560f217 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -13,7 +13,6 @@ #include <linux/kthread.h> #include <linux/mutex.h> #include <linux/io.h> -#include <linux/module.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -82,6 +81,10 @@ static void backend_changed(struct xenbus_watch *watch, xenbus_otherend_changed(watch, vec, len, 1); } +static struct device_attribute xenbus_frontend_dev_attrs[] = { + __ATTR_NULL +}; + static const struct dev_pm_ops xenbus_pm_ops = { .suspend = xenbus_dev_suspend, .resume = xenbus_dev_resume, @@ -103,7 +106,7 @@ static struct xen_bus_type xenbus_frontend = { .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, .shutdown = xenbus_dev_shutdown, - .dev_attrs = xenbus_dev_attrs, + .dev_attrs = xenbus_frontend_dev_attrs, .pm = &xenbus_pm_ops, }, @@ -286,131 +289,10 @@ int __xenbus_register_frontend(struct xenbus_driver *drv, } EXPORT_SYMBOL_GPL(__xenbus_register_frontend); -static DECLARE_WAIT_QUEUE_HEAD(backend_state_wq); -static int backend_state; - -static void xenbus_reset_backend_state_changed(struct xenbus_watch *w, - const char **v, unsigned int l) -{ - xenbus_scanf(XBT_NIL, v[XS_WATCH_PATH], "", "%i", &backend_state); - printk(KERN_DEBUG "XENBUS: backend %s %s\n", - v[XS_WATCH_PATH], xenbus_strstate(backend_state)); - wake_up(&backend_state_wq); -} - -static void xenbus_reset_wait_for_backend(char *be, int expected) -{ - long timeout; - timeout = wait_event_interruptible_timeout(backend_state_wq, - backend_state == expected, 5 * HZ); - if (timeout <= 0) - printk(KERN_INFO "XENBUS: backend %s timed out.\n", be); -} - -/* - * 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); -} - -static void xenbus_check_frontend(char *class, char *dev) -{ - int be_state, fe_state, err; - char *backend, *frontend; - - frontend = kasprintf(GFP_NOIO | __GFP_HIGH, "device/%s/%s", class, dev); - if (!frontend) - return; - - err = xenbus_scanf(XBT_NIL, frontend, "state", "%i", &fe_state); - if (err != 1) - goto out; - - switch (fe_state) { - case XenbusStateConnected: - case XenbusStateClosed: - printk(KERN_DEBUG "XENBUS: frontend %s %s\n", - frontend, xenbus_strstate(fe_state)); - backend = xenbus_read(XBT_NIL, frontend, "backend", NULL); - if (!backend || IS_ERR(backend)) - goto out; - err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state); - if (err == 1) - xenbus_reset_frontend(frontend, backend, be_state); - kfree(backend); - break; - default: - break; - } -out: - kfree(frontend); -} - -static void xenbus_reset_state(void) -{ - char **devclass, **dev; - int devclass_n, dev_n; - int i, j; - - devclass = xenbus_directory(XBT_NIL, "device", "", &devclass_n); - if (IS_ERR(devclass)) - return; - - for (i = 0; i < devclass_n; i++) { - dev = xenbus_directory(XBT_NIL, "device", devclass[i], &dev_n); - if (IS_ERR(dev)) - continue; - for (j = 0; j < dev_n; j++) - xenbus_check_frontend(devclass[i], dev[j]); - kfree(dev); - } - kfree(devclass); -} - static int frontend_probe_and_watch(struct notifier_block *notifier, unsigned long event, void *data) { - /* reset devices in Connected or Closed state */ - if (xen_hvm_domain()) - xenbus_reset_state(); /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_frontend); register_xenbus_watch(&fe_watch); diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index a580b17..daee5db 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -45,7 +45,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <xen/xenbus.h> -#include <xen/xen.h> #include "xenbus_comms.h" struct xs_stored_msg { @@ -639,7 +638,8 @@ int register_xenbus_watch(struct xenbus_watch *watch) err = xs_watch(watch->node, token); - if (err) { + /* Ignore errors due to multiple registration. */ + if ((err != 0) && (err != -EEXIST)) { spin_lock(&watches_lock); list_del(&watch->list); spin_unlock(&watches_lock); |