diff options
| -rw-r--r-- | arch/arm/mach-ux500/cpu-db8500.c | 35 | ||||
| -rw-r--r-- | arch/arm64/include/asm/cputype.h | 2 | ||||
| -rw-r--r-- | arch/arm64/include/asm/stacktrace.h | 2 | ||||
| -rw-r--r-- | arch/arm64/include/asm/uaccess.h | 12 | ||||
| -rw-r--r-- | arch/arm64/kernel/armv8_deprecated.c | 4 | ||||
| -rw-r--r-- | arch/arm64/kernel/cpufeature.c | 6 | ||||
| -rw-r--r-- | arch/arm64/kernel/perf_event.c | 4 | ||||
| -rw-r--r-- | arch/arm64/kernel/process.c | 11 | ||||
| -rw-r--r-- | arch/arm64/kernel/stacktrace.c | 5 | ||||
| -rw-r--r-- | arch/arm64/kernel/sys_compat.c | 2 | ||||
| -rw-r--r-- | arch/arm64/kernel/time.c | 2 | ||||
| -rw-r--r-- | arch/arm64/kernel/traps.c | 10 | ||||
| -rw-r--r-- | arch/arm64/mm/mmu.c | 10 | ||||
| -rw-r--r-- | drivers/perf/arm_pmu.c | 138 | ||||
| -rw-r--r-- | drivers/perf/arm_pmu_acpi.c | 61 | ||||
| -rw-r--r-- | drivers/perf/arm_pmu_platform.c | 37 | ||||
| -rw-r--r-- | include/linux/perf/arm_pmu.h | 26 |
17 files changed, 183 insertions, 184 deletions
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 57058ac46f49..7e5d7a083707 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 24 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
| 25 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
| 26 | #include <linux/perf/arm_pmu.h> | ||
| 27 | #include <linux/regulator/machine.h> | 26 | #include <linux/regulator/machine.h> |
| 28 | 27 | ||
| 29 | #include <asm/outercache.h> | 28 | #include <asm/outercache.h> |
| @@ -112,37 +111,6 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd) | |||
| 112 | prcmu_system_reset(0); | 111 | prcmu_system_reset(0); |
| 113 | } | 112 | } |
| 114 | 113 | ||
| 115 | /* | ||
| 116 | * The PMU IRQ lines of two cores are wired together into a single interrupt. | ||
| 117 | * Bounce the interrupt to the other core if it's not ours. | ||
| 118 | */ | ||
| 119 | static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) | ||
| 120 | { | ||
| 121 | irqreturn_t ret = handler(irq, dev); | ||
| 122 | int other = !smp_processor_id(); | ||
| 123 | |||
| 124 | if (ret == IRQ_NONE && cpu_online(other)) | ||
| 125 | irq_set_affinity(irq, cpumask_of(other)); | ||
| 126 | |||
| 127 | /* | ||
| 128 | * We should be able to get away with the amount of IRQ_NONEs we give, | ||
| 129 | * while still having the spurious IRQ detection code kick in if the | ||
| 130 | * interrupt really starts hitting spuriously. | ||
| 131 | */ | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | |||
| 135 | static struct arm_pmu_platdata db8500_pmu_platdata = { | ||
| 136 | .handle_irq = db8500_pmu_handler, | ||
| 137 | .irq_flags = IRQF_NOBALANCING | IRQF_NO_THREAD, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { | ||
| 141 | /* Requires call-back bindings. */ | ||
| 142 | OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata), | ||
| 143 | {}, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = { | 114 | static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = { |
| 147 | OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL), | 115 | OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL), |
| 148 | {}, | 116 | {}, |
| @@ -165,9 +133,6 @@ static void __init u8500_init_machine(void) | |||
| 165 | if (of_machine_is_compatible("st-ericsson,u8540")) | 133 | if (of_machine_is_compatible("st-ericsson,u8540")) |
| 166 | of_platform_populate(NULL, u8500_local_bus_nodes, | 134 | of_platform_populate(NULL, u8500_local_bus_nodes, |
| 167 | u8540_auxdata_lookup, NULL); | 135 | u8540_auxdata_lookup, NULL); |
| 168 | else | ||
| 169 | of_platform_populate(NULL, u8500_local_bus_nodes, | ||
| 170 | u8500_auxdata_lookup, NULL); | ||
| 171 | } | 136 | } |
| 172 | 137 | ||
| 173 | static const char * stericsson_dt_platform_compat[] = { | 138 | static const char * stericsson_dt_platform_compat[] = { |
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index eda8c5f629fc..350c76a1d15b 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | #define MPIDR_UP_BITMASK (0x1 << 30) | 21 | #define MPIDR_UP_BITMASK (0x1 << 30) |
| 22 | #define MPIDR_MT_BITMASK (0x1 << 24) | 22 | #define MPIDR_MT_BITMASK (0x1 << 24) |
| 23 | #define MPIDR_HWID_BITMASK 0xff00ffffffUL | 23 | #define MPIDR_HWID_BITMASK UL(0xff00ffffff) |
| 24 | 24 | ||
| 25 | #define MPIDR_LEVEL_BITS_SHIFT 3 | 25 | #define MPIDR_LEVEL_BITS_SHIFT 3 |
| 26 | #define MPIDR_LEVEL_BITS (1 << MPIDR_LEVEL_BITS_SHIFT) | 26 | #define MPIDR_LEVEL_BITS (1 << MPIDR_LEVEL_BITS_SHIFT) |
diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h index 472ef944e932..902f9edacbea 100644 --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h | |||
| @@ -28,7 +28,7 @@ struct stackframe { | |||
| 28 | unsigned long fp; | 28 | unsigned long fp; |
| 29 | unsigned long pc; | 29 | unsigned long pc; |
| 30 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 30 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 31 | unsigned int graph; | 31 | int graph; |
| 32 | #endif | 32 | #endif |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 543e11f0f657..e66b0fca99c2 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h | |||
| @@ -72,15 +72,15 @@ static inline void set_fs(mm_segment_t fs) | |||
| 72 | * This is equivalent to the following test: | 72 | * This is equivalent to the following test: |
| 73 | * (u65)addr + (u65)size <= (u65)current->addr_limit + 1 | 73 | * (u65)addr + (u65)size <= (u65)current->addr_limit + 1 |
| 74 | */ | 74 | */ |
| 75 | static inline unsigned long __range_ok(unsigned long addr, unsigned long size) | 75 | static inline unsigned long __range_ok(const void __user *addr, unsigned long size) |
| 76 | { | 76 | { |
| 77 | unsigned long limit = current_thread_info()->addr_limit; | 77 | unsigned long ret, limit = current_thread_info()->addr_limit; |
| 78 | 78 | ||
| 79 | __chk_user_ptr(addr); | 79 | __chk_user_ptr(addr); |
| 80 | asm volatile( | 80 | asm volatile( |
| 81 | // A + B <= C + 1 for all A,B,C, in four easy steps: | 81 | // A + B <= C + 1 for all A,B,C, in four easy steps: |
| 82 | // 1: X = A + B; X' = X % 2^64 | 82 | // 1: X = A + B; X' = X % 2^64 |
| 83 | " adds %0, %0, %2\n" | 83 | " adds %0, %3, %2\n" |
| 84 | // 2: Set C = 0 if X > 2^64, to guarantee X' > C in step 4 | 84 | // 2: Set C = 0 if X > 2^64, to guarantee X' > C in step 4 |
| 85 | " csel %1, xzr, %1, hi\n" | 85 | " csel %1, xzr, %1, hi\n" |
| 86 | // 3: Set X' = ~0 if X >= 2^64. For X == 2^64, this decrements X' | 86 | // 3: Set X' = ~0 if X >= 2^64. For X == 2^64, this decrements X' |
| @@ -92,9 +92,9 @@ static inline unsigned long __range_ok(unsigned long addr, unsigned long size) | |||
| 92 | // testing X' - C == 0, subject to the previous adjustments. | 92 | // testing X' - C == 0, subject to the previous adjustments. |
| 93 | " sbcs xzr, %0, %1\n" | 93 | " sbcs xzr, %0, %1\n" |
| 94 | " cset %0, ls\n" | 94 | " cset %0, ls\n" |
| 95 | : "+r" (addr), "+r" (limit) : "Ir" (size) : "cc"); | 95 | : "=&r" (ret), "+r" (limit) : "Ir" (size), "0" (addr) : "cc"); |
| 96 | 96 | ||
| 97 | return addr; | 97 | return ret; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | /* | 100 | /* |
| @@ -104,7 +104,7 @@ static inline unsigned long __range_ok(unsigned long addr, unsigned long size) | |||
| 104 | */ | 104 | */ |
| 105 | #define untagged_addr(addr) sign_extend64(addr, 55) | 105 | #define untagged_addr(addr) sign_extend64(addr, 55) |
| 106 | 106 | ||
| 107 | #define access_ok(type, addr, size) __range_ok((unsigned long)(addr), size) | 107 | #define access_ok(type, addr, size) __range_ok(addr, size) |
| 108 | #define user_addr_max get_fs | 108 | #define user_addr_max get_fs |
| 109 | 109 | ||
| 110 | #define _ASM_EXTABLE(from, to) \ | 110 | #define _ASM_EXTABLE(from, to) \ |
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index c33b5e4010ab..68450e954d47 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c | |||
| @@ -370,6 +370,7 @@ static unsigned int __kprobes aarch32_check_condition(u32 opcode, u32 psr) | |||
| 370 | static int swp_handler(struct pt_regs *regs, u32 instr) | 370 | static int swp_handler(struct pt_regs *regs, u32 instr) |
| 371 | { | 371 | { |
| 372 | u32 destreg, data, type, address = 0; | 372 | u32 destreg, data, type, address = 0; |
| 373 | const void __user *user_ptr; | ||
| 373 | int rn, rt2, res = 0; | 374 | int rn, rt2, res = 0; |
| 374 | 375 | ||
| 375 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); | 376 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); |
| @@ -401,7 +402,8 @@ static int swp_handler(struct pt_regs *regs, u32 instr) | |||
| 401 | aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data); | 402 | aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data); |
| 402 | 403 | ||
| 403 | /* Check access in reasonable access range for both SWP and SWPB */ | 404 | /* Check access in reasonable access range for both SWP and SWPB */ |
| 404 | if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) { | 405 | user_ptr = (const void __user *)(unsigned long)(address & ~3); |
| 406 | if (!access_ok(VERIFY_WRITE, user_ptr, 4)) { | ||
| 405 | pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n", | 407 | pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n", |
| 406 | address); | 408 | address); |
| 407 | goto fault; | 409 | goto fault; |
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 29b1f873e337..2985a067fc13 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
| @@ -199,9 +199,11 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { | |||
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | static const struct arm64_ftr_bits ftr_ctr[] = { | 201 | static const struct arm64_ftr_bits ftr_ctr[] = { |
| 202 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RAO */ | 202 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */ |
| 203 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 29, 1, 1), /* DIC */ | ||
| 204 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 28, 1, 1), /* IDC */ | ||
| 203 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ | 205 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ |
| 204 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), /* ERG */ | 206 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 20, 4, 0), /* ERG */ |
| 205 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ | 207 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ |
| 206 | /* | 208 | /* |
| 207 | * Linux can handle differing I-cache policies. Userspace JITs will | 209 | * Linux can handle differing I-cache policies. Userspace JITs will |
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 75b220ba73a3..85a251b6dfa8 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c | |||
| @@ -908,9 +908,9 @@ static void __armv8pmu_probe_pmu(void *info) | |||
| 908 | int pmuver; | 908 | int pmuver; |
| 909 | 909 | ||
| 910 | dfr0 = read_sysreg(id_aa64dfr0_el1); | 910 | dfr0 = read_sysreg(id_aa64dfr0_el1); |
| 911 | pmuver = cpuid_feature_extract_signed_field(dfr0, | 911 | pmuver = cpuid_feature_extract_unsigned_field(dfr0, |
| 912 | ID_AA64DFR0_PMUVER_SHIFT); | 912 | ID_AA64DFR0_PMUVER_SHIFT); |
| 913 | if (pmuver < 1) | 913 | if (pmuver == 0xf || pmuver == 0) |
| 914 | return; | 914 | return; |
| 915 | 915 | ||
| 916 | probe->present = true; | 916 | probe->present = true; |
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index ad8aeb098b31..c0da6efe5465 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c | |||
| @@ -220,8 +220,15 @@ void __show_regs(struct pt_regs *regs) | |||
| 220 | 220 | ||
| 221 | show_regs_print_info(KERN_DEFAULT); | 221 | show_regs_print_info(KERN_DEFAULT); |
| 222 | print_pstate(regs); | 222 | print_pstate(regs); |
| 223 | printk("pc : %pS\n", (void *)regs->pc); | 223 | |
| 224 | printk("lr : %pS\n", (void *)lr); | 224 | if (!user_mode(regs)) { |
| 225 | printk("pc : %pS\n", (void *)regs->pc); | ||
| 226 | printk("lr : %pS\n", (void *)lr); | ||
| 227 | } else { | ||
| 228 | printk("pc : %016llx\n", regs->pc); | ||
| 229 | printk("lr : %016llx\n", lr); | ||
| 230 | } | ||
| 231 | |||
| 225 | printk("sp : %016llx\n", sp); | 232 | printk("sp : %016llx\n", sp); |
| 226 | 233 | ||
| 227 | i = top_reg; | 234 | i = top_reg; |
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index 76809ccd309c..d5718a060672 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c | |||
| @@ -59,6 +59,11 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) | |||
| 59 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 59 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 60 | if (tsk->ret_stack && | 60 | if (tsk->ret_stack && |
| 61 | (frame->pc == (unsigned long)return_to_handler)) { | 61 | (frame->pc == (unsigned long)return_to_handler)) { |
| 62 | if (WARN_ON_ONCE(frame->graph == -1)) | ||
| 63 | return -EINVAL; | ||
| 64 | if (frame->graph < -1) | ||
| 65 | frame->graph += FTRACE_NOTRACE_DEPTH; | ||
| 66 | |||
| 62 | /* | 67 | /* |
| 63 | * This is a case where function graph tracer has | 68 | * This is a case where function graph tracer has |
| 64 | * modified a return address (LR) in a stack frame | 69 | * modified a return address (LR) in a stack frame |
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index 8b8bbd3eaa52..a382b2a1b84e 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c | |||
| @@ -57,7 +57,7 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags) | |||
| 57 | if (end < start || flags) | 57 | if (end < start || flags) |
| 58 | return -EINVAL; | 58 | return -EINVAL; |
| 59 | 59 | ||
| 60 | if (!access_ok(VERIFY_READ, start, end - start)) | 60 | if (!access_ok(VERIFY_READ, (const void __user *)start, end - start)) |
| 61 | return -EFAULT; | 61 | return -EFAULT; |
| 62 | 62 | ||
| 63 | return __do_compat_cache_op(start, end); | 63 | return __do_compat_cache_op(start, end); |
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index a4391280fba9..f258636273c9 100644 --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c | |||
| @@ -52,7 +52,7 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
| 52 | frame.fp = regs->regs[29]; | 52 | frame.fp = regs->regs[29]; |
| 53 | frame.pc = regs->pc; | 53 | frame.pc = regs->pc; |
| 54 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 54 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 55 | frame.graph = -1; /* no task info */ | 55 | frame.graph = current->curr_ret_stack; |
| 56 | #endif | 56 | #endif |
| 57 | do { | 57 | do { |
| 58 | int ret = unwind_frame(NULL, &frame); | 58 | int ret = unwind_frame(NULL, &frame); |
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index bbb0fde2780e..eb2d15147e8d 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
| @@ -57,7 +57,7 @@ static const char *handler[]= { | |||
| 57 | "Error" | 57 | "Error" |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | int show_unhandled_signals = 1; | 60 | int show_unhandled_signals = 0; |
| 61 | 61 | ||
| 62 | static void dump_backtrace_entry(unsigned long where) | 62 | static void dump_backtrace_entry(unsigned long where) |
| 63 | { | 63 | { |
| @@ -526,14 +526,6 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs) | |||
| 526 | } | 526 | } |
| 527 | #endif | 527 | #endif |
| 528 | 528 | ||
| 529 | if (show_unhandled_signals_ratelimited()) { | ||
| 530 | pr_info("%s[%d]: syscall %d\n", current->comm, | ||
| 531 | task_pid_nr(current), regs->syscallno); | ||
| 532 | dump_instr("", regs); | ||
| 533 | if (user_mode(regs)) | ||
| 534 | __show_regs(regs); | ||
| 535 | } | ||
| 536 | |||
| 537 | return sys_ni_syscall(); | 529 | return sys_ni_syscall(); |
| 538 | } | 530 | } |
| 539 | 531 | ||
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 3161b853f29e..84a019f55022 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c | |||
| @@ -933,6 +933,11 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) | |||
| 933 | { | 933 | { |
| 934 | pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | | 934 | pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | |
| 935 | pgprot_val(mk_sect_prot(prot))); | 935 | pgprot_val(mk_sect_prot(prot))); |
| 936 | |||
| 937 | /* ioremap_page_range doesn't honour BBM */ | ||
| 938 | if (pud_present(READ_ONCE(*pudp))) | ||
| 939 | return 0; | ||
| 940 | |||
| 936 | BUG_ON(phys & ~PUD_MASK); | 941 | BUG_ON(phys & ~PUD_MASK); |
| 937 | set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot)); | 942 | set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot)); |
| 938 | return 1; | 943 | return 1; |
| @@ -942,6 +947,11 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) | |||
| 942 | { | 947 | { |
| 943 | pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | | 948 | pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | |
| 944 | pgprot_val(mk_sect_prot(prot))); | 949 | pgprot_val(mk_sect_prot(prot))); |
| 950 | |||
| 951 | /* ioremap_page_range doesn't honour BBM */ | ||
| 952 | if (pmd_present(READ_ONCE(*pmdp))) | ||
| 953 | return 0; | ||
| 954 | |||
| 945 | BUG_ON(phys & ~PMD_MASK); | 955 | BUG_ON(phys & ~PMD_MASK); |
| 946 | set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot)); | 956 | set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot)); |
| 947 | return 1; | 957 | return 1; |
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 7bc5eee96b31..0c2ed11c0603 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/export.h> | 17 | #include <linux/export.h> |
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/perf/arm_pmu.h> | 19 | #include <linux/perf/arm_pmu.h> |
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 22 | #include <linux/sched/clock.h> | 21 | #include <linux/sched/clock.h> |
| 23 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
| @@ -26,6 +25,9 @@ | |||
| 26 | 25 | ||
| 27 | #include <asm/irq_regs.h> | 26 | #include <asm/irq_regs.h> |
| 28 | 27 | ||
| 28 | static DEFINE_PER_CPU(struct arm_pmu *, cpu_armpmu); | ||
| 29 | static DEFINE_PER_CPU(int, cpu_irq); | ||
| 30 | |||
| 29 | static int | 31 | static int |
| 30 | armpmu_map_cache_event(const unsigned (*cache_map) | 32 | armpmu_map_cache_event(const unsigned (*cache_map) |
| 31 | [PERF_COUNT_HW_CACHE_MAX] | 33 | [PERF_COUNT_HW_CACHE_MAX] |
| @@ -320,17 +322,9 @@ validate_group(struct perf_event *event) | |||
| 320 | return 0; | 322 | return 0; |
| 321 | } | 323 | } |
| 322 | 324 | ||
| 323 | static struct arm_pmu_platdata *armpmu_get_platdata(struct arm_pmu *armpmu) | ||
| 324 | { | ||
| 325 | struct platform_device *pdev = armpmu->plat_device; | ||
| 326 | |||
| 327 | return pdev ? dev_get_platdata(&pdev->dev) : NULL; | ||
| 328 | } | ||
| 329 | |||
| 330 | static irqreturn_t armpmu_dispatch_irq(int irq, void *dev) | 325 | static irqreturn_t armpmu_dispatch_irq(int irq, void *dev) |
| 331 | { | 326 | { |
| 332 | struct arm_pmu *armpmu; | 327 | struct arm_pmu *armpmu; |
| 333 | struct arm_pmu_platdata *plat; | ||
| 334 | int ret; | 328 | int ret; |
| 335 | u64 start_clock, finish_clock; | 329 | u64 start_clock, finish_clock; |
| 336 | 330 | ||
| @@ -341,14 +335,11 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev) | |||
| 341 | * dereference. | 335 | * dereference. |
| 342 | */ | 336 | */ |
| 343 | armpmu = *(void **)dev; | 337 | armpmu = *(void **)dev; |
| 344 | 338 | if (WARN_ON_ONCE(!armpmu)) | |
| 345 | plat = armpmu_get_platdata(armpmu); | 339 | return IRQ_NONE; |
| 346 | 340 | ||
| 347 | start_clock = sched_clock(); | 341 | start_clock = sched_clock(); |
| 348 | if (plat && plat->handle_irq) | 342 | ret = armpmu->handle_irq(irq, armpmu); |
| 349 | ret = plat->handle_irq(irq, armpmu, armpmu->handle_irq); | ||
| 350 | else | ||
| 351 | ret = armpmu->handle_irq(irq, armpmu); | ||
| 352 | finish_clock = sched_clock(); | 343 | finish_clock = sched_clock(); |
| 353 | 344 | ||
| 354 | perf_sample_event_took(finish_clock - start_clock); | 345 | perf_sample_event_took(finish_clock - start_clock); |
| @@ -531,54 +522,41 @@ int perf_num_counters(void) | |||
| 531 | } | 522 | } |
| 532 | EXPORT_SYMBOL_GPL(perf_num_counters); | 523 | EXPORT_SYMBOL_GPL(perf_num_counters); |
| 533 | 524 | ||
| 534 | void armpmu_free_irq(struct arm_pmu *armpmu, int cpu) | 525 | static int armpmu_count_irq_users(const int irq) |
| 535 | { | 526 | { |
| 536 | struct pmu_hw_events __percpu *hw_events = armpmu->hw_events; | 527 | int cpu, count = 0; |
| 537 | int irq = per_cpu(hw_events->irq, cpu); | ||
| 538 | 528 | ||
| 539 | if (!cpumask_test_and_clear_cpu(cpu, &armpmu->active_irqs)) | 529 | for_each_possible_cpu(cpu) { |
| 540 | return; | 530 | if (per_cpu(cpu_irq, cpu) == irq) |
| 541 | 531 | count++; | |
| 542 | if (irq_is_percpu_devid(irq)) { | ||
| 543 | free_percpu_irq(irq, &hw_events->percpu_pmu); | ||
| 544 | cpumask_clear(&armpmu->active_irqs); | ||
| 545 | return; | ||
| 546 | } | 532 | } |
| 547 | 533 | ||
| 548 | free_irq(irq, per_cpu_ptr(&hw_events->percpu_pmu, cpu)); | 534 | return count; |
| 549 | } | 535 | } |
| 550 | 536 | ||
| 551 | void armpmu_free_irqs(struct arm_pmu *armpmu) | 537 | void armpmu_free_irq(int irq, int cpu) |
| 552 | { | 538 | { |
| 553 | int cpu; | 539 | if (per_cpu(cpu_irq, cpu) == 0) |
| 540 | return; | ||
| 541 | if (WARN_ON(irq != per_cpu(cpu_irq, cpu))) | ||
| 542 | return; | ||
| 543 | |||
| 544 | if (!irq_is_percpu_devid(irq)) | ||
| 545 | free_irq(irq, per_cpu_ptr(&cpu_armpmu, cpu)); | ||
| 546 | else if (armpmu_count_irq_users(irq) == 1) | ||
| 547 | free_percpu_irq(irq, &cpu_armpmu); | ||
| 554 | 548 | ||
| 555 | for_each_cpu(cpu, &armpmu->supported_cpus) | 549 | per_cpu(cpu_irq, cpu) = 0; |
| 556 | armpmu_free_irq(armpmu, cpu); | ||
| 557 | } | 550 | } |
| 558 | 551 | ||
| 559 | int armpmu_request_irq(struct arm_pmu *armpmu, int cpu) | 552 | int armpmu_request_irq(int irq, int cpu) |
| 560 | { | 553 | { |
| 561 | int err = 0; | 554 | int err = 0; |
| 562 | struct pmu_hw_events __percpu *hw_events = armpmu->hw_events; | ||
| 563 | const irq_handler_t handler = armpmu_dispatch_irq; | 555 | const irq_handler_t handler = armpmu_dispatch_irq; |
| 564 | int irq = per_cpu(hw_events->irq, cpu); | ||
| 565 | if (!irq) | 556 | if (!irq) |
| 566 | return 0; | 557 | return 0; |
| 567 | 558 | ||
| 568 | if (irq_is_percpu_devid(irq) && cpumask_empty(&armpmu->active_irqs)) { | 559 | if (!irq_is_percpu_devid(irq)) { |
| 569 | err = request_percpu_irq(irq, handler, "arm-pmu", | ||
| 570 | &hw_events->percpu_pmu); | ||
| 571 | } else if (irq_is_percpu_devid(irq)) { | ||
| 572 | int other_cpu = cpumask_first(&armpmu->active_irqs); | ||
| 573 | int other_irq = per_cpu(hw_events->irq, other_cpu); | ||
| 574 | |||
| 575 | if (irq != other_irq) { | ||
| 576 | pr_warn("mismatched PPIs detected.\n"); | ||
| 577 | err = -EINVAL; | ||
| 578 | goto err_out; | ||
| 579 | } | ||
| 580 | } else { | ||
| 581 | struct arm_pmu_platdata *platdata = armpmu_get_platdata(armpmu); | ||
| 582 | unsigned long irq_flags; | 560 | unsigned long irq_flags; |
| 583 | 561 | ||
| 584 | err = irq_force_affinity(irq, cpumask_of(cpu)); | 562 | err = irq_force_affinity(irq, cpumask_of(cpu)); |
| @@ -589,22 +567,22 @@ int armpmu_request_irq(struct arm_pmu *armpmu, int cpu) | |||
| 589 | goto err_out; | 567 | goto err_out; |
| 590 | } | 568 | } |
| 591 | 569 | ||
| 592 | if (platdata && platdata->irq_flags) { | 570 | irq_flags = IRQF_PERCPU | |
| 593 | irq_flags = platdata->irq_flags; | 571 | IRQF_NOBALANCING | |
| 594 | } else { | 572 | IRQF_NO_THREAD; |
| 595 | irq_flags = IRQF_PERCPU | | ||
| 596 | IRQF_NOBALANCING | | ||
| 597 | IRQF_NO_THREAD; | ||
| 598 | } | ||
| 599 | 573 | ||
| 574 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
| 600 | err = request_irq(irq, handler, irq_flags, "arm-pmu", | 575 | err = request_irq(irq, handler, irq_flags, "arm-pmu", |
| 601 | per_cpu_ptr(&hw_events->percpu_pmu, cpu)); | 576 | per_cpu_ptr(&cpu_armpmu, cpu)); |
| 577 | } else if (armpmu_count_irq_users(irq) == 0) { | ||
| 578 | err = request_percpu_irq(irq, handler, "arm-pmu", | ||
| 579 | &cpu_armpmu); | ||
| 602 | } | 580 | } |
| 603 | 581 | ||
| 604 | if (err) | 582 | if (err) |
| 605 | goto err_out; | 583 | goto err_out; |
| 606 | 584 | ||
| 607 | cpumask_set_cpu(cpu, &armpmu->active_irqs); | 585 | per_cpu(cpu_irq, cpu) = irq; |
| 608 | return 0; | 586 | return 0; |
| 609 | 587 | ||
| 610 | err_out: | 588 | err_out: |
| @@ -612,19 +590,6 @@ err_out: | |||
| 612 | return err; | 590 | return err; |
| 613 | } | 591 | } |
| 614 | 592 | ||
| 615 | int armpmu_request_irqs(struct arm_pmu *armpmu) | ||
| 616 | { | ||
| 617 | int cpu, err; | ||
| 618 | |||
| 619 | for_each_cpu(cpu, &armpmu->supported_cpus) { | ||
| 620 | err = armpmu_request_irq(armpmu, cpu); | ||
| 621 | if (err) | ||
| 622 | break; | ||
| 623 | } | ||
| 624 | |||
| 625 | return err; | ||
| 626 | } | ||
| 627 | |||
| 628 | static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu) | 593 | static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu) |
| 629 | { | 594 | { |
| 630 | struct pmu_hw_events __percpu *hw_events = pmu->hw_events; | 595 | struct pmu_hw_events __percpu *hw_events = pmu->hw_events; |
| @@ -647,12 +612,14 @@ static int arm_perf_starting_cpu(unsigned int cpu, struct hlist_node *node) | |||
| 647 | if (pmu->reset) | 612 | if (pmu->reset) |
| 648 | pmu->reset(pmu); | 613 | pmu->reset(pmu); |
| 649 | 614 | ||
| 615 | per_cpu(cpu_armpmu, cpu) = pmu; | ||
| 616 | |||
| 650 | irq = armpmu_get_cpu_irq(pmu, cpu); | 617 | irq = armpmu_get_cpu_irq(pmu, cpu); |
| 651 | if (irq) { | 618 | if (irq) { |
| 652 | if (irq_is_percpu_devid(irq)) { | 619 | if (irq_is_percpu_devid(irq)) |
| 653 | enable_percpu_irq(irq, IRQ_TYPE_NONE); | 620 | enable_percpu_irq(irq, IRQ_TYPE_NONE); |
| 654 | return 0; | 621 | else |
| 655 | } | 622 | enable_irq(irq); |
| 656 | } | 623 | } |
| 657 | 624 | ||
| 658 | return 0; | 625 | return 0; |
| @@ -667,8 +634,14 @@ static int arm_perf_teardown_cpu(unsigned int cpu, struct hlist_node *node) | |||
| 667 | return 0; | 634 | return 0; |
| 668 | 635 | ||
| 669 | irq = armpmu_get_cpu_irq(pmu, cpu); | 636 | irq = armpmu_get_cpu_irq(pmu, cpu); |
| 670 | if (irq && irq_is_percpu_devid(irq)) | 637 | if (irq) { |
| 671 | disable_percpu_irq(irq); | 638 | if (irq_is_percpu_devid(irq)) |
| 639 | disable_percpu_irq(irq); | ||
| 640 | else | ||
| 641 | disable_irq(irq); | ||
| 642 | } | ||
| 643 | |||
| 644 | per_cpu(cpu_armpmu, cpu) = NULL; | ||
| 672 | 645 | ||
| 673 | return 0; | 646 | return 0; |
| 674 | } | 647 | } |
| @@ -800,18 +773,18 @@ static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu) | |||
| 800 | &cpu_pmu->node); | 773 | &cpu_pmu->node); |
| 801 | } | 774 | } |
| 802 | 775 | ||
| 803 | struct arm_pmu *armpmu_alloc(void) | 776 | static struct arm_pmu *__armpmu_alloc(gfp_t flags) |
| 804 | { | 777 | { |
| 805 | struct arm_pmu *pmu; | 778 | struct arm_pmu *pmu; |
| 806 | int cpu; | 779 | int cpu; |
| 807 | 780 | ||
| 808 | pmu = kzalloc(sizeof(*pmu), GFP_KERNEL); | 781 | pmu = kzalloc(sizeof(*pmu), flags); |
| 809 | if (!pmu) { | 782 | if (!pmu) { |
| 810 | pr_info("failed to allocate PMU device!\n"); | 783 | pr_info("failed to allocate PMU device!\n"); |
| 811 | goto out; | 784 | goto out; |
| 812 | } | 785 | } |
| 813 | 786 | ||
| 814 | pmu->hw_events = alloc_percpu(struct pmu_hw_events); | 787 | pmu->hw_events = alloc_percpu_gfp(struct pmu_hw_events, flags); |
| 815 | if (!pmu->hw_events) { | 788 | if (!pmu->hw_events) { |
| 816 | pr_info("failed to allocate per-cpu PMU data.\n"); | 789 | pr_info("failed to allocate per-cpu PMU data.\n"); |
| 817 | goto out_free_pmu; | 790 | goto out_free_pmu; |
| @@ -857,6 +830,17 @@ out: | |||
| 857 | return NULL; | 830 | return NULL; |
| 858 | } | 831 | } |
| 859 | 832 | ||
| 833 | struct arm_pmu *armpmu_alloc(void) | ||
| 834 | { | ||
| 835 | return __armpmu_alloc(GFP_KERNEL); | ||
| 836 | } | ||
| 837 | |||
| 838 | struct arm_pmu *armpmu_alloc_atomic(void) | ||
| 839 | { | ||
| 840 | return __armpmu_alloc(GFP_ATOMIC); | ||
| 841 | } | ||
| 842 | |||
| 843 | |||
| 860 | void armpmu_free(struct arm_pmu *pmu) | 844 | void armpmu_free(struct arm_pmu *pmu) |
| 861 | { | 845 | { |
| 862 | free_percpu(pmu->hw_events); | 846 | free_percpu(pmu->hw_events); |
diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c index 705f1a390e31..0f197516d708 100644 --- a/drivers/perf/arm_pmu_acpi.c +++ b/drivers/perf/arm_pmu_acpi.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
| 12 | #include <linux/cpumask.h> | 12 | #include <linux/cpumask.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/irq.h> | ||
| 15 | #include <linux/irqdesc.h> | ||
| 14 | #include <linux/percpu.h> | 16 | #include <linux/percpu.h> |
| 15 | #include <linux/perf/arm_pmu.h> | 17 | #include <linux/perf/arm_pmu.h> |
| 16 | 18 | ||
| @@ -87,7 +89,13 @@ static int arm_pmu_acpi_parse_irqs(void) | |||
| 87 | pr_warn("No ACPI PMU IRQ for CPU%d\n", cpu); | 89 | pr_warn("No ACPI PMU IRQ for CPU%d\n", cpu); |
| 88 | } | 90 | } |
| 89 | 91 | ||
| 92 | /* | ||
| 93 | * Log and request the IRQ so the core arm_pmu code can manage | ||
| 94 | * it. We'll have to sanity-check IRQs later when we associate | ||
| 95 | * them with their PMUs. | ||
| 96 | */ | ||
| 90 | per_cpu(pmu_irqs, cpu) = irq; | 97 | per_cpu(pmu_irqs, cpu) = irq; |
| 98 | armpmu_request_irq(irq, cpu); | ||
| 91 | } | 99 | } |
| 92 | 100 | ||
| 93 | return 0; | 101 | return 0; |
| @@ -127,7 +135,7 @@ static struct arm_pmu *arm_pmu_acpi_find_alloc_pmu(void) | |||
| 127 | return pmu; | 135 | return pmu; |
| 128 | } | 136 | } |
| 129 | 137 | ||
| 130 | pmu = armpmu_alloc(); | 138 | pmu = armpmu_alloc_atomic(); |
| 131 | if (!pmu) { | 139 | if (!pmu) { |
| 132 | pr_warn("Unable to allocate PMU for CPU%d\n", | 140 | pr_warn("Unable to allocate PMU for CPU%d\n", |
| 133 | smp_processor_id()); | 141 | smp_processor_id()); |
| @@ -140,6 +148,35 @@ static struct arm_pmu *arm_pmu_acpi_find_alloc_pmu(void) | |||
| 140 | } | 148 | } |
| 141 | 149 | ||
| 142 | /* | 150 | /* |
| 151 | * Check whether the new IRQ is compatible with those already associated with | ||
| 152 | * the PMU (e.g. we don't have mismatched PPIs). | ||
| 153 | */ | ||
| 154 | static bool pmu_irq_matches(struct arm_pmu *pmu, int irq) | ||
| 155 | { | ||
| 156 | struct pmu_hw_events __percpu *hw_events = pmu->hw_events; | ||
| 157 | int cpu; | ||
| 158 | |||
| 159 | if (!irq) | ||
| 160 | return true; | ||
| 161 | |||
| 162 | for_each_cpu(cpu, &pmu->supported_cpus) { | ||
| 163 | int other_irq = per_cpu(hw_events->irq, cpu); | ||
| 164 | if (!other_irq) | ||
| 165 | continue; | ||
| 166 | |||
| 167 | if (irq == other_irq) | ||
| 168 | continue; | ||
| 169 | if (!irq_is_percpu_devid(irq) && !irq_is_percpu_devid(other_irq)) | ||
| 170 | continue; | ||
| 171 | |||
| 172 | pr_warn("mismatched PPIs detected\n"); | ||
| 173 | return false; | ||
| 174 | } | ||
| 175 | |||
| 176 | return true; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* | ||
| 143 | * This must run before the common arm_pmu hotplug logic, so that we can | 180 | * This must run before the common arm_pmu hotplug logic, so that we can |
| 144 | * associate a CPU and its interrupt before the common code tries to manage the | 181 | * associate a CPU and its interrupt before the common code tries to manage the |
| 145 | * affinity and so on. | 182 | * affinity and so on. |
| @@ -164,19 +201,14 @@ static int arm_pmu_acpi_cpu_starting(unsigned int cpu) | |||
| 164 | if (!pmu) | 201 | if (!pmu) |
| 165 | return -ENOMEM; | 202 | return -ENOMEM; |
| 166 | 203 | ||
| 167 | cpumask_set_cpu(cpu, &pmu->supported_cpus); | ||
| 168 | |||
| 169 | per_cpu(probed_pmus, cpu) = pmu; | 204 | per_cpu(probed_pmus, cpu) = pmu; |
| 170 | 205 | ||
| 171 | /* | 206 | if (pmu_irq_matches(pmu, irq)) { |
| 172 | * Log and request the IRQ so the core arm_pmu code can manage it. In | 207 | hw_events = pmu->hw_events; |
| 173 | * some situations (e.g. mismatched PPIs), we may fail to request the | 208 | per_cpu(hw_events->irq, cpu) = irq; |
| 174 | * IRQ. However, it may be too late for us to do anything about it. | 209 | } |
| 175 | * The common ARM PMU code will log a warning in this case. | 210 | |
| 176 | */ | 211 | cpumask_set_cpu(cpu, &pmu->supported_cpus); |
| 177 | hw_events = pmu->hw_events; | ||
| 178 | per_cpu(hw_events->irq, cpu) = irq; | ||
| 179 | armpmu_request_irq(pmu, cpu); | ||
| 180 | 212 | ||
| 181 | /* | 213 | /* |
| 182 | * Ideally, we'd probe the PMU here when we find the first matching | 214 | * Ideally, we'd probe the PMU here when we find the first matching |
| @@ -247,11 +279,6 @@ static int arm_pmu_acpi_init(void) | |||
| 247 | if (acpi_disabled) | 279 | if (acpi_disabled) |
| 248 | return 0; | 280 | return 0; |
| 249 | 281 | ||
| 250 | /* | ||
| 251 | * We can't request IRQs yet, since we don't know the cookie value | ||
| 252 | * until we know which CPUs share the same logical PMU. We'll handle | ||
| 253 | * that in arm_pmu_acpi_cpu_starting(). | ||
| 254 | */ | ||
| 255 | ret = arm_pmu_acpi_parse_irqs(); | 282 | ret = arm_pmu_acpi_parse_irqs(); |
| 256 | if (ret) | 283 | if (ret) |
| 257 | return ret; | 284 | return ret; |
diff --git a/drivers/perf/arm_pmu_platform.c b/drivers/perf/arm_pmu_platform.c index 46501cc79fd7..7729eda5909d 100644 --- a/drivers/perf/arm_pmu_platform.c +++ b/drivers/perf/arm_pmu_platform.c | |||
| @@ -127,13 +127,6 @@ static int pmu_parse_irqs(struct arm_pmu *pmu) | |||
| 127 | pdev->dev.of_node); | 127 | pdev->dev.of_node); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | /* | ||
| 131 | * Some platforms have all PMU IRQs OR'd into a single IRQ, with a | ||
| 132 | * special platdata function that attempts to demux them. | ||
| 133 | */ | ||
| 134 | if (dev_get_platdata(&pdev->dev)) | ||
| 135 | cpumask_setall(&pmu->supported_cpus); | ||
| 136 | |||
| 137 | for (i = 0; i < num_irqs; i++) { | 130 | for (i = 0; i < num_irqs; i++) { |
| 138 | int cpu, irq; | 131 | int cpu, irq; |
| 139 | 132 | ||
| @@ -164,6 +157,36 @@ static int pmu_parse_irqs(struct arm_pmu *pmu) | |||
| 164 | return 0; | 157 | return 0; |
| 165 | } | 158 | } |
| 166 | 159 | ||
| 160 | static int armpmu_request_irqs(struct arm_pmu *armpmu) | ||
| 161 | { | ||
| 162 | struct pmu_hw_events __percpu *hw_events = armpmu->hw_events; | ||
| 163 | int cpu, err; | ||
| 164 | |||
| 165 | for_each_cpu(cpu, &armpmu->supported_cpus) { | ||
| 166 | int irq = per_cpu(hw_events->irq, cpu); | ||
| 167 | if (!irq) | ||
| 168 | continue; | ||
| 169 | |||
| 170 | err = armpmu_request_irq(irq, cpu); | ||
| 171 | if (err) | ||
| 172 | break; | ||
| 173 | } | ||
| 174 | |||
| 175 | return err; | ||
| 176 | } | ||
| 177 | |||
| 178 | static void armpmu_free_irqs(struct arm_pmu *armpmu) | ||
| 179 | { | ||
| 180 | int cpu; | ||
| 181 | struct pmu_hw_events __percpu *hw_events = armpmu->hw_events; | ||
| 182 | |||
| 183 | for_each_cpu(cpu, &armpmu->supported_cpus) { | ||
| 184 | int irq = per_cpu(hw_events->irq, cpu); | ||
| 185 | |||
| 186 | armpmu_free_irq(irq, cpu); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 167 | int arm_pmu_device_probe(struct platform_device *pdev, | 190 | int arm_pmu_device_probe(struct platform_device *pdev, |
| 168 | const struct of_device_id *of_table, | 191 | const struct of_device_id *of_table, |
| 169 | const struct pmu_probe_info *probe_table) | 192 | const struct pmu_probe_info *probe_table) |
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index af0f44effd44..40036a57d072 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h | |||
| @@ -14,26 +14,10 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/perf_event.h> | 16 | #include <linux/perf_event.h> |
| 17 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/sysfs.h> | 18 | #include <linux/sysfs.h> |
| 18 | #include <asm/cputype.h> | 19 | #include <asm/cputype.h> |
| 19 | 20 | ||
| 20 | /* | ||
| 21 | * struct arm_pmu_platdata - ARM PMU platform data | ||
| 22 | * | ||
| 23 | * @handle_irq: an optional handler which will be called from the | ||
| 24 | * interrupt and passed the address of the low level handler, | ||
| 25 | * and can be used to implement any platform specific handling | ||
| 26 | * before or after calling it. | ||
| 27 | * | ||
| 28 | * @irq_flags: if non-zero, these flags will be passed to request_irq | ||
| 29 | * when requesting interrupts for this PMU device. | ||
| 30 | */ | ||
| 31 | struct arm_pmu_platdata { | ||
| 32 | irqreturn_t (*handle_irq)(int irq, void *dev, | ||
| 33 | irq_handler_t pmu_handler); | ||
| 34 | unsigned long irq_flags; | ||
| 35 | }; | ||
| 36 | |||
| 37 | #ifdef CONFIG_ARM_PMU | 21 | #ifdef CONFIG_ARM_PMU |
| 38 | 22 | ||
| 39 | /* | 23 | /* |
| @@ -92,7 +76,6 @@ enum armpmu_attr_groups { | |||
| 92 | 76 | ||
| 93 | struct arm_pmu { | 77 | struct arm_pmu { |
| 94 | struct pmu pmu; | 78 | struct pmu pmu; |
| 95 | cpumask_t active_irqs; | ||
| 96 | cpumask_t supported_cpus; | 79 | cpumask_t supported_cpus; |
| 97 | char *name; | 80 | char *name; |
| 98 | irqreturn_t (*handle_irq)(int irq_num, void *dev); | 81 | irqreturn_t (*handle_irq)(int irq_num, void *dev); |
| @@ -174,12 +157,11 @@ static inline int arm_pmu_acpi_probe(armpmu_init_fn init_fn) { return 0; } | |||
| 174 | 157 | ||
| 175 | /* Internal functions only for core arm_pmu code */ | 158 | /* Internal functions only for core arm_pmu code */ |
| 176 | struct arm_pmu *armpmu_alloc(void); | 159 | struct arm_pmu *armpmu_alloc(void); |
| 160 | struct arm_pmu *armpmu_alloc_atomic(void); | ||
| 177 | void armpmu_free(struct arm_pmu *pmu); | 161 | void armpmu_free(struct arm_pmu *pmu); |
| 178 | int armpmu_register(struct arm_pmu *pmu); | 162 | int armpmu_register(struct arm_pmu *pmu); |
| 179 | int armpmu_request_irqs(struct arm_pmu *armpmu); | 163 | int armpmu_request_irq(int irq, int cpu); |
| 180 | void armpmu_free_irqs(struct arm_pmu *armpmu); | 164 | void armpmu_free_irq(int irq, int cpu); |
| 181 | int armpmu_request_irq(struct arm_pmu *armpmu, int cpu); | ||
| 182 | void armpmu_free_irq(struct arm_pmu *armpmu, int cpu); | ||
| 183 | 165 | ||
| 184 | #define ARMV8_PMU_PDEV_NAME "armv8-pmu" | 166 | #define ARMV8_PMU_PDEV_NAME "armv8-pmu" |
| 185 | 167 | ||
