diff options
author | Lin Ming <mlin@ss.pku.edu.cn> | 2012-04-20 12:11:05 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-05-07 15:33:17 -0400 |
commit | 1ff2b0c303698e486f1e0886b4d9876200ef8ca5 (patch) | |
tree | 1579c2602ac178460697dbb44e547b86a8ae1cfe /arch/x86/xen | |
parent | f447d56d36af18c5104ff29dcb1327c0c0ac3634 (diff) |
xen: implement IRQ_WORK_VECTOR handler
Signed-off-by: Lin Ming <mlin@ss.pku.edu.cn>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/smp.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 2dc6628c1520..3ec3f8eb19fc 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/irq_work.h> | ||
19 | 20 | ||
20 | #include <asm/paravirt.h> | 21 | #include <asm/paravirt.h> |
21 | #include <asm/desc.h> | 22 | #include <asm/desc.h> |
@@ -41,10 +42,12 @@ cpumask_var_t xen_cpu_initialized_map; | |||
41 | static DEFINE_PER_CPU(int, xen_resched_irq); | 42 | static DEFINE_PER_CPU(int, xen_resched_irq); |
42 | static DEFINE_PER_CPU(int, xen_callfunc_irq); | 43 | static DEFINE_PER_CPU(int, xen_callfunc_irq); |
43 | static DEFINE_PER_CPU(int, xen_callfuncsingle_irq); | 44 | static DEFINE_PER_CPU(int, xen_callfuncsingle_irq); |
45 | static DEFINE_PER_CPU(int, xen_irq_work); | ||
44 | static DEFINE_PER_CPU(int, xen_debug_irq) = -1; | 46 | static DEFINE_PER_CPU(int, xen_debug_irq) = -1; |
45 | 47 | ||
46 | static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id); | 48 | static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id); |
47 | static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id); | 49 | static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id); |
50 | static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id); | ||
48 | 51 | ||
49 | /* | 52 | /* |
50 | * Reschedule call back. | 53 | * Reschedule call back. |
@@ -143,6 +146,17 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
143 | goto fail; | 146 | goto fail; |
144 | per_cpu(xen_callfuncsingle_irq, cpu) = rc; | 147 | per_cpu(xen_callfuncsingle_irq, cpu) = rc; |
145 | 148 | ||
149 | callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu); | ||
150 | rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, | ||
151 | cpu, | ||
152 | xen_irq_work_interrupt, | ||
153 | IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, | ||
154 | callfunc_name, | ||
155 | NULL); | ||
156 | if (rc < 0) | ||
157 | goto fail; | ||
158 | per_cpu(xen_irq_work, cpu) = rc; | ||
159 | |||
146 | return 0; | 160 | return 0; |
147 | 161 | ||
148 | fail: | 162 | fail: |
@@ -155,6 +169,8 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
155 | if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0) | 169 | if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0) |
156 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), | 170 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), |
157 | NULL); | 171 | NULL); |
172 | if (per_cpu(xen_irq_work, cpu) >= 0) | ||
173 | unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); | ||
158 | 174 | ||
159 | return rc; | 175 | return rc; |
160 | } | 176 | } |
@@ -509,6 +525,9 @@ static inline int xen_map_vector(int vector) | |||
509 | case CALL_FUNCTION_SINGLE_VECTOR: | 525 | case CALL_FUNCTION_SINGLE_VECTOR: |
510 | xen_vector = XEN_CALL_FUNCTION_SINGLE_VECTOR; | 526 | xen_vector = XEN_CALL_FUNCTION_SINGLE_VECTOR; |
511 | break; | 527 | break; |
528 | case IRQ_WORK_VECTOR: | ||
529 | xen_vector = XEN_IRQ_WORK_VECTOR; | ||
530 | break; | ||
512 | default: | 531 | default: |
513 | xen_vector = -1; | 532 | xen_vector = -1; |
514 | printk(KERN_ERR "xen: vector 0x%x is not implemented\n", | 533 | printk(KERN_ERR "xen: vector 0x%x is not implemented\n", |
@@ -588,6 +607,16 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id) | |||
588 | return IRQ_HANDLED; | 607 | return IRQ_HANDLED; |
589 | } | 608 | } |
590 | 609 | ||
610 | static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id) | ||
611 | { | ||
612 | irq_enter(); | ||
613 | irq_work_run(); | ||
614 | inc_irq_stat(apic_irq_work_irqs); | ||
615 | irq_exit(); | ||
616 | |||
617 | return IRQ_HANDLED; | ||
618 | } | ||
619 | |||
591 | static const struct smp_ops xen_smp_ops __initconst = { | 620 | static const struct smp_ops xen_smp_ops __initconst = { |
592 | .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, | 621 | .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, |
593 | .smp_prepare_cpus = xen_smp_prepare_cpus, | 622 | .smp_prepare_cpus = xen_smp_prepare_cpus, |
@@ -634,6 +663,7 @@ static void xen_hvm_cpu_die(unsigned int cpu) | |||
634 | unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); | 663 | unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); |
635 | unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); | 664 | unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); |
636 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL); | 665 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL); |
666 | unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); | ||
637 | native_cpu_die(cpu); | 667 | native_cpu_die(cpu); |
638 | } | 668 | } |
639 | 669 | ||