diff options
Diffstat (limited to 'drivers/xen/xenbus')
| -rw-r--r-- | drivers/xen/xenbus/xenbus_client.c | 5 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_comms.h | 1 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_dev_backend.c | 21 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe.c | 27 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe.h | 7 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe_frontend.c | 37 |
6 files changed, 69 insertions, 29 deletions
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 61786be9138b..ec097d6f964d 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c | |||
| @@ -534,7 +534,7 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, | |||
| 534 | 534 | ||
| 535 | err = xenbus_map_ring(dev, gnt_ref, &node->handle, addr); | 535 | err = xenbus_map_ring(dev, gnt_ref, &node->handle, addr); |
| 536 | if (err) | 536 | if (err) |
| 537 | goto out_err; | 537 | goto out_err_free_ballooned_pages; |
| 538 | 538 | ||
| 539 | spin_lock(&xenbus_valloc_lock); | 539 | spin_lock(&xenbus_valloc_lock); |
| 540 | list_add(&node->next, &xenbus_valloc_pages); | 540 | list_add(&node->next, &xenbus_valloc_pages); |
| @@ -543,8 +543,9 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, | |||
| 543 | *vaddr = addr; | 543 | *vaddr = addr; |
| 544 | return 0; | 544 | return 0; |
| 545 | 545 | ||
| 546 | out_err: | 546 | out_err_free_ballooned_pages: |
| 547 | free_xenballooned_pages(1, &node->page); | 547 | free_xenballooned_pages(1, &node->page); |
| 548 | out_err: | ||
| 548 | kfree(node); | 549 | kfree(node); |
| 549 | return err; | 550 | return err; |
| 550 | } | 551 | } |
diff --git a/drivers/xen/xenbus/xenbus_comms.h b/drivers/xen/xenbus/xenbus_comms.h index c8abd3b8a6c4..e74f9c1fbd80 100644 --- a/drivers/xen/xenbus/xenbus_comms.h +++ b/drivers/xen/xenbus/xenbus_comms.h | |||
| @@ -45,6 +45,7 @@ int xb_wait_for_data_to_read(void); | |||
| 45 | int xs_input_avail(void); | 45 | int xs_input_avail(void); |
| 46 | extern struct xenstore_domain_interface *xen_store_interface; | 46 | extern struct xenstore_domain_interface *xen_store_interface; |
| 47 | extern int xen_store_evtchn; | 47 | extern int xen_store_evtchn; |
| 48 | extern enum xenstore_init xen_store_domain_type; | ||
| 48 | 49 | ||
| 49 | extern const struct file_operations xen_xenbus_fops; | 50 | extern const struct file_operations xen_xenbus_fops; |
| 50 | 51 | ||
diff --git a/drivers/xen/xenbus/xenbus_dev_backend.c b/drivers/xen/xenbus/xenbus_dev_backend.c index d73000800762..a6f42fc01407 100644 --- a/drivers/xen/xenbus/xenbus_dev_backend.c +++ b/drivers/xen/xenbus/xenbus_dev_backend.c | |||
| @@ -70,22 +70,21 @@ static long xenbus_alloc(domid_t domid) | |||
| 70 | return err; | 70 | return err; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static long xenbus_backend_ioctl(struct file *file, unsigned int cmd, unsigned long data) | 73 | static long xenbus_backend_ioctl(struct file *file, unsigned int cmd, |
| 74 | unsigned long data) | ||
| 74 | { | 75 | { |
| 75 | if (!capable(CAP_SYS_ADMIN)) | 76 | if (!capable(CAP_SYS_ADMIN)) |
| 76 | return -EPERM; | 77 | return -EPERM; |
| 77 | 78 | ||
| 78 | switch (cmd) { | 79 | switch (cmd) { |
| 79 | case IOCTL_XENBUS_BACKEND_EVTCHN: | 80 | case IOCTL_XENBUS_BACKEND_EVTCHN: |
| 80 | if (xen_store_evtchn > 0) | 81 | if (xen_store_evtchn > 0) |
| 81 | return xen_store_evtchn; | 82 | return xen_store_evtchn; |
| 82 | return -ENODEV; | 83 | return -ENODEV; |
| 83 | 84 | case IOCTL_XENBUS_BACKEND_SETUP: | |
| 84 | case IOCTL_XENBUS_BACKEND_SETUP: | 85 | return xenbus_alloc(data); |
| 85 | return xenbus_alloc(data); | 86 | default: |
| 86 | 87 | return -ENOTTY; | |
| 87 | default: | ||
| 88 | return -ENOTTY; | ||
| 89 | } | 88 | } |
| 90 | } | 89 | } |
| 91 | 90 | ||
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 3325884c693f..56cfaaa9d006 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c | |||
| @@ -69,6 +69,9 @@ EXPORT_SYMBOL_GPL(xen_store_evtchn); | |||
| 69 | struct xenstore_domain_interface *xen_store_interface; | 69 | struct xenstore_domain_interface *xen_store_interface; |
| 70 | EXPORT_SYMBOL_GPL(xen_store_interface); | 70 | EXPORT_SYMBOL_GPL(xen_store_interface); |
| 71 | 71 | ||
| 72 | enum xenstore_init xen_store_domain_type; | ||
| 73 | EXPORT_SYMBOL_GPL(xen_store_domain_type); | ||
| 74 | |||
| 72 | static unsigned long xen_store_mfn; | 75 | static unsigned long xen_store_mfn; |
| 73 | 76 | ||
| 74 | static BLOCKING_NOTIFIER_HEAD(xenstore_chain); | 77 | static BLOCKING_NOTIFIER_HEAD(xenstore_chain); |
| @@ -719,17 +722,11 @@ static int __init xenstored_local_init(void) | |||
| 719 | return err; | 722 | return err; |
| 720 | } | 723 | } |
| 721 | 724 | ||
| 722 | enum xenstore_init { | ||
| 723 | UNKNOWN, | ||
| 724 | PV, | ||
| 725 | HVM, | ||
| 726 | LOCAL, | ||
| 727 | }; | ||
| 728 | static int __init xenbus_init(void) | 725 | static int __init xenbus_init(void) |
| 729 | { | 726 | { |
| 730 | int err = 0; | 727 | int err = 0; |
| 731 | enum xenstore_init usage = UNKNOWN; | ||
| 732 | uint64_t v = 0; | 728 | uint64_t v = 0; |
| 729 | xen_store_domain_type = XS_UNKNOWN; | ||
| 733 | 730 | ||
| 734 | if (!xen_domain()) | 731 | if (!xen_domain()) |
| 735 | return -ENODEV; | 732 | return -ENODEV; |
| @@ -737,29 +734,29 @@ static int __init xenbus_init(void) | |||
| 737 | xenbus_ring_ops_init(); | 734 | xenbus_ring_ops_init(); |
| 738 | 735 | ||
| 739 | if (xen_pv_domain()) | 736 | if (xen_pv_domain()) |
| 740 | usage = PV; | 737 | xen_store_domain_type = XS_PV; |
| 741 | if (xen_hvm_domain()) | 738 | if (xen_hvm_domain()) |
| 742 | usage = HVM; | 739 | xen_store_domain_type = XS_HVM; |
| 743 | if (xen_hvm_domain() && xen_initial_domain()) | 740 | if (xen_hvm_domain() && xen_initial_domain()) |
| 744 | usage = LOCAL; | 741 | xen_store_domain_type = XS_LOCAL; |
| 745 | if (xen_pv_domain() && !xen_start_info->store_evtchn) | 742 | if (xen_pv_domain() && !xen_start_info->store_evtchn) |
| 746 | usage = LOCAL; | 743 | xen_store_domain_type = XS_LOCAL; |
| 747 | if (xen_pv_domain() && xen_start_info->store_evtchn) | 744 | if (xen_pv_domain() && xen_start_info->store_evtchn) |
| 748 | xenstored_ready = 1; | 745 | xenstored_ready = 1; |
| 749 | 746 | ||
| 750 | switch (usage) { | 747 | switch (xen_store_domain_type) { |
| 751 | case LOCAL: | 748 | case XS_LOCAL: |
| 752 | err = xenstored_local_init(); | 749 | err = xenstored_local_init(); |
| 753 | if (err) | 750 | if (err) |
| 754 | goto out_error; | 751 | goto out_error; |
| 755 | xen_store_interface = mfn_to_virt(xen_store_mfn); | 752 | xen_store_interface = mfn_to_virt(xen_store_mfn); |
| 756 | break; | 753 | break; |
| 757 | case PV: | 754 | case XS_PV: |
| 758 | xen_store_evtchn = xen_start_info->store_evtchn; | 755 | xen_store_evtchn = xen_start_info->store_evtchn; |
| 759 | xen_store_mfn = xen_start_info->store_mfn; | 756 | xen_store_mfn = xen_start_info->store_mfn; |
| 760 | xen_store_interface = mfn_to_virt(xen_store_mfn); | 757 | xen_store_interface = mfn_to_virt(xen_store_mfn); |
| 761 | break; | 758 | break; |
| 762 | case HVM: | 759 | case XS_HVM: |
| 763 | err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); | 760 | err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); |
| 764 | if (err) | 761 | if (err) |
| 765 | goto out_error; | 762 | goto out_error; |
diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h index bb4f92ed8730..146f857a36f8 100644 --- a/drivers/xen/xenbus/xenbus_probe.h +++ b/drivers/xen/xenbus/xenbus_probe.h | |||
| @@ -47,6 +47,13 @@ struct xen_bus_type { | |||
| 47 | struct bus_type bus; | 47 | struct bus_type bus; |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | enum xenstore_init { | ||
| 51 | XS_UNKNOWN, | ||
| 52 | XS_PV, | ||
| 53 | XS_HVM, | ||
| 54 | XS_LOCAL, | ||
| 55 | }; | ||
| 56 | |||
| 50 | extern struct device_attribute xenbus_dev_attrs[]; | 57 | extern struct device_attribute xenbus_dev_attrs[]; |
| 51 | 58 | ||
| 52 | extern int xenbus_match(struct device *_dev, struct device_driver *_drv); | 59 | extern int xenbus_match(struct device *_dev, struct device_driver *_drv); |
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 3159a37d966d..a7e25073de19 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include "xenbus_probe.h" | 29 | #include "xenbus_probe.h" |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | static struct workqueue_struct *xenbus_frontend_wq; | ||
| 33 | |||
| 32 | /* device/<type>/<id> => <type>-<id> */ | 34 | /* device/<type>/<id> => <type>-<id> */ |
| 33 | static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) | 35 | static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) |
| 34 | { | 36 | { |
| @@ -89,9 +91,40 @@ static void backend_changed(struct xenbus_watch *watch, | |||
| 89 | xenbus_otherend_changed(watch, vec, len, 1); | 91 | xenbus_otherend_changed(watch, vec, len, 1); |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 94 | static void xenbus_frontend_delayed_resume(struct work_struct *w) | ||
| 95 | { | ||
| 96 | struct xenbus_device *xdev = container_of(w, struct xenbus_device, work); | ||
| 97 | |||
| 98 | xenbus_dev_resume(&xdev->dev); | ||
| 99 | } | ||
| 100 | |||
| 101 | static int xenbus_frontend_dev_resume(struct device *dev) | ||
| 102 | { | ||
| 103 | /* | ||
| 104 | * If xenstored is running in this domain, we cannot access the backend | ||
| 105 | * state at the moment, so we need to defer xenbus_dev_resume | ||
| 106 | */ | ||
| 107 | if (xen_store_domain_type == XS_LOCAL) { | ||
| 108 | struct xenbus_device *xdev = to_xenbus_device(dev); | ||
| 109 | |||
| 110 | if (!xenbus_frontend_wq) { | ||
| 111 | pr_err("%s: no workqueue to process delayed resume\n", | ||
| 112 | xdev->nodename); | ||
| 113 | return -EFAULT; | ||
| 114 | } | ||
| 115 | |||
| 116 | INIT_WORK(&xdev->work, xenbus_frontend_delayed_resume); | ||
| 117 | queue_work(xenbus_frontend_wq, &xdev->work); | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | return xenbus_dev_resume(dev); | ||
| 123 | } | ||
| 124 | |||
| 92 | static const struct dev_pm_ops xenbus_pm_ops = { | 125 | static const struct dev_pm_ops xenbus_pm_ops = { |
| 93 | .suspend = xenbus_dev_suspend, | 126 | .suspend = xenbus_dev_suspend, |
| 94 | .resume = xenbus_dev_resume, | 127 | .resume = xenbus_frontend_dev_resume, |
| 95 | .freeze = xenbus_dev_suspend, | 128 | .freeze = xenbus_dev_suspend, |
| 96 | .thaw = xenbus_dev_cancel, | 129 | .thaw = xenbus_dev_cancel, |
| 97 | .restore = xenbus_dev_resume, | 130 | .restore = xenbus_dev_resume, |
| @@ -440,6 +473,8 @@ static int __init xenbus_probe_frontend_init(void) | |||
| 440 | 473 | ||
| 441 | register_xenstore_notifier(&xenstore_notifier); | 474 | register_xenstore_notifier(&xenstore_notifier); |
| 442 | 475 | ||
| 476 | xenbus_frontend_wq = create_workqueue("xenbus_frontend"); | ||
| 477 | |||
| 443 | return 0; | 478 | return 0; |
| 444 | } | 479 | } |
| 445 | subsys_initcall(xenbus_probe_frontend_init); | 480 | subsys_initcall(xenbus_probe_frontend_init); |
