diff options
Diffstat (limited to 'arch/x86')
| -rw-r--r-- | arch/x86/Kconfig | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/entry_arch.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/hardirq.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/hw_irq.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/irq_vectors.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 19 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/irq.c | 8 | ||||
| -rw-r--r-- | arch/x86/kernel/irq_work.c | 30 | ||||
| -rw-r--r-- | arch/x86/kernel/irqinit.c | 6 |
11 files changed, 48 insertions, 35 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9815221976a7..fd227d6b8d9c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -25,6 +25,7 @@ config X86 | |||
| 25 | select HAVE_IDE | 25 | select HAVE_IDE |
| 26 | select HAVE_OPROFILE | 26 | select HAVE_OPROFILE |
| 27 | select HAVE_PERF_EVENTS if (!M386 && !M486) | 27 | select HAVE_PERF_EVENTS if (!M386 && !M486) |
| 28 | select HAVE_IRQ_WORK | ||
| 28 | select HAVE_IOREMAP_PROT | 29 | select HAVE_IOREMAP_PROT |
| 29 | select HAVE_KPROBES | 30 | select HAVE_KPROBES |
| 30 | select ARCH_WANT_OPTIONAL_GPIOLIB | 31 | select ARCH_WANT_OPTIONAL_GPIOLIB |
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index 8e8ec663a98f..b8e96a18676b 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
| @@ -49,8 +49,8 @@ BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR) | |||
| 49 | BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) | 49 | BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) |
| 50 | BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) | 50 | BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) |
| 51 | 51 | ||
| 52 | #ifdef CONFIG_PERF_EVENTS | 52 | #ifdef CONFIG_IRQ_WORK |
| 53 | BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR) | 53 | BUILD_INTERRUPT(irq_work_interrupt, IRQ_WORK_VECTOR) |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| 56 | #ifdef CONFIG_X86_THERMAL_VECTOR | 56 | #ifdef CONFIG_X86_THERMAL_VECTOR |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index aeab29aee617..55e4de613f0e 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
| @@ -14,7 +14,7 @@ typedef struct { | |||
| 14 | #endif | 14 | #endif |
| 15 | unsigned int x86_platform_ipis; /* arch dependent */ | 15 | unsigned int x86_platform_ipis; /* arch dependent */ |
| 16 | unsigned int apic_perf_irqs; | 16 | unsigned int apic_perf_irqs; |
| 17 | unsigned int apic_pending_irqs; | 17 | unsigned int apic_irq_work_irqs; |
| 18 | #ifdef CONFIG_SMP | 18 | #ifdef CONFIG_SMP |
| 19 | unsigned int irq_resched_count; | 19 | unsigned int irq_resched_count; |
| 20 | unsigned int irq_call_count; | 20 | unsigned int irq_call_count; |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 46c0fe05f230..3a54a1ca1a02 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | extern void apic_timer_interrupt(void); | 29 | extern void apic_timer_interrupt(void); |
| 30 | extern void x86_platform_ipi(void); | 30 | extern void x86_platform_ipi(void); |
| 31 | extern void error_interrupt(void); | 31 | extern void error_interrupt(void); |
| 32 | extern void perf_pending_interrupt(void); | 32 | extern void irq_work_interrupt(void); |
| 33 | 33 | ||
| 34 | extern void spurious_interrupt(void); | 34 | extern void spurious_interrupt(void); |
| 35 | extern void thermal_interrupt(void); | 35 | extern void thermal_interrupt(void); |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index e2ca30092557..6af0894dafb4 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
| @@ -114,9 +114,9 @@ | |||
| 114 | #define X86_PLATFORM_IPI_VECTOR 0xed | 114 | #define X86_PLATFORM_IPI_VECTOR 0xed |
| 115 | 115 | ||
| 116 | /* | 116 | /* |
| 117 | * Performance monitoring pending work vector: | 117 | * IRQ work vector: |
| 118 | */ | 118 | */ |
| 119 | #define LOCAL_PENDING_VECTOR 0xec | 119 | #define IRQ_WORK_VECTOR 0xec |
| 120 | 120 | ||
| 121 | #define UV_BAU_MESSAGE 0xea | 121 | #define UV_BAU_MESSAGE 0xea |
| 122 | 122 | ||
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9d3f485e5dd0..7490bf8d1459 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -35,6 +35,7 @@ obj-y := process_$(BITS).o signal.o entry_$(BITS).o | |||
| 35 | obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o | 35 | obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o |
| 36 | obj-y += time.o ioport.o ldt.o dumpstack.o | 36 | obj-y += time.o ioport.o ldt.o dumpstack.o |
| 37 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o | 37 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o |
| 38 | obj-$(CONFIG_IRQ_WORK) += irq_work.o | ||
| 38 | obj-$(CONFIG_X86_VISWS) += visws_quirks.o | 39 | obj-$(CONFIG_X86_VISWS) += visws_quirks.o |
| 39 | obj-$(CONFIG_X86_32) += probe_roms_32.o | 40 | obj-$(CONFIG_X86_32) += probe_roms_32.o |
| 40 | obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o | 41 | obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e2513f26ba8b..fe73c1844a9a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -1196,25 +1196,6 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
| 1196 | return handled; | 1196 | return handled; |
| 1197 | } | 1197 | } |
| 1198 | 1198 | ||
| 1199 | void smp_perf_pending_interrupt(struct pt_regs *regs) | ||
| 1200 | { | ||
| 1201 | irq_enter(); | ||
| 1202 | ack_APIC_irq(); | ||
| 1203 | inc_irq_stat(apic_pending_irqs); | ||
| 1204 | perf_event_do_pending(); | ||
| 1205 | irq_exit(); | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | void set_perf_event_pending(void) | ||
| 1209 | { | ||
| 1210 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 1211 | if (!x86_pmu.apic || !x86_pmu_initialized()) | ||
| 1212 | return; | ||
| 1213 | |||
| 1214 | apic->send_IPI_self(LOCAL_PENDING_VECTOR); | ||
| 1215 | #endif | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | void perf_events_lapic_init(void) | 1199 | void perf_events_lapic_init(void) |
| 1219 | { | 1200 | { |
| 1220 | if (!x86_pmu.apic || !x86_pmu_initialized()) | 1201 | if (!x86_pmu.apic || !x86_pmu_initialized()) |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 17be5ec7cbba..c375c79065f8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -1023,9 +1023,9 @@ apicinterrupt ERROR_APIC_VECTOR \ | |||
| 1023 | apicinterrupt SPURIOUS_APIC_VECTOR \ | 1023 | apicinterrupt SPURIOUS_APIC_VECTOR \ |
| 1024 | spurious_interrupt smp_spurious_interrupt | 1024 | spurious_interrupt smp_spurious_interrupt |
| 1025 | 1025 | ||
| 1026 | #ifdef CONFIG_PERF_EVENTS | 1026 | #ifdef CONFIG_IRQ_WORK |
| 1027 | apicinterrupt LOCAL_PENDING_VECTOR \ | 1027 | apicinterrupt IRQ_WORK_VECTOR \ |
| 1028 | perf_pending_interrupt smp_perf_pending_interrupt | 1028 | irq_work_interrupt smp_irq_work_interrupt |
| 1029 | #endif | 1029 | #endif |
| 1030 | 1030 | ||
| 1031 | /* | 1031 | /* |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 91fd0c70a18a..44edb03fc9ec 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
| @@ -67,10 +67,10 @@ static int show_other_interrupts(struct seq_file *p, int prec) | |||
| 67 | for_each_online_cpu(j) | 67 | for_each_online_cpu(j) |
| 68 | seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); | 68 | seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); |
| 69 | seq_printf(p, " Performance monitoring interrupts\n"); | 69 | seq_printf(p, " Performance monitoring interrupts\n"); |
| 70 | seq_printf(p, "%*s: ", prec, "PND"); | 70 | seq_printf(p, "%*s: ", prec, "IWI"); |
| 71 | for_each_online_cpu(j) | 71 | for_each_online_cpu(j) |
| 72 | seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs); | 72 | seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs); |
| 73 | seq_printf(p, " Performance pending work\n"); | 73 | seq_printf(p, " IRQ work interrupts\n"); |
| 74 | #endif | 74 | #endif |
| 75 | if (x86_platform_ipi_callback) { | 75 | if (x86_platform_ipi_callback) { |
| 76 | seq_printf(p, "%*s: ", prec, "PLT"); | 76 | seq_printf(p, "%*s: ", prec, "PLT"); |
| @@ -185,7 +185,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
| 185 | sum += irq_stats(cpu)->apic_timer_irqs; | 185 | sum += irq_stats(cpu)->apic_timer_irqs; |
| 186 | sum += irq_stats(cpu)->irq_spurious_count; | 186 | sum += irq_stats(cpu)->irq_spurious_count; |
| 187 | sum += irq_stats(cpu)->apic_perf_irqs; | 187 | sum += irq_stats(cpu)->apic_perf_irqs; |
| 188 | sum += irq_stats(cpu)->apic_pending_irqs; | 188 | sum += irq_stats(cpu)->apic_irq_work_irqs; |
| 189 | #endif | 189 | #endif |
| 190 | if (x86_platform_ipi_callback) | 190 | if (x86_platform_ipi_callback) |
| 191 | sum += irq_stats(cpu)->x86_platform_ipis; | 191 | sum += irq_stats(cpu)->x86_platform_ipis; |
diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c new file mode 100644 index 000000000000..ca8f703a1e70 --- /dev/null +++ b/arch/x86/kernel/irq_work.c | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * x86 specific code for irq_work | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/kernel.h> | ||
| 8 | #include <linux/irq_work.h> | ||
| 9 | #include <linux/hardirq.h> | ||
| 10 | #include <asm/apic.h> | ||
| 11 | |||
| 12 | void smp_irq_work_interrupt(struct pt_regs *regs) | ||
| 13 | { | ||
| 14 | irq_enter(); | ||
| 15 | ack_APIC_irq(); | ||
| 16 | inc_irq_stat(apic_irq_work_irqs); | ||
| 17 | irq_work_run(); | ||
| 18 | irq_exit(); | ||
| 19 | } | ||
| 20 | |||
| 21 | void arch_irq_work_raise(void) | ||
| 22 | { | ||
| 23 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 24 | if (!cpu_has_apic) | ||
| 25 | return; | ||
| 26 | |||
| 27 | apic->send_IPI_self(IRQ_WORK_VECTOR); | ||
| 28 | apic_wait_icr_idle(); | ||
| 29 | #endif | ||
| 30 | } | ||
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 990ae7cfc578..713969b9266b 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
| @@ -224,9 +224,9 @@ static void __init apic_intr_init(void) | |||
| 224 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 224 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
| 225 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 225 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
| 226 | 226 | ||
| 227 | /* Performance monitoring interrupts: */ | 227 | /* IRQ work interrupts: */ |
| 228 | # ifdef CONFIG_PERF_EVENTS | 228 | # ifdef CONFIG_IRQ_WORK |
| 229 | alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt); | 229 | alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt); |
| 230 | # endif | 230 | # endif |
| 231 | 231 | ||
| 232 | #endif | 232 | #endif |
