aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 17:01:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 17:01:37 -0400
commita372c967a38a789caf52d4b1d2a78781e1b25d91 (patch)
tree6b7947c97d43b91ee119e41f2b6e2ae0e6082cad /drivers/xen
parent32d01dc7be4e725ab85ce1d74e8f4adc02ad68dd (diff)
parentcd979883b9ede90643e019f33cb317933eb867b4 (diff)
Merge tag 'stable/for-linus-3.15-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull Xen features and fixes from David Vrabel: "Support PCI devices with multiple MSIs, performance improvement for kernel-based backends (by not populated m2p overrides when mapping), and assorted minor bug fixes and cleanups" * tag 'stable/for-linus-3.15-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/acpi-processor: fix enabling interrupts on syscore_resume xen/grant-table: Refactor gnttab_[un]map_refs to avoid m2p_override xen: remove XEN_PRIVILEGED_GUEST xen: add support for MSI message groups xen-pciback: Use pci_enable_msix_exact() instead of pci_enable_msix() xen/xenbus: remove unused xenbus_bind_evtchn() xen/events: remove unnecessary call to bind_evtchn_to_cpu() xen/events: remove the unused resend_irq_on_evtchn() drivers:xen-selfballoon:reset 'frontswap_inertia_counter' after frontswap_shrink drivers: xen: Include appropriate header file in pcpu.c drivers: xen: Mark function as static in platform-pci.c
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/events/events_base.c83
-rw-r--r--drivers/xen/events/events_internal.h1
-rw-r--r--drivers/xen/grant-table.c73
-rw-r--r--drivers/xen/manage.c16
-rw-r--r--drivers/xen/pcpu.c1
-rw-r--r--drivers/xen/platform-pci.c2
-rw-r--r--drivers/xen/xen-acpi-processor.c15
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c3
-rw-r--r--drivers/xen/xen-selfballoon.c1
-rw-r--r--drivers/xen/xenbus/xenbus_client.c27
10 files changed, 76 insertions, 146 deletions
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index c3458f58de90..d5a3de88ac59 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -388,10 +388,10 @@ static void xen_irq_init(unsigned irq)
388 list_add_tail(&info->list, &xen_irq_list_head); 388 list_add_tail(&info->list, &xen_irq_list_head);
389} 389}
390 390
391static int __must_check xen_allocate_irq_dynamic(void) 391static int __must_check xen_allocate_irqs_dynamic(int nvec)
392{ 392{
393 int first = 0; 393 int first = 0;
394 int irq; 394 int i, irq;
395 395
396#ifdef CONFIG_X86_IO_APIC 396#ifdef CONFIG_X86_IO_APIC
397 /* 397 /*
@@ -405,14 +405,22 @@ static int __must_check xen_allocate_irq_dynamic(void)
405 first = get_nr_irqs_gsi(); 405 first = get_nr_irqs_gsi();
406#endif 406#endif
407 407
408 irq = irq_alloc_desc_from(first, -1); 408 irq = irq_alloc_descs_from(first, nvec, -1);
409 409
410 if (irq >= 0) 410 if (irq >= 0) {
411 xen_irq_init(irq); 411 for (i = 0; i < nvec; i++)
412 xen_irq_init(irq + i);
413 }
412 414
413 return irq; 415 return irq;
414} 416}
415 417
418static inline int __must_check xen_allocate_irq_dynamic(void)
419{
420
421 return xen_allocate_irqs_dynamic(1);
422}
423
416static int __must_check xen_allocate_irq_gsi(unsigned gsi) 424static int __must_check xen_allocate_irq_gsi(unsigned gsi)
417{ 425{
418 int irq; 426 int irq;
@@ -466,9 +474,6 @@ static void xen_evtchn_close(unsigned int port)
466 close.port = port; 474 close.port = port;
467 if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) 475 if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
468 BUG(); 476 BUG();
469
470 /* Closed ports are implicitly re-bound to VCPU0. */
471 bind_evtchn_to_cpu(port, 0);
472} 477}
473 478
474static void pirq_query_unmask(int irq) 479static void pirq_query_unmask(int irq)
@@ -730,22 +735,25 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
730} 735}
731 736
732int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, 737int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
733 int pirq, const char *name, domid_t domid) 738 int pirq, int nvec, const char *name, domid_t domid)
734{ 739{
735 int irq, ret; 740 int i, irq, ret;
736 741
737 mutex_lock(&irq_mapping_update_lock); 742 mutex_lock(&irq_mapping_update_lock);
738 743
739 irq = xen_allocate_irq_dynamic(); 744 irq = xen_allocate_irqs_dynamic(nvec);
740 if (irq < 0) 745 if (irq < 0)
741 goto out; 746 goto out;
742 747
743 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, 748 for (i = 0; i < nvec; i++) {
744 name); 749 irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name);
750
751 ret = xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid,
752 i == 0 ? 0 : PIRQ_MSI_GROUP);
753 if (ret < 0)
754 goto error_irq;
755 }
745 756
746 ret = xen_irq_info_pirq_setup(irq, 0, pirq, 0, domid, 0);
747 if (ret < 0)
748 goto error_irq;
749 ret = irq_set_msi_desc(irq, msidesc); 757 ret = irq_set_msi_desc(irq, msidesc);
750 if (ret < 0) 758 if (ret < 0)
751 goto error_irq; 759 goto error_irq;
@@ -753,7 +761,8 @@ out:
753 mutex_unlock(&irq_mapping_update_lock); 761 mutex_unlock(&irq_mapping_update_lock);
754 return irq; 762 return irq;
755error_irq: 763error_irq:
756 __unbind_from_irq(irq); 764 for (; i >= 0; i--)
765 __unbind_from_irq(irq + i);
757 mutex_unlock(&irq_mapping_update_lock); 766 mutex_unlock(&irq_mapping_update_lock);
758 return ret; 767 return ret;
759} 768}
@@ -767,7 +776,12 @@ int xen_destroy_irq(int irq)
767 776
768 mutex_lock(&irq_mapping_update_lock); 777 mutex_lock(&irq_mapping_update_lock);
769 778
770 if (xen_initial_domain()) { 779 /*
780 * If trying to remove a vector in a MSI group different
781 * than the first one skip the PIRQ unmap unless this vector
782 * is the first one in the group.
783 */
784 if (xen_initial_domain() && !(info->u.pirq.flags & PIRQ_MSI_GROUP)) {
771 unmap_irq.pirq = info->u.pirq.pirq; 785 unmap_irq.pirq = info->u.pirq.pirq;
772 unmap_irq.domid = info->u.pirq.domid; 786 unmap_irq.domid = info->u.pirq.domid;
773 rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); 787 rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
@@ -1329,26 +1343,6 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
1329 return rebind_irq_to_cpu(data->irq, tcpu); 1343 return rebind_irq_to_cpu(data->irq, tcpu);
1330} 1344}
1331 1345
1332static int retrigger_evtchn(int evtchn)
1333{
1334 int masked;
1335
1336 if (!VALID_EVTCHN(evtchn))
1337 return 0;
1338
1339 masked = test_and_set_mask(evtchn);
1340 set_evtchn(evtchn);
1341 if (!masked)
1342 unmask_evtchn(evtchn);
1343
1344 return 1;
1345}
1346
1347int resend_irq_on_evtchn(unsigned int irq)
1348{
1349 return retrigger_evtchn(evtchn_from_irq(irq));
1350}
1351
1352static void enable_dynirq(struct irq_data *data) 1346static void enable_dynirq(struct irq_data *data)
1353{ 1347{
1354 int evtchn = evtchn_from_irq(data->irq); 1348 int evtchn = evtchn_from_irq(data->irq);
@@ -1383,7 +1377,18 @@ static void mask_ack_dynirq(struct irq_data *data)
1383 1377
1384static int retrigger_dynirq(struct irq_data *data) 1378static int retrigger_dynirq(struct irq_data *data)
1385{ 1379{
1386 return retrigger_evtchn(evtchn_from_irq(data->irq)); 1380 unsigned int evtchn = evtchn_from_irq(data->irq);
1381 int masked;
1382
1383 if (!VALID_EVTCHN(evtchn))
1384 return 0;
1385
1386 masked = test_and_set_mask(evtchn);
1387 set_evtchn(evtchn);
1388 if (!masked)
1389 unmask_evtchn(evtchn);
1390
1391 return 1;
1387} 1392}
1388 1393
1389static void restore_pirqs(void) 1394static void restore_pirqs(void)
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h
index 677f41a0fff9..50c2050a1e32 100644
--- a/drivers/xen/events/events_internal.h
+++ b/drivers/xen/events/events_internal.h
@@ -53,6 +53,7 @@ struct irq_info {
53 53
54#define PIRQ_NEEDS_EOI (1 << 0) 54#define PIRQ_NEEDS_EOI (1 << 0)
55#define PIRQ_SHAREABLE (1 << 1) 55#define PIRQ_SHAREABLE (1 << 1)
56#define PIRQ_MSI_GROUP (1 << 2)
56 57
57struct evtchn_ops { 58struct evtchn_ops {
58 unsigned (*max_channels)(void); 59 unsigned (*max_channels)(void);
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index b84e3ab839aa..6d325bda76da 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -933,9 +933,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
933 struct page **pages, unsigned int count) 933 struct page **pages, unsigned int count)
934{ 934{
935 int i, ret; 935 int i, ret;
936 bool lazy = false;
937 pte_t *pte;
938 unsigned long mfn;
939 936
940 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count); 937 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
941 if (ret) 938 if (ret)
@@ -947,45 +944,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
947 gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, 944 gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
948 &map_ops[i].status, __func__); 945 &map_ops[i].status, __func__);
949 946
950 /* this is basically a nop on x86 */ 947 return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count);
951 if (xen_feature(XENFEAT_auto_translated_physmap)) {
952 for (i = 0; i < count; i++) {
953 if (map_ops[i].status)
954 continue;
955 set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
956 map_ops[i].dev_bus_addr >> PAGE_SHIFT);
957 }
958 return ret;
959 }
960
961 if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
962 arch_enter_lazy_mmu_mode();
963 lazy = true;
964 }
965
966 for (i = 0; i < count; i++) {
967 /* Do not add to override if the map failed. */
968 if (map_ops[i].status)
969 continue;
970
971 if (map_ops[i].flags & GNTMAP_contains_pte) {
972 pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
973 (map_ops[i].host_addr & ~PAGE_MASK));
974 mfn = pte_mfn(*pte);
975 } else {
976 mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
977 }
978 ret = m2p_add_override(mfn, pages[i], kmap_ops ?
979 &kmap_ops[i] : NULL);
980 if (ret)
981 goto out;
982 }
983
984 out:
985 if (lazy)
986 arch_leave_lazy_mmu_mode();
987
988 return ret;
989} 948}
990EXPORT_SYMBOL_GPL(gnttab_map_refs); 949EXPORT_SYMBOL_GPL(gnttab_map_refs);
991 950
@@ -993,39 +952,13 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
993 struct gnttab_map_grant_ref *kmap_ops, 952 struct gnttab_map_grant_ref *kmap_ops,
994 struct page **pages, unsigned int count) 953 struct page **pages, unsigned int count)
995{ 954{
996 int i, ret; 955 int ret;
997 bool lazy = false;
998 956
999 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); 957 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
1000 if (ret) 958 if (ret)
1001 return ret; 959 return ret;
1002 960
1003 /* this is basically a nop on x86 */ 961 return clear_foreign_p2m_mapping(unmap_ops, kmap_ops, pages, count);
1004 if (xen_feature(XENFEAT_auto_translated_physmap)) {
1005 for (i = 0; i < count; i++) {
1006 set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
1007 INVALID_P2M_ENTRY);
1008 }
1009 return ret;
1010 }
1011
1012 if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
1013 arch_enter_lazy_mmu_mode();
1014 lazy = true;
1015 }
1016
1017 for (i = 0; i < count; i++) {
1018 ret = m2p_remove_override(pages[i], kmap_ops ?
1019 &kmap_ops[i] : NULL);
1020 if (ret)
1021 goto out;
1022 }
1023
1024 out:
1025 if (lazy)
1026 arch_leave_lazy_mmu_mode();
1027
1028 return ret;
1029} 962}
1030EXPORT_SYMBOL_GPL(gnttab_unmap_refs); 963EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
1031 964
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 624e8dc24532..fc6c94c0b436 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -46,6 +46,20 @@ struct suspend_info {
46 void (*post)(int cancelled); 46 void (*post)(int cancelled);
47}; 47};
48 48
49static RAW_NOTIFIER_HEAD(xen_resume_notifier);
50
51void xen_resume_notifier_register(struct notifier_block *nb)
52{
53 raw_notifier_chain_register(&xen_resume_notifier, nb);
54}
55EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
56
57void xen_resume_notifier_unregister(struct notifier_block *nb)
58{
59 raw_notifier_chain_unregister(&xen_resume_notifier, nb);
60}
61EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
62
49#ifdef CONFIG_HIBERNATE_CALLBACKS 63#ifdef CONFIG_HIBERNATE_CALLBACKS
50static void xen_hvm_post_suspend(int cancelled) 64static void xen_hvm_post_suspend(int cancelled)
51{ 65{
@@ -152,6 +166,8 @@ static void do_suspend(void)
152 166
153 err = stop_machine(xen_suspend, &si, cpumask_of(0)); 167 err = stop_machine(xen_suspend, &si, cpumask_of(0));
154 168
169 raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
170
155 dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE); 171 dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
156 172
157 if (err) { 173 if (err) {
diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c
index 79e1dff7ed4f..0aac403d53fd 100644
--- a/drivers/xen/pcpu.c
+++ b/drivers/xen/pcpu.c
@@ -40,6 +40,7 @@
40#include <linux/capability.h> 40#include <linux/capability.h>
41 41
42#include <xen/xen.h> 42#include <xen/xen.h>
43#include <xen/acpi.h>
43#include <xen/xenbus.h> 44#include <xen/xenbus.h>
44#include <xen/events.h> 45#include <xen/events.h>
45#include <xen/interface/platform.h> 46#include <xen/interface/platform.h>
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index a1361c312c06..3454973dc3bb 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -45,7 +45,7 @@ static unsigned long platform_mmio_alloc;
45static unsigned long platform_mmiolen; 45static unsigned long platform_mmiolen;
46static uint64_t callback_via; 46static uint64_t callback_via;
47 47
48unsigned long alloc_xen_mmio(unsigned long len) 48static unsigned long alloc_xen_mmio(unsigned long len)
49{ 49{
50 unsigned long addr; 50 unsigned long addr;
51 51
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 7231859119f1..82358d14ecf1 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -27,10 +27,10 @@
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/types.h> 29#include <linux/types.h>
30#include <linux/syscore_ops.h>
31#include <linux/acpi.h> 30#include <linux/acpi.h>
32#include <acpi/processor.h> 31#include <acpi/processor.h>
33#include <xen/xen.h> 32#include <xen/xen.h>
33#include <xen/xen-ops.h>
34#include <xen/interface/platform.h> 34#include <xen/interface/platform.h>
35#include <asm/xen/hypercall.h> 35#include <asm/xen/hypercall.h>
36 36
@@ -495,14 +495,15 @@ static int xen_upload_processor_pm_data(void)
495 return rc; 495 return rc;
496} 496}
497 497
498static void xen_acpi_processor_resume(void) 498static int xen_acpi_processor_resume(struct notifier_block *nb,
499 unsigned long action, void *data)
499{ 500{
500 bitmap_zero(acpi_ids_done, nr_acpi_bits); 501 bitmap_zero(acpi_ids_done, nr_acpi_bits);
501 xen_upload_processor_pm_data(); 502 return xen_upload_processor_pm_data();
502} 503}
503 504
504static struct syscore_ops xap_syscore_ops = { 505struct notifier_block xen_acpi_processor_resume_nb = {
505 .resume = xen_acpi_processor_resume, 506 .notifier_call = xen_acpi_processor_resume,
506}; 507};
507 508
508static int __init xen_acpi_processor_init(void) 509static int __init xen_acpi_processor_init(void)
@@ -555,7 +556,7 @@ static int __init xen_acpi_processor_init(void)
555 if (rc) 556 if (rc)
556 goto err_unregister; 557 goto err_unregister;
557 558
558 register_syscore_ops(&xap_syscore_ops); 559 xen_resume_notifier_register(&xen_acpi_processor_resume_nb);
559 560
560 return 0; 561 return 0;
561err_unregister: 562err_unregister:
@@ -574,7 +575,7 @@ static void __exit xen_acpi_processor_exit(void)
574{ 575{
575 int i; 576 int i;
576 577
577 unregister_syscore_ops(&xap_syscore_ops); 578 xen_resume_notifier_unregister(&xen_acpi_processor_resume_nb);
578 kfree(acpi_ids_done); 579 kfree(acpi_ids_done);
579 kfree(acpi_id_present); 580 kfree(acpi_id_present);
580 kfree(acpi_id_cst_present); 581 kfree(acpi_id_cst_present);
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index 64eb0cd8b8af..929dd46bb40c 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -213,8 +213,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
213 entries[i].vector = op->msix_entries[i].vector; 213 entries[i].vector = op->msix_entries[i].vector;
214 } 214 }
215 215
216 result = pci_enable_msix(dev, entries, op->value); 216 result = pci_enable_msix_exact(dev, entries, op->value);
217
218 if (result == 0) { 217 if (result == 0) {
219 for (i = 0; i < op->value; i++) { 218 for (i = 0; i < op->value; i++) {
220 op->msix_entries[i].entry = entries[i].entry; 219 op->msix_entries[i].entry = entries[i].entry;
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c
index 745ad79c1d8e..3b2bffde534f 100644
--- a/drivers/xen/xen-selfballoon.c
+++ b/drivers/xen/xen-selfballoon.c
@@ -170,6 +170,7 @@ static void frontswap_selfshrink(void)
170 tgt_frontswap_pages = cur_frontswap_pages - 170 tgt_frontswap_pages = cur_frontswap_pages -
171 (cur_frontswap_pages / frontswap_hysteresis); 171 (cur_frontswap_pages / frontswap_hysteresis);
172 frontswap_shrink(tgt_frontswap_pages); 172 frontswap_shrink(tgt_frontswap_pages);
173 frontswap_inertia_counter = frontswap_inertia;
173} 174}
174 175
175#endif /* CONFIG_FRONTSWAP */ 176#endif /* CONFIG_FRONTSWAP */
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 01d59e66565d..439c9dca9eee 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -401,33 +401,6 @@ EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
401 401
402 402
403/** 403/**
404 * Bind to an existing interdomain event channel in another domain. Returns 0
405 * on success and stores the local port in *port. On error, returns -errno,
406 * switches the device to XenbusStateClosing, and saves the error in XenStore.
407 */
408int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
409{
410 struct evtchn_bind_interdomain bind_interdomain;
411 int err;
412
413 bind_interdomain.remote_dom = dev->otherend_id;
414 bind_interdomain.remote_port = remote_port;
415
416 err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
417 &bind_interdomain);
418 if (err)
419 xenbus_dev_fatal(dev, err,
420 "binding to event channel %d from domain %d",
421 remote_port, dev->otherend_id);
422 else
423 *port = bind_interdomain.local_port;
424
425 return err;
426}
427EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
428
429
430/**
431 * Free an existing event channel. Returns 0 on success or -errno on error. 404 * Free an existing event channel. Returns 0 on success or -errno on error.
432 */ 405 */
433int xenbus_free_evtchn(struct xenbus_device *dev, int port) 406int xenbus_free_evtchn(struct xenbus_device *dev, int port)