diff options
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/Kconfig | 9 | ||||
-rw-r--r-- | drivers/xen/Makefile | 3 | ||||
-rw-r--r-- | drivers/xen/events.c | 95 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 77 | ||||
-rw-r--r-- | drivers/xen/manage.c | 46 | ||||
-rw-r--r-- | drivers/xen/platform-pci.c | 207 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_probe.c | 52 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_xs.c | 57 | ||||
-rw-r--r-- | drivers/xen/xenfs/super.c | 4 | ||||
-rw-r--r-- | drivers/xen/xenfs/xenbus.c | 3 |
10 files changed, 503 insertions, 50 deletions
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index fad3df2c1276..0a8826936639 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
@@ -62,4 +62,13 @@ config XEN_SYS_HYPERVISOR | |||
62 | virtual environment, /sys/hypervisor will still be present, | 62 | virtual environment, /sys/hypervisor will still be present, |
63 | but will have no xen contents. | 63 | but will have no xen contents. |
64 | 64 | ||
65 | config XEN_PLATFORM_PCI | ||
66 | tristate "xen platform pci device driver" | ||
67 | depends on XEN_PVHVM | ||
68 | default m | ||
69 | help | ||
70 | Driver for the Xen PCI Platform device: it is responsible for | ||
71 | initializing xenbus and grant_table when running in a Xen HVM | ||
72 | domain. As a consequence this driver is required to run any Xen PV | ||
73 | frontend on Xen HVM. | ||
65 | endmenu | 74 | endmenu |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 7c284342f30f..e392fb776af3 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
@@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_XENCOMM) += xencomm.o | |||
9 | obj-$(CONFIG_XEN_BALLOON) += balloon.o | 9 | obj-$(CONFIG_XEN_BALLOON) += balloon.o |
10 | obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o | 10 | obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o |
11 | obj-$(CONFIG_XENFS) += xenfs/ | 11 | obj-$(CONFIG_XENFS) += xenfs/ |
12 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o \ No newline at end of file | 12 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o |
13 | obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 28f133ae76ad..72f91bff29c7 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/bootmem.h> | 29 | #include <linux/bootmem.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | 31 | ||
32 | #include <asm/desc.h> | ||
32 | #include <asm/ptrace.h> | 33 | #include <asm/ptrace.h> |
33 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
34 | #include <asm/idle.h> | 35 | #include <asm/idle.h> |
@@ -36,10 +37,14 @@ | |||
36 | #include <asm/xen/hypercall.h> | 37 | #include <asm/xen/hypercall.h> |
37 | #include <asm/xen/hypervisor.h> | 38 | #include <asm/xen/hypervisor.h> |
38 | 39 | ||
40 | #include <xen/xen.h> | ||
41 | #include <xen/hvm.h> | ||
39 | #include <xen/xen-ops.h> | 42 | #include <xen/xen-ops.h> |
40 | #include <xen/events.h> | 43 | #include <xen/events.h> |
41 | #include <xen/interface/xen.h> | 44 | #include <xen/interface/xen.h> |
42 | #include <xen/interface/event_channel.h> | 45 | #include <xen/interface/event_channel.h> |
46 | #include <xen/interface/hvm/hvm_op.h> | ||
47 | #include <xen/interface/hvm/params.h> | ||
43 | 48 | ||
44 | /* | 49 | /* |
45 | * This lock protects updates to the following mapping and reference-count | 50 | * This lock protects updates to the following mapping and reference-count |
@@ -335,9 +340,18 @@ static int find_unbound_irq(void) | |||
335 | int irq; | 340 | int irq; |
336 | struct irq_desc *desc; | 341 | struct irq_desc *desc; |
337 | 342 | ||
338 | for (irq = 0; irq < nr_irqs; irq++) | 343 | for (irq = 0; irq < nr_irqs; irq++) { |
344 | desc = irq_to_desc(irq); | ||
345 | /* only 0->15 have init'd desc; handle irq > 16 */ | ||
346 | if (desc == NULL) | ||
347 | break; | ||
348 | if (desc->chip == &no_irq_chip) | ||
349 | break; | ||
350 | if (desc->chip != &xen_dynamic_chip) | ||
351 | continue; | ||
339 | if (irq_info[irq].type == IRQT_UNBOUND) | 352 | if (irq_info[irq].type == IRQT_UNBOUND) |
340 | break; | 353 | break; |
354 | } | ||
341 | 355 | ||
342 | if (irq == nr_irqs) | 356 | if (irq == nr_irqs) |
343 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | 357 | panic("No available IRQ to bind to: increase nr_irqs!\n"); |
@@ -346,7 +360,7 @@ static int find_unbound_irq(void) | |||
346 | if (WARN_ON(desc == NULL)) | 360 | if (WARN_ON(desc == NULL)) |
347 | return -1; | 361 | return -1; |
348 | 362 | ||
349 | dynamic_irq_init(irq); | 363 | dynamic_irq_init_keep_chip_data(irq); |
350 | 364 | ||
351 | return irq; | 365 | return irq; |
352 | } | 366 | } |
@@ -618,17 +632,13 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count); | |||
618 | * a bitset of words which contain pending event bits. The second | 632 | * a bitset of words which contain pending event bits. The second |
619 | * level is a bitset of pending events themselves. | 633 | * level is a bitset of pending events themselves. |
620 | */ | 634 | */ |
621 | void xen_evtchn_do_upcall(struct pt_regs *regs) | 635 | static void __xen_evtchn_do_upcall(void) |
622 | { | 636 | { |
623 | int cpu = get_cpu(); | 637 | int cpu = get_cpu(); |
624 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
625 | struct shared_info *s = HYPERVISOR_shared_info; | 638 | struct shared_info *s = HYPERVISOR_shared_info; |
626 | struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); | 639 | struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); |
627 | unsigned count; | 640 | unsigned count; |
628 | 641 | ||
629 | exit_idle(); | ||
630 | irq_enter(); | ||
631 | |||
632 | do { | 642 | do { |
633 | unsigned long pending_words; | 643 | unsigned long pending_words; |
634 | 644 | ||
@@ -665,14 +675,31 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) | |||
665 | 675 | ||
666 | count = __get_cpu_var(xed_nesting_count); | 676 | count = __get_cpu_var(xed_nesting_count); |
667 | __get_cpu_var(xed_nesting_count) = 0; | 677 | __get_cpu_var(xed_nesting_count) = 0; |
668 | } while(count != 1); | 678 | } while (count != 1 || vcpu_info->evtchn_upcall_pending); |
669 | 679 | ||
670 | out: | 680 | out: |
681 | |||
682 | put_cpu(); | ||
683 | } | ||
684 | |||
685 | void xen_evtchn_do_upcall(struct pt_regs *regs) | ||
686 | { | ||
687 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
688 | |||
689 | exit_idle(); | ||
690 | irq_enter(); | ||
691 | |||
692 | __xen_evtchn_do_upcall(); | ||
693 | |||
671 | irq_exit(); | 694 | irq_exit(); |
672 | set_irq_regs(old_regs); | 695 | set_irq_regs(old_regs); |
696 | } | ||
673 | 697 | ||
674 | put_cpu(); | 698 | void xen_hvm_evtchn_do_upcall(void) |
699 | { | ||
700 | __xen_evtchn_do_upcall(); | ||
675 | } | 701 | } |
702 | EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall); | ||
676 | 703 | ||
677 | /* Rebind a new event channel to an existing irq. */ | 704 | /* Rebind a new event channel to an existing irq. */ |
678 | void rebind_evtchn_irq(int evtchn, int irq) | 705 | void rebind_evtchn_irq(int evtchn, int irq) |
@@ -709,7 +736,10 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
709 | struct evtchn_bind_vcpu bind_vcpu; | 736 | struct evtchn_bind_vcpu bind_vcpu; |
710 | int evtchn = evtchn_from_irq(irq); | 737 | int evtchn = evtchn_from_irq(irq); |
711 | 738 | ||
712 | if (!VALID_EVTCHN(evtchn)) | 739 | /* events delivered via platform PCI interrupts are always |
740 | * routed to vcpu 0 */ | ||
741 | if (!VALID_EVTCHN(evtchn) || | ||
742 | (xen_hvm_domain() && !xen_have_vector_callback)) | ||
713 | return -1; | 743 | return -1; |
714 | 744 | ||
715 | /* Send future instances of this interrupt to other vcpu. */ | 745 | /* Send future instances of this interrupt to other vcpu. */ |
@@ -934,6 +964,44 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { | |||
934 | .retrigger = retrigger_dynirq, | 964 | .retrigger = retrigger_dynirq, |
935 | }; | 965 | }; |
936 | 966 | ||
967 | int xen_set_callback_via(uint64_t via) | ||
968 | { | ||
969 | struct xen_hvm_param a; | ||
970 | a.domid = DOMID_SELF; | ||
971 | a.index = HVM_PARAM_CALLBACK_IRQ; | ||
972 | a.value = via; | ||
973 | return HYPERVISOR_hvm_op(HVMOP_set_param, &a); | ||
974 | } | ||
975 | EXPORT_SYMBOL_GPL(xen_set_callback_via); | ||
976 | |||
977 | #ifdef CONFIG_XEN_PVHVM | ||
978 | /* Vector callbacks are better than PCI interrupts to receive event | ||
979 | * channel notifications because we can receive vector callbacks on any | ||
980 | * vcpu and we don't need PCI support or APIC interactions. */ | ||
981 | void xen_callback_vector(void) | ||
982 | { | ||
983 | int rc; | ||
984 | uint64_t callback_via; | ||
985 | if (xen_have_vector_callback) { | ||
986 | callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK); | ||
987 | rc = xen_set_callback_via(callback_via); | ||
988 | if (rc) { | ||
989 | printk(KERN_ERR "Request for Xen HVM callback vector" | ||
990 | " failed.\n"); | ||
991 | xen_have_vector_callback = 0; | ||
992 | return; | ||
993 | } | ||
994 | printk(KERN_INFO "Xen HVM callback vector for event delivery is " | ||
995 | "enabled\n"); | ||
996 | /* in the restore case the vector has already been allocated */ | ||
997 | if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors)) | ||
998 | alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector); | ||
999 | } | ||
1000 | } | ||
1001 | #else | ||
1002 | void xen_callback_vector(void) {} | ||
1003 | #endif | ||
1004 | |||
937 | void __init xen_init_IRQ(void) | 1005 | void __init xen_init_IRQ(void) |
938 | { | 1006 | { |
939 | int i; | 1007 | int i; |
@@ -948,5 +1016,10 @@ void __init xen_init_IRQ(void) | |||
948 | for (i = 0; i < NR_EVENT_CHANNELS; i++) | 1016 | for (i = 0; i < NR_EVENT_CHANNELS; i++) |
949 | mask_evtchn(i); | 1017 | mask_evtchn(i); |
950 | 1018 | ||
951 | irq_ctx_init(smp_processor_id()); | 1019 | if (xen_hvm_domain()) { |
1020 | xen_callback_vector(); | ||
1021 | native_init_IRQ(); | ||
1022 | } else { | ||
1023 | irq_ctx_init(smp_processor_id()); | ||
1024 | } | ||
952 | } | 1025 | } |
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index f66db3b91d61..6c4531816496 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -37,11 +37,13 @@ | |||
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/uaccess.h> | 39 | #include <linux/uaccess.h> |
40 | #include <linux/io.h> | ||
40 | 41 | ||
41 | #include <xen/xen.h> | 42 | #include <xen/xen.h> |
42 | #include <xen/interface/xen.h> | 43 | #include <xen/interface/xen.h> |
43 | #include <xen/page.h> | 44 | #include <xen/page.h> |
44 | #include <xen/grant_table.h> | 45 | #include <xen/grant_table.h> |
46 | #include <xen/interface/memory.h> | ||
45 | #include <asm/xen/hypercall.h> | 47 | #include <asm/xen/hypercall.h> |
46 | 48 | ||
47 | #include <asm/pgtable.h> | 49 | #include <asm/pgtable.h> |
@@ -59,6 +61,8 @@ static unsigned int boot_max_nr_grant_frames; | |||
59 | static int gnttab_free_count; | 61 | static int gnttab_free_count; |
60 | static grant_ref_t gnttab_free_head; | 62 | static grant_ref_t gnttab_free_head; |
61 | static DEFINE_SPINLOCK(gnttab_list_lock); | 63 | static DEFINE_SPINLOCK(gnttab_list_lock); |
64 | unsigned long xen_hvm_resume_frames; | ||
65 | EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); | ||
62 | 66 | ||
63 | static struct grant_entry *shared; | 67 | static struct grant_entry *shared; |
64 | 68 | ||
@@ -433,7 +437,7 @@ static unsigned int __max_nr_grant_frames(void) | |||
433 | return query.max_nr_frames; | 437 | return query.max_nr_frames; |
434 | } | 438 | } |
435 | 439 | ||
436 | static inline unsigned int max_nr_grant_frames(void) | 440 | unsigned int gnttab_max_grant_frames(void) |
437 | { | 441 | { |
438 | unsigned int xen_max = __max_nr_grant_frames(); | 442 | unsigned int xen_max = __max_nr_grant_frames(); |
439 | 443 | ||
@@ -441,6 +445,7 @@ static inline unsigned int max_nr_grant_frames(void) | |||
441 | return boot_max_nr_grant_frames; | 445 | return boot_max_nr_grant_frames; |
442 | return xen_max; | 446 | return xen_max; |
443 | } | 447 | } |
448 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | ||
444 | 449 | ||
445 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | 450 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) |
446 | { | 451 | { |
@@ -449,6 +454,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
449 | unsigned int nr_gframes = end_idx + 1; | 454 | unsigned int nr_gframes = end_idx + 1; |
450 | int rc; | 455 | int rc; |
451 | 456 | ||
457 | if (xen_hvm_domain()) { | ||
458 | struct xen_add_to_physmap xatp; | ||
459 | unsigned int i = end_idx; | ||
460 | rc = 0; | ||
461 | /* | ||
462 | * Loop backwards, so that the first hypercall has the largest | ||
463 | * index, ensuring that the table will grow only once. | ||
464 | */ | ||
465 | do { | ||
466 | xatp.domid = DOMID_SELF; | ||
467 | xatp.idx = i; | ||
468 | xatp.space = XENMAPSPACE_grant_table; | ||
469 | xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i; | ||
470 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); | ||
471 | if (rc != 0) { | ||
472 | printk(KERN_WARNING | ||
473 | "grant table add_to_physmap failed, err=%d\n", rc); | ||
474 | break; | ||
475 | } | ||
476 | } while (i-- > start_idx); | ||
477 | |||
478 | return rc; | ||
479 | } | ||
480 | |||
452 | frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); | 481 | frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); |
453 | if (!frames) | 482 | if (!frames) |
454 | return -ENOMEM; | 483 | return -ENOMEM; |
@@ -465,7 +494,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
465 | 494 | ||
466 | BUG_ON(rc || setup.status); | 495 | BUG_ON(rc || setup.status); |
467 | 496 | ||
468 | rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(), | 497 | rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(), |
469 | &shared); | 498 | &shared); |
470 | BUG_ON(rc); | 499 | BUG_ON(rc); |
471 | 500 | ||
@@ -476,9 +505,27 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
476 | 505 | ||
477 | int gnttab_resume(void) | 506 | int gnttab_resume(void) |
478 | { | 507 | { |
479 | if (max_nr_grant_frames() < nr_grant_frames) | 508 | unsigned int max_nr_gframes; |
509 | |||
510 | max_nr_gframes = gnttab_max_grant_frames(); | ||
511 | if (max_nr_gframes < nr_grant_frames) | ||
480 | return -ENOSYS; | 512 | return -ENOSYS; |
481 | return gnttab_map(0, nr_grant_frames - 1); | 513 | |
514 | if (xen_pv_domain()) | ||
515 | return gnttab_map(0, nr_grant_frames - 1); | ||
516 | |||
517 | if (!shared) { | ||
518 | shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes); | ||
519 | if (shared == NULL) { | ||
520 | printk(KERN_WARNING | ||
521 | "Failed to ioremap gnttab share frames!"); | ||
522 | return -ENOMEM; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | gnttab_map(0, nr_grant_frames - 1); | ||
527 | |||
528 | return 0; | ||
482 | } | 529 | } |
483 | 530 | ||
484 | int gnttab_suspend(void) | 531 | int gnttab_suspend(void) |
@@ -495,7 +542,7 @@ static int gnttab_expand(unsigned int req_entries) | |||
495 | cur = nr_grant_frames; | 542 | cur = nr_grant_frames; |
496 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / | 543 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / |
497 | GREFS_PER_GRANT_FRAME); | 544 | GREFS_PER_GRANT_FRAME); |
498 | if (cur + extra > max_nr_grant_frames()) | 545 | if (cur + extra > gnttab_max_grant_frames()) |
499 | return -ENOSPC; | 546 | return -ENOSPC; |
500 | 547 | ||
501 | rc = gnttab_map(cur, cur + extra - 1); | 548 | rc = gnttab_map(cur, cur + extra - 1); |
@@ -505,15 +552,12 @@ static int gnttab_expand(unsigned int req_entries) | |||
505 | return rc; | 552 | return rc; |
506 | } | 553 | } |
507 | 554 | ||
508 | static int __devinit gnttab_init(void) | 555 | int gnttab_init(void) |
509 | { | 556 | { |
510 | int i; | 557 | int i; |
511 | unsigned int max_nr_glist_frames, nr_glist_frames; | 558 | unsigned int max_nr_glist_frames, nr_glist_frames; |
512 | unsigned int nr_init_grefs; | 559 | unsigned int nr_init_grefs; |
513 | 560 | ||
514 | if (!xen_domain()) | ||
515 | return -ENODEV; | ||
516 | |||
517 | nr_grant_frames = 1; | 561 | nr_grant_frames = 1; |
518 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | 562 | boot_max_nr_grant_frames = __max_nr_grant_frames(); |
519 | 563 | ||
@@ -556,5 +600,18 @@ static int __devinit gnttab_init(void) | |||
556 | kfree(gnttab_list); | 600 | kfree(gnttab_list); |
557 | return -ENOMEM; | 601 | return -ENOMEM; |
558 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(gnttab_init); | ||
604 | |||
605 | static int __devinit __gnttab_init(void) | ||
606 | { | ||
607 | /* Delay grant-table initialization in the PV on HVM case */ | ||
608 | if (xen_hvm_domain()) | ||
609 | return 0; | ||
610 | |||
611 | if (!xen_pv_domain()) | ||
612 | return -ENODEV; | ||
613 | |||
614 | return gnttab_init(); | ||
615 | } | ||
559 | 616 | ||
560 | core_initcall(gnttab_init); | 617 | core_initcall(__gnttab_init); |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 07e857b0de13..1799bd890315 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/stop_machine.h> | 9 | #include <linux/stop_machine.h> |
10 | #include <linux/freezer.h> | 10 | #include <linux/freezer.h> |
11 | 11 | ||
12 | #include <xen/xen.h> | ||
12 | #include <xen/xenbus.h> | 13 | #include <xen/xenbus.h> |
13 | #include <xen/grant_table.h> | 14 | #include <xen/grant_table.h> |
14 | #include <xen/events.h> | 15 | #include <xen/events.h> |
@@ -17,6 +18,7 @@ | |||
17 | 18 | ||
18 | #include <asm/xen/hypercall.h> | 19 | #include <asm/xen/hypercall.h> |
19 | #include <asm/xen/page.h> | 20 | #include <asm/xen/page.h> |
21 | #include <asm/xen/hypervisor.h> | ||
20 | 22 | ||
21 | enum shutdown_state { | 23 | enum shutdown_state { |
22 | SHUTDOWN_INVALID = -1, | 24 | SHUTDOWN_INVALID = -1, |
@@ -33,10 +35,30 @@ enum shutdown_state { | |||
33 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; | 35 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; |
34 | 36 | ||
35 | #ifdef CONFIG_PM_SLEEP | 37 | #ifdef CONFIG_PM_SLEEP |
36 | static int xen_suspend(void *data) | 38 | static int xen_hvm_suspend(void *data) |
37 | { | 39 | { |
40 | struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; | ||
38 | int *cancelled = data; | 41 | int *cancelled = data; |
42 | |||
43 | BUG_ON(!irqs_disabled()); | ||
44 | |||
45 | *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); | ||
46 | |||
47 | xen_hvm_post_suspend(*cancelled); | ||
48 | gnttab_resume(); | ||
49 | |||
50 | if (!*cancelled) { | ||
51 | xen_irq_resume(); | ||
52 | xen_timer_resume(); | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int xen_suspend(void *data) | ||
59 | { | ||
39 | int err; | 60 | int err; |
61 | int *cancelled = data; | ||
40 | 62 | ||
41 | BUG_ON(!irqs_disabled()); | 63 | BUG_ON(!irqs_disabled()); |
42 | 64 | ||
@@ -106,7 +128,10 @@ static void do_suspend(void) | |||
106 | goto out_resume; | 128 | goto out_resume; |
107 | } | 129 | } |
108 | 130 | ||
109 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 131 | if (xen_hvm_domain()) |
132 | err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0)); | ||
133 | else | ||
134 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | ||
110 | 135 | ||
111 | dpm_resume_noirq(PMSG_RESUME); | 136 | dpm_resume_noirq(PMSG_RESUME); |
112 | 137 | ||
@@ -255,7 +280,19 @@ static int shutdown_event(struct notifier_block *notifier, | |||
255 | return NOTIFY_DONE; | 280 | return NOTIFY_DONE; |
256 | } | 281 | } |
257 | 282 | ||
258 | static int __init setup_shutdown_event(void) | 283 | static int __init __setup_shutdown_event(void) |
284 | { | ||
285 | /* Delay initialization in the PV on HVM case */ | ||
286 | if (xen_hvm_domain()) | ||
287 | return 0; | ||
288 | |||
289 | if (!xen_pv_domain()) | ||
290 | return -ENODEV; | ||
291 | |||
292 | return xen_setup_shutdown_event(); | ||
293 | } | ||
294 | |||
295 | int xen_setup_shutdown_event(void) | ||
259 | { | 296 | { |
260 | static struct notifier_block xenstore_notifier = { | 297 | static struct notifier_block xenstore_notifier = { |
261 | .notifier_call = shutdown_event | 298 | .notifier_call = shutdown_event |
@@ -264,5 +301,6 @@ static int __init setup_shutdown_event(void) | |||
264 | 301 | ||
265 | return 0; | 302 | return 0; |
266 | } | 303 | } |
304 | EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); | ||
267 | 305 | ||
268 | subsys_initcall(setup_shutdown_event); | 306 | subsys_initcall(__setup_shutdown_event); |
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c new file mode 100644 index 000000000000..c01b5ddce529 --- /dev/null +++ b/drivers/xen/platform-pci.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /****************************************************************************** | ||
2 | * platform-pci.c | ||
3 | * | ||
4 | * Xen platform PCI device driver | ||
5 | * Copyright (c) 2005, Intel Corporation. | ||
6 | * Copyright (c) 2007, XenSource Inc. | ||
7 | * Copyright (c) 2010, Citrix | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms and conditions of the GNU General Public License, | ||
11 | * version 2, as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
20 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | |||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/pci.h> | ||
29 | |||
30 | #include <xen/platform_pci.h> | ||
31 | #include <xen/grant_table.h> | ||
32 | #include <xen/xenbus.h> | ||
33 | #include <xen/events.h> | ||
34 | #include <xen/hvm.h> | ||
35 | #include <xen/xen-ops.h> | ||
36 | |||
37 | #define DRV_NAME "xen-platform-pci" | ||
38 | |||
39 | MODULE_AUTHOR("ssmith@xensource.com and stefano.stabellini@eu.citrix.com"); | ||
40 | MODULE_DESCRIPTION("Xen platform PCI device"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static unsigned long platform_mmio; | ||
44 | static unsigned long platform_mmio_alloc; | ||
45 | static unsigned long platform_mmiolen; | ||
46 | static uint64_t callback_via; | ||
47 | |||
48 | unsigned long alloc_xen_mmio(unsigned long len) | ||
49 | { | ||
50 | unsigned long addr; | ||
51 | |||
52 | addr = platform_mmio + platform_mmio_alloc; | ||
53 | platform_mmio_alloc += len; | ||
54 | BUG_ON(platform_mmio_alloc > platform_mmiolen); | ||
55 | |||
56 | return addr; | ||
57 | } | ||
58 | |||
59 | static uint64_t get_callback_via(struct pci_dev *pdev) | ||
60 | { | ||
61 | u8 pin; | ||
62 | int irq; | ||
63 | |||
64 | irq = pdev->irq; | ||
65 | if (irq < 16) | ||
66 | return irq; /* ISA IRQ */ | ||
67 | |||
68 | pin = pdev->pin; | ||
69 | |||
70 | /* We don't know the GSI. Specify the PCI INTx line instead. */ | ||
71 | return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */ | ||
72 | ((uint64_t)pci_domain_nr(pdev->bus) << 32) | | ||
73 | ((uint64_t)pdev->bus->number << 16) | | ||
74 | ((uint64_t)(pdev->devfn & 0xff) << 8) | | ||
75 | ((uint64_t)(pin - 1) & 3); | ||
76 | } | ||
77 | |||
78 | static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id) | ||
79 | { | ||
80 | xen_hvm_evtchn_do_upcall(); | ||
81 | return IRQ_HANDLED; | ||
82 | } | ||
83 | |||
84 | static int xen_allocate_irq(struct pci_dev *pdev) | ||
85 | { | ||
86 | return request_irq(pdev->irq, do_hvm_evtchn_intr, | ||
87 | IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, | ||
88 | "xen-platform-pci", pdev); | ||
89 | } | ||
90 | |||
91 | static int platform_pci_resume(struct pci_dev *pdev) | ||
92 | { | ||
93 | int err; | ||
94 | if (xen_have_vector_callback) | ||
95 | return 0; | ||
96 | err = xen_set_callback_via(callback_via); | ||
97 | if (err) { | ||
98 | dev_err(&pdev->dev, "platform_pci_resume failure!\n"); | ||
99 | return err; | ||
100 | } | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int __devinit platform_pci_init(struct pci_dev *pdev, | ||
105 | const struct pci_device_id *ent) | ||
106 | { | ||
107 | int i, ret; | ||
108 | long ioaddr, iolen; | ||
109 | long mmio_addr, mmio_len; | ||
110 | unsigned int max_nr_gframes; | ||
111 | |||
112 | i = pci_enable_device(pdev); | ||
113 | if (i) | ||
114 | return i; | ||
115 | |||
116 | ioaddr = pci_resource_start(pdev, 0); | ||
117 | iolen = pci_resource_len(pdev, 0); | ||
118 | |||
119 | mmio_addr = pci_resource_start(pdev, 1); | ||
120 | mmio_len = pci_resource_len(pdev, 1); | ||
121 | |||
122 | if (mmio_addr == 0 || ioaddr == 0) { | ||
123 | dev_err(&pdev->dev, "no resources found\n"); | ||
124 | ret = -ENOENT; | ||
125 | goto pci_out; | ||
126 | } | ||
127 | |||
128 | if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) { | ||
129 | dev_err(&pdev->dev, "MEM I/O resource 0x%lx @ 0x%lx busy\n", | ||
130 | mmio_addr, mmio_len); | ||
131 | ret = -EBUSY; | ||
132 | goto pci_out; | ||
133 | } | ||
134 | |||
135 | if (request_region(ioaddr, iolen, DRV_NAME) == NULL) { | ||
136 | dev_err(&pdev->dev, "I/O resource 0x%lx @ 0x%lx busy\n", | ||
137 | iolen, ioaddr); | ||
138 | ret = -EBUSY; | ||
139 | goto mem_out; | ||
140 | } | ||
141 | |||
142 | platform_mmio = mmio_addr; | ||
143 | platform_mmiolen = mmio_len; | ||
144 | |||
145 | if (!xen_have_vector_callback) { | ||
146 | ret = xen_allocate_irq(pdev); | ||
147 | if (ret) { | ||
148 | dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); | ||
149 | goto out; | ||
150 | } | ||
151 | callback_via = get_callback_via(pdev); | ||
152 | ret = xen_set_callback_via(callback_via); | ||
153 | if (ret) { | ||
154 | dev_warn(&pdev->dev, "Unable to set the evtchn callback " | ||
155 | "err=%d\n", ret); | ||
156 | goto out; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | max_nr_gframes = gnttab_max_grant_frames(); | ||
161 | xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); | ||
162 | ret = gnttab_init(); | ||
163 | if (ret) | ||
164 | goto out; | ||
165 | xenbus_probe(NULL); | ||
166 | ret = xen_setup_shutdown_event(); | ||
167 | if (ret) | ||
168 | goto out; | ||
169 | return 0; | ||
170 | |||
171 | out: | ||
172 | release_region(ioaddr, iolen); | ||
173 | mem_out: | ||
174 | release_mem_region(mmio_addr, mmio_len); | ||
175 | pci_out: | ||
176 | pci_disable_device(pdev); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static struct pci_device_id platform_pci_tbl[] __devinitdata = { | ||
181 | {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM, | ||
182 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
183 | {0,} | ||
184 | }; | ||
185 | |||
186 | MODULE_DEVICE_TABLE(pci, platform_pci_tbl); | ||
187 | |||
188 | static struct pci_driver platform_driver = { | ||
189 | .name = DRV_NAME, | ||
190 | .probe = platform_pci_init, | ||
191 | .id_table = platform_pci_tbl, | ||
192 | #ifdef CONFIG_PM | ||
193 | .resume_early = platform_pci_resume, | ||
194 | #endif | ||
195 | }; | ||
196 | |||
197 | static int __init platform_pci_module_init(void) | ||
198 | { | ||
199 | /* no unplug has been done, IGNORE hasn't been specified: just | ||
200 | * return now */ | ||
201 | if (!xen_platform_pci_unplug) | ||
202 | return -ENODEV; | ||
203 | |||
204 | return pci_register_driver(&platform_driver); | ||
205 | } | ||
206 | |||
207 | module_init(platform_pci_module_init); | ||
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 3479332113e9..29bac5118877 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c | |||
@@ -56,6 +56,9 @@ | |||
56 | #include <xen/events.h> | 56 | #include <xen/events.h> |
57 | #include <xen/page.h> | 57 | #include <xen/page.h> |
58 | 58 | ||
59 | #include <xen/platform_pci.h> | ||
60 | #include <xen/hvm.h> | ||
61 | |||
59 | #include "xenbus_comms.h" | 62 | #include "xenbus_comms.h" |
60 | #include "xenbus_probe.h" | 63 | #include "xenbus_probe.h" |
61 | 64 | ||
@@ -752,10 +755,7 @@ int register_xenstore_notifier(struct notifier_block *nb) | |||
752 | { | 755 | { |
753 | int ret = 0; | 756 | int ret = 0; |
754 | 757 | ||
755 | if (xenstored_ready > 0) | 758 | blocking_notifier_chain_register(&xenstore_chain, nb); |
756 | ret = nb->notifier_call(nb, 0, NULL); | ||
757 | else | ||
758 | blocking_notifier_chain_register(&xenstore_chain, nb); | ||
759 | 759 | ||
760 | return ret; | 760 | return ret; |
761 | } | 761 | } |
@@ -779,8 +779,23 @@ void xenbus_probe(struct work_struct *unused) | |||
779 | /* Notify others that xenstore is up */ | 779 | /* Notify others that xenstore is up */ |
780 | blocking_notifier_call_chain(&xenstore_chain, 0, NULL); | 780 | blocking_notifier_call_chain(&xenstore_chain, 0, NULL); |
781 | } | 781 | } |
782 | EXPORT_SYMBOL_GPL(xenbus_probe); | ||
783 | |||
784 | static int __init xenbus_probe_initcall(void) | ||
785 | { | ||
786 | if (!xen_domain()) | ||
787 | return -ENODEV; | ||
788 | |||
789 | if (xen_initial_domain() || xen_hvm_domain()) | ||
790 | return 0; | ||
791 | |||
792 | xenbus_probe(NULL); | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | device_initcall(xenbus_probe_initcall); | ||
782 | 797 | ||
783 | static int __init xenbus_probe_init(void) | 798 | static int __init xenbus_init(void) |
784 | { | 799 | { |
785 | int err = 0; | 800 | int err = 0; |
786 | 801 | ||
@@ -805,11 +820,24 @@ static int __init xenbus_probe_init(void) | |||
805 | if (xen_initial_domain()) { | 820 | if (xen_initial_domain()) { |
806 | /* dom0 not yet supported */ | 821 | /* dom0 not yet supported */ |
807 | } else { | 822 | } else { |
823 | if (xen_hvm_domain()) { | ||
824 | uint64_t v = 0; | ||
825 | err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); | ||
826 | if (err) | ||
827 | goto out_error; | ||
828 | xen_store_evtchn = (int)v; | ||
829 | err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); | ||
830 | if (err) | ||
831 | goto out_error; | ||
832 | xen_store_mfn = (unsigned long)v; | ||
833 | xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); | ||
834 | } else { | ||
835 | xen_store_evtchn = xen_start_info->store_evtchn; | ||
836 | xen_store_mfn = xen_start_info->store_mfn; | ||
837 | xen_store_interface = mfn_to_virt(xen_store_mfn); | ||
838 | } | ||
808 | xenstored_ready = 1; | 839 | xenstored_ready = 1; |
809 | xen_store_evtchn = xen_start_info->store_evtchn; | ||
810 | xen_store_mfn = xen_start_info->store_mfn; | ||
811 | } | 840 | } |
812 | xen_store_interface = mfn_to_virt(xen_store_mfn); | ||
813 | 841 | ||
814 | /* Initialize the interface to xenstore. */ | 842 | /* Initialize the interface to xenstore. */ |
815 | err = xs_init(); | 843 | err = xs_init(); |
@@ -819,9 +847,6 @@ static int __init xenbus_probe_init(void) | |||
819 | goto out_unreg_back; | 847 | goto out_unreg_back; |
820 | } | 848 | } |
821 | 849 | ||
822 | if (!xen_initial_domain()) | ||
823 | xenbus_probe(NULL); | ||
824 | |||
825 | #ifdef CONFIG_XEN_COMPAT_XENFS | 850 | #ifdef CONFIG_XEN_COMPAT_XENFS |
826 | /* | 851 | /* |
827 | * Create xenfs mountpoint in /proc for compatibility with | 852 | * Create xenfs mountpoint in /proc for compatibility with |
@@ -842,7 +867,7 @@ static int __init xenbus_probe_init(void) | |||
842 | return err; | 867 | return err; |
843 | } | 868 | } |
844 | 869 | ||
845 | postcore_initcall(xenbus_probe_init); | 870 | postcore_initcall(xenbus_init); |
846 | 871 | ||
847 | MODULE_LICENSE("GPL"); | 872 | MODULE_LICENSE("GPL"); |
848 | 873 | ||
@@ -950,6 +975,9 @@ static void wait_for_devices(struct xenbus_driver *xendrv) | |||
950 | #ifndef MODULE | 975 | #ifndef MODULE |
951 | static int __init boot_wait_for_devices(void) | 976 | static int __init boot_wait_for_devices(void) |
952 | { | 977 | { |
978 | if (xen_hvm_domain() && !xen_platform_pci_unplug) | ||
979 | return -ENODEV; | ||
980 | |||
953 | ready_to_wait_for_devices = 1; | 981 | ready_to_wait_for_devices = 1; |
954 | wait_for_devices(NULL); | 982 | wait_for_devices(NULL); |
955 | return 0; | 983 | return 0; |
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 7b547f53f65e..5534690075af 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c | |||
@@ -76,6 +76,14 @@ struct xs_handle { | |||
76 | /* | 76 | /* |
77 | * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex. | 77 | * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex. |
78 | * response_mutex is never taken simultaneously with the other three. | 78 | * response_mutex is never taken simultaneously with the other three. |
79 | * | ||
80 | * transaction_mutex must be held before incrementing | ||
81 | * transaction_count. The mutex is held when a suspend is in | ||
82 | * progress to prevent new transactions starting. | ||
83 | * | ||
84 | * When decrementing transaction_count to zero the wait queue | ||
85 | * should be woken up, the suspend code waits for count to | ||
86 | * reach zero. | ||
79 | */ | 87 | */ |
80 | 88 | ||
81 | /* One request at a time. */ | 89 | /* One request at a time. */ |
@@ -85,7 +93,9 @@ struct xs_handle { | |||
85 | struct mutex response_mutex; | 93 | struct mutex response_mutex; |
86 | 94 | ||
87 | /* Protect transactions against save/restore. */ | 95 | /* Protect transactions against save/restore. */ |
88 | struct rw_semaphore transaction_mutex; | 96 | struct mutex transaction_mutex; |
97 | atomic_t transaction_count; | ||
98 | wait_queue_head_t transaction_wq; | ||
89 | 99 | ||
90 | /* Protect watch (de)register against save/restore. */ | 100 | /* Protect watch (de)register against save/restore. */ |
91 | struct rw_semaphore watch_mutex; | 101 | struct rw_semaphore watch_mutex; |
@@ -157,6 +167,31 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) | |||
157 | return body; | 167 | return body; |
158 | } | 168 | } |
159 | 169 | ||
170 | static void transaction_start(void) | ||
171 | { | ||
172 | mutex_lock(&xs_state.transaction_mutex); | ||
173 | atomic_inc(&xs_state.transaction_count); | ||
174 | mutex_unlock(&xs_state.transaction_mutex); | ||
175 | } | ||
176 | |||
177 | static void transaction_end(void) | ||
178 | { | ||
179 | if (atomic_dec_and_test(&xs_state.transaction_count)) | ||
180 | wake_up(&xs_state.transaction_wq); | ||
181 | } | ||
182 | |||
183 | static void transaction_suspend(void) | ||
184 | { | ||
185 | mutex_lock(&xs_state.transaction_mutex); | ||
186 | wait_event(xs_state.transaction_wq, | ||
187 | atomic_read(&xs_state.transaction_count) == 0); | ||
188 | } | ||
189 | |||
190 | static void transaction_resume(void) | ||
191 | { | ||
192 | mutex_unlock(&xs_state.transaction_mutex); | ||
193 | } | ||
194 | |||
160 | void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) | 195 | void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) |
161 | { | 196 | { |
162 | void *ret; | 197 | void *ret; |
@@ -164,7 +199,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) | |||
164 | int err; | 199 | int err; |
165 | 200 | ||
166 | if (req_msg.type == XS_TRANSACTION_START) | 201 | if (req_msg.type == XS_TRANSACTION_START) |
167 | down_read(&xs_state.transaction_mutex); | 202 | transaction_start(); |
168 | 203 | ||
169 | mutex_lock(&xs_state.request_mutex); | 204 | mutex_lock(&xs_state.request_mutex); |
170 | 205 | ||
@@ -180,7 +215,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) | |||
180 | if ((msg->type == XS_TRANSACTION_END) || | 215 | if ((msg->type == XS_TRANSACTION_END) || |
181 | ((req_msg.type == XS_TRANSACTION_START) && | 216 | ((req_msg.type == XS_TRANSACTION_START) && |
182 | (msg->type == XS_ERROR))) | 217 | (msg->type == XS_ERROR))) |
183 | up_read(&xs_state.transaction_mutex); | 218 | transaction_end(); |
184 | 219 | ||
185 | return ret; | 220 | return ret; |
186 | } | 221 | } |
@@ -432,11 +467,11 @@ int xenbus_transaction_start(struct xenbus_transaction *t) | |||
432 | { | 467 | { |
433 | char *id_str; | 468 | char *id_str; |
434 | 469 | ||
435 | down_read(&xs_state.transaction_mutex); | 470 | transaction_start(); |
436 | 471 | ||
437 | id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); | 472 | id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); |
438 | if (IS_ERR(id_str)) { | 473 | if (IS_ERR(id_str)) { |
439 | up_read(&xs_state.transaction_mutex); | 474 | transaction_end(); |
440 | return PTR_ERR(id_str); | 475 | return PTR_ERR(id_str); |
441 | } | 476 | } |
442 | 477 | ||
@@ -461,7 +496,7 @@ int xenbus_transaction_end(struct xenbus_transaction t, int abort) | |||
461 | 496 | ||
462 | err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); | 497 | err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); |
463 | 498 | ||
464 | up_read(&xs_state.transaction_mutex); | 499 | transaction_end(); |
465 | 500 | ||
466 | return err; | 501 | return err; |
467 | } | 502 | } |
@@ -662,7 +697,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watch); | |||
662 | 697 | ||
663 | void xs_suspend(void) | 698 | void xs_suspend(void) |
664 | { | 699 | { |
665 | down_write(&xs_state.transaction_mutex); | 700 | transaction_suspend(); |
666 | down_write(&xs_state.watch_mutex); | 701 | down_write(&xs_state.watch_mutex); |
667 | mutex_lock(&xs_state.request_mutex); | 702 | mutex_lock(&xs_state.request_mutex); |
668 | mutex_lock(&xs_state.response_mutex); | 703 | mutex_lock(&xs_state.response_mutex); |
@@ -677,7 +712,7 @@ void xs_resume(void) | |||
677 | 712 | ||
678 | mutex_unlock(&xs_state.response_mutex); | 713 | mutex_unlock(&xs_state.response_mutex); |
679 | mutex_unlock(&xs_state.request_mutex); | 714 | mutex_unlock(&xs_state.request_mutex); |
680 | up_write(&xs_state.transaction_mutex); | 715 | transaction_resume(); |
681 | 716 | ||
682 | /* No need for watches_lock: the watch_mutex is sufficient. */ | 717 | /* No need for watches_lock: the watch_mutex is sufficient. */ |
683 | list_for_each_entry(watch, &watches, list) { | 718 | list_for_each_entry(watch, &watches, list) { |
@@ -693,7 +728,7 @@ void xs_suspend_cancel(void) | |||
693 | mutex_unlock(&xs_state.response_mutex); | 728 | mutex_unlock(&xs_state.response_mutex); |
694 | mutex_unlock(&xs_state.request_mutex); | 729 | mutex_unlock(&xs_state.request_mutex); |
695 | up_write(&xs_state.watch_mutex); | 730 | up_write(&xs_state.watch_mutex); |
696 | up_write(&xs_state.transaction_mutex); | 731 | mutex_unlock(&xs_state.transaction_mutex); |
697 | } | 732 | } |
698 | 733 | ||
699 | static int xenwatch_thread(void *unused) | 734 | static int xenwatch_thread(void *unused) |
@@ -843,8 +878,10 @@ int xs_init(void) | |||
843 | 878 | ||
844 | mutex_init(&xs_state.request_mutex); | 879 | mutex_init(&xs_state.request_mutex); |
845 | mutex_init(&xs_state.response_mutex); | 880 | mutex_init(&xs_state.response_mutex); |
846 | init_rwsem(&xs_state.transaction_mutex); | 881 | mutex_init(&xs_state.transaction_mutex); |
847 | init_rwsem(&xs_state.watch_mutex); | 882 | init_rwsem(&xs_state.watch_mutex); |
883 | atomic_set(&xs_state.transaction_count, 0); | ||
884 | init_waitqueue_head(&xs_state.transaction_wq); | ||
848 | 885 | ||
849 | /* Initialize the shared memory rings to talk to xenstored */ | 886 | /* Initialize the shared memory rings to talk to xenstored */ |
850 | err = xb_init_comms(); | 887 | err = xb_init_comms(); |
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index 8924d93136f1..78bfab0700ba 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c | |||
@@ -65,7 +65,7 @@ static struct file_system_type xenfs_type = { | |||
65 | 65 | ||
66 | static int __init xenfs_init(void) | 66 | static int __init xenfs_init(void) |
67 | { | 67 | { |
68 | if (xen_pv_domain()) | 68 | if (xen_domain()) |
69 | return register_filesystem(&xenfs_type); | 69 | return register_filesystem(&xenfs_type); |
70 | 70 | ||
71 | printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n"); | 71 | printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n"); |
@@ -74,7 +74,7 @@ static int __init xenfs_init(void) | |||
74 | 74 | ||
75 | static void __exit xenfs_exit(void) | 75 | static void __exit xenfs_exit(void) |
76 | { | 76 | { |
77 | if (xen_pv_domain()) | 77 | if (xen_domain()) |
78 | unregister_filesystem(&xenfs_type); | 78 | unregister_filesystem(&xenfs_type); |
79 | } | 79 | } |
80 | 80 | ||
diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c index f28ece397361..3b39c3752e21 100644 --- a/drivers/xen/xenfs/xenbus.c +++ b/drivers/xen/xenfs/xenbus.c | |||
@@ -124,6 +124,9 @@ static ssize_t xenbus_file_read(struct file *filp, | |||
124 | mutex_lock(&u->reply_mutex); | 124 | mutex_lock(&u->reply_mutex); |
125 | while (list_empty(&u->read_buffers)) { | 125 | while (list_empty(&u->read_buffers)) { |
126 | mutex_unlock(&u->reply_mutex); | 126 | mutex_unlock(&u->reply_mutex); |
127 | if (filp->f_flags & O_NONBLOCK) | ||
128 | return -EAGAIN; | ||
129 | |||
127 | ret = wait_event_interruptible(u->read_waitq, | 130 | ret = wait_event_interruptible(u->read_waitq, |
128 | !list_empty(&u->read_buffers)); | 131 | !list_empty(&u->read_buffers)); |
129 | if (ret) | 132 | if (ret) |