diff options
| -rw-r--r-- | arch/arm/oprofile/op_model_arm11_core.c | 4 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_model_arm11_core.h | 4 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_model_mpcore.c | 42 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_model_v6.c | 30 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_model_v7.c | 30 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_model_v7.h | 4 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_model_xscale.c | 35 |
7 files changed, 85 insertions, 64 deletions
diff --git a/arch/arm/oprofile/op_model_arm11_core.c b/arch/arm/oprofile/op_model_arm11_core.c index ad80752cb9fb..ef3e2653b90c 100644 --- a/arch/arm/oprofile/op_model_arm11_core.c +++ b/arch/arm/oprofile/op_model_arm11_core.c | |||
| @@ -132,7 +132,7 @@ static irqreturn_t arm11_pmu_interrupt(int irq, void *arg) | |||
| 132 | return IRQ_HANDLED; | 132 | return IRQ_HANDLED; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | int arm11_request_interrupts(int *irqs, int nr) | 135 | int arm11_request_interrupts(const int *irqs, int nr) |
| 136 | { | 136 | { |
| 137 | unsigned int i; | 137 | unsigned int i; |
| 138 | int ret = 0; | 138 | int ret = 0; |
| @@ -153,7 +153,7 @@ int arm11_request_interrupts(int *irqs, int nr) | |||
| 153 | return ret; | 153 | return ret; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | void arm11_release_interrupts(int *irqs, int nr) | 156 | void arm11_release_interrupts(const int *irqs, int nr) |
| 157 | { | 157 | { |
| 158 | unsigned int i; | 158 | unsigned int i; |
| 159 | 159 | ||
diff --git a/arch/arm/oprofile/op_model_arm11_core.h b/arch/arm/oprofile/op_model_arm11_core.h index 6f8538e5a960..1902b99d9dfd 100644 --- a/arch/arm/oprofile/op_model_arm11_core.h +++ b/arch/arm/oprofile/op_model_arm11_core.h | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | int arm11_setup_pmu(void); | 39 | int arm11_setup_pmu(void); |
| 40 | int arm11_start_pmu(void); | 40 | int arm11_start_pmu(void); |
| 41 | int arm11_stop_pmu(void); | 41 | int arm11_stop_pmu(void); |
| 42 | int arm11_request_interrupts(int *, int); | 42 | int arm11_request_interrupts(const int *, int); |
| 43 | void arm11_release_interrupts(int *, int); | 43 | void arm11_release_interrupts(const int *, int); |
| 44 | 44 | ||
| 45 | #endif | 45 | #endif |
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c index 4ce0f9801e2e..f73ce875a395 100644 --- a/arch/arm/oprofile/op_model_mpcore.c +++ b/arch/arm/oprofile/op_model_mpcore.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | /* #define DEBUG */ | 32 | /* #define DEBUG */ |
| 33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
| 34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
| 35 | #include <linux/err.h> | ||
| 35 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
| 36 | #include <linux/oprofile.h> | 37 | #include <linux/oprofile.h> |
| 37 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
| @@ -43,6 +44,7 @@ | |||
| 43 | #include <mach/hardware.h> | 44 | #include <mach/hardware.h> |
| 44 | #include <mach/board-eb.h> | 45 | #include <mach/board-eb.h> |
| 45 | #include <asm/system.h> | 46 | #include <asm/system.h> |
| 47 | #include <asm/pmu.h> | ||
| 46 | 48 | ||
| 47 | #include "op_counter.h" | 49 | #include "op_counter.h" |
| 48 | #include "op_arm_model.h" | 50 | #include "op_arm_model.h" |
| @@ -58,6 +60,7 @@ | |||
| 58 | * Bitmask of used SCU counters | 60 | * Bitmask of used SCU counters |
| 59 | */ | 61 | */ |
| 60 | static unsigned int scu_em_used; | 62 | static unsigned int scu_em_used; |
| 63 | static const struct pmu_irqs *pmu_irqs; | ||
| 61 | 64 | ||
| 62 | /* | 65 | /* |
| 63 | * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number) | 66 | * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number) |
| @@ -225,33 +228,40 @@ static int em_setup_ctrs(void) | |||
| 225 | return 0; | 228 | return 0; |
| 226 | } | 229 | } |
| 227 | 230 | ||
| 228 | static int arm11_irqs[] = { | ||
| 229 | [0] = IRQ_EB11MP_PMU_CPU0, | ||
| 230 | [1] = IRQ_EB11MP_PMU_CPU1, | ||
| 231 | [2] = IRQ_EB11MP_PMU_CPU2, | ||
| 232 | [3] = IRQ_EB11MP_PMU_CPU3 | ||
| 233 | }; | ||
| 234 | |||
| 235 | static int em_start(void) | 231 | static int em_start(void) |
| 236 | { | 232 | { |
| 237 | int ret; | 233 | int ret; |
| 238 | 234 | ||
| 239 | ret = arm11_request_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs)); | 235 | pmu_irqs = reserve_pmu(); |
| 236 | if (IS_ERR(pmu_irqs)) { | ||
| 237 | ret = PTR_ERR(pmu_irqs); | ||
| 238 | goto out; | ||
| 239 | } | ||
| 240 | |||
| 241 | ret = arm11_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); | ||
| 240 | if (ret == 0) { | 242 | if (ret == 0) { |
| 241 | em_call_function(arm11_start_pmu); | 243 | em_call_function(arm11_start_pmu); |
| 242 | 244 | ||
| 243 | ret = scu_start(); | 245 | ret = scu_start(); |
| 244 | if (ret) | 246 | if (ret) { |
| 245 | arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs)); | 247 | arm11_release_interrupts(pmu_irqs->irqs, |
| 248 | pmu_irqs->num_irqs); | ||
| 249 | } else { | ||
| 250 | release_pmu(pmu_irqs); | ||
| 251 | pmu_irqs = NULL; | ||
| 252 | } | ||
| 246 | } | 253 | } |
| 254 | |||
| 255 | out: | ||
| 247 | return ret; | 256 | return ret; |
| 248 | } | 257 | } |
| 249 | 258 | ||
| 250 | static void em_stop(void) | 259 | static void em_stop(void) |
| 251 | { | 260 | { |
| 252 | em_call_function(arm11_stop_pmu); | 261 | em_call_function(arm11_stop_pmu); |
| 253 | arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs)); | 262 | arm11_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); |
| 254 | scu_stop(); | 263 | scu_stop(); |
| 264 | release_pmu(pmu_irqs); | ||
| 255 | } | 265 | } |
| 256 | 266 | ||
| 257 | /* | 267 | /* |
| @@ -283,15 +293,7 @@ static int em_setup(void) | |||
| 283 | em_route_irq(IRQ_EB11MP_PMU_SCU6, 3); | 293 | em_route_irq(IRQ_EB11MP_PMU_SCU6, 3); |
| 284 | em_route_irq(IRQ_EB11MP_PMU_SCU7, 3); | 294 | em_route_irq(IRQ_EB11MP_PMU_SCU7, 3); |
| 285 | 295 | ||
| 286 | /* | 296 | return init_pmu(); |
| 287 | * Send CP15 PMU interrupts to the owner CPU. | ||
| 288 | */ | ||
| 289 | em_route_irq(IRQ_EB11MP_PMU_CPU0, 0); | ||
| 290 | em_route_irq(IRQ_EB11MP_PMU_CPU1, 1); | ||
| 291 | em_route_irq(IRQ_EB11MP_PMU_CPU2, 2); | ||
| 292 | em_route_irq(IRQ_EB11MP_PMU_CPU3, 3); | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | 297 | } |
| 296 | 298 | ||
| 297 | struct op_arm_model_spec op_mpcore_spec = { | 299 | struct op_arm_model_spec op_mpcore_spec = { |
diff --git a/arch/arm/oprofile/op_model_v6.c b/arch/arm/oprofile/op_model_v6.c index f7d2ec5ee9a1..a22357a2fd08 100644 --- a/arch/arm/oprofile/op_model_v6.c +++ b/arch/arm/oprofile/op_model_v6.c | |||
| @@ -19,39 +19,47 @@ | |||
| 19 | /* #define DEBUG */ | 19 | /* #define DEBUG */ |
| 20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
| 21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
| 22 | #include <linux/err.h> | ||
| 22 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
| 23 | #include <linux/oprofile.h> | 24 | #include <linux/oprofile.h> |
| 24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 25 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
| 26 | #include <asm/system.h> | 27 | #include <asm/system.h> |
| 28 | #include <asm/pmu.h> | ||
| 27 | 29 | ||
| 28 | #include "op_counter.h" | 30 | #include "op_counter.h" |
| 29 | #include "op_arm_model.h" | 31 | #include "op_arm_model.h" |
| 30 | #include "op_model_arm11_core.h" | 32 | #include "op_model_arm11_core.h" |
| 31 | 33 | ||
| 32 | static int irqs[] = { | 34 | static const struct pmu_irqs *pmu_irqs; |
| 33 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 34 | 3, | ||
| 35 | #endif | ||
| 36 | #ifdef CONFIG_ARCH_BCMRING | ||
| 37 | IRQ_PMUIRQ, /* for BCMRING, ARM PMU interrupt is 43 */ | ||
| 38 | #endif | ||
| 39 | }; | ||
| 40 | 35 | ||
| 41 | static void armv6_pmu_stop(void) | 36 | static void armv6_pmu_stop(void) |
| 42 | { | 37 | { |
| 43 | arm11_stop_pmu(); | 38 | arm11_stop_pmu(); |
| 44 | arm11_release_interrupts(irqs, ARRAY_SIZE(irqs)); | 39 | arm11_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); |
| 40 | release_pmu(pmu_irqs); | ||
| 41 | pmu_irqs = NULL; | ||
| 45 | } | 42 | } |
| 46 | 43 | ||
| 47 | static int armv6_pmu_start(void) | 44 | static int armv6_pmu_start(void) |
| 48 | { | 45 | { |
| 49 | int ret; | 46 | int ret; |
| 50 | 47 | ||
| 51 | ret = arm11_request_interrupts(irqs, ARRAY_SIZE(irqs)); | 48 | pmu_irqs = reserve_pmu(); |
| 52 | if (ret >= 0) | 49 | if (IS_ERR(pmu_irqs)) { |
| 50 | ret = PTR_ERR(pmu_irqs); | ||
| 51 | goto out; | ||
| 52 | } | ||
| 53 | |||
| 54 | ret = arm11_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); | ||
| 55 | if (ret >= 0) { | ||
| 53 | ret = arm11_start_pmu(); | 56 | ret = arm11_start_pmu(); |
| 57 | } else { | ||
| 58 | release_pmu(pmu_irqs); | ||
| 59 | pmu_irqs = NULL; | ||
| 60 | } | ||
| 54 | 61 | ||
| 62 | out: | ||
| 55 | return ret; | 63 | return ret; |
| 56 | } | 64 | } |
| 57 | 65 | ||
diff --git a/arch/arm/oprofile/op_model_v7.c b/arch/arm/oprofile/op_model_v7.c index 2088a6c0cc0e..8642d0891ae1 100644 --- a/arch/arm/oprofile/op_model_v7.c +++ b/arch/arm/oprofile/op_model_v7.c | |||
| @@ -11,11 +11,14 @@ | |||
| 11 | */ | 11 | */ |
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | #include <linux/err.h> | ||
| 14 | #include <linux/oprofile.h> | 15 | #include <linux/oprofile.h> |
| 15 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 16 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
| 17 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
| 18 | 19 | ||
| 20 | #include <asm/pmu.h> | ||
| 21 | |||
| 19 | #include "op_counter.h" | 22 | #include "op_counter.h" |
| 20 | #include "op_arm_model.h" | 23 | #include "op_arm_model.h" |
| 21 | #include "op_model_v7.h" | 24 | #include "op_model_v7.h" |
| @@ -295,7 +298,7 @@ static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg) | |||
| 295 | return IRQ_HANDLED; | 298 | return IRQ_HANDLED; |
| 296 | } | 299 | } |
| 297 | 300 | ||
| 298 | int armv7_request_interrupts(int *irqs, int nr) | 301 | int armv7_request_interrupts(const int *irqs, int nr) |
| 299 | { | 302 | { |
| 300 | unsigned int i; | 303 | unsigned int i; |
| 301 | int ret = 0; | 304 | int ret = 0; |
| @@ -318,7 +321,7 @@ int armv7_request_interrupts(int *irqs, int nr) | |||
| 318 | return ret; | 321 | return ret; |
| 319 | } | 322 | } |
| 320 | 323 | ||
| 321 | void armv7_release_interrupts(int *irqs, int nr) | 324 | void armv7_release_interrupts(const int *irqs, int nr) |
| 322 | { | 325 | { |
| 323 | unsigned int i; | 326 | unsigned int i; |
| 324 | 327 | ||
| @@ -362,12 +365,7 @@ static void armv7_pmnc_dump_regs(void) | |||
| 362 | } | 365 | } |
| 363 | #endif | 366 | #endif |
| 364 | 367 | ||
| 365 | 368 | static const struct pmu_irqs *pmu_irqs; | |
| 366 | static int irqs[] = { | ||
| 367 | #ifdef CONFIG_ARCH_OMAP3 | ||
| 368 | INT_34XX_BENCH_MPU_EMUL, | ||
| 369 | #endif | ||
| 370 | }; | ||
| 371 | 369 | ||
| 372 | static void armv7_pmnc_stop(void) | 370 | static void armv7_pmnc_stop(void) |
| 373 | { | 371 | { |
| @@ -375,19 +373,29 @@ static void armv7_pmnc_stop(void) | |||
| 375 | armv7_pmnc_dump_regs(); | 373 | armv7_pmnc_dump_regs(); |
| 376 | #endif | 374 | #endif |
| 377 | armv7_stop_pmnc(); | 375 | armv7_stop_pmnc(); |
| 378 | armv7_release_interrupts(irqs, ARRAY_SIZE(irqs)); | 376 | armv7_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); |
| 377 | release_pmu(pmu_irqs); | ||
| 378 | pmu_irqs = NULL; | ||
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | static int armv7_pmnc_start(void) | 381 | static int armv7_pmnc_start(void) |
| 382 | { | 382 | { |
| 383 | int ret; | 383 | int ret; |
| 384 | 384 | ||
| 385 | pmu_irqs = reserve_pmu(); | ||
| 386 | if (IS_ERR(pmu_irqs)) | ||
| 387 | return PTR_ERR(pmu_irqs); | ||
| 388 | |||
| 385 | #ifdef DEBUG | 389 | #ifdef DEBUG |
| 386 | armv7_pmnc_dump_regs(); | 390 | armv7_pmnc_dump_regs(); |
| 387 | #endif | 391 | #endif |
| 388 | ret = armv7_request_interrupts(irqs, ARRAY_SIZE(irqs)); | 392 | ret = armv7_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); |
| 389 | if (ret >= 0) | 393 | if (ret >= 0) { |
| 390 | armv7_start_pmnc(); | 394 | armv7_start_pmnc(); |
| 395 | } else { | ||
| 396 | release_pmu(pmu_irqs); | ||
| 397 | pmu_irqs = NULL; | ||
| 398 | } | ||
| 391 | 399 | ||
| 392 | return ret; | 400 | return ret; |
| 393 | } | 401 | } |
diff --git a/arch/arm/oprofile/op_model_v7.h b/arch/arm/oprofile/op_model_v7.h index 0e19bcc2e100..9ca334b39c75 100644 --- a/arch/arm/oprofile/op_model_v7.h +++ b/arch/arm/oprofile/op_model_v7.h | |||
| @@ -97,7 +97,7 @@ | |||
| 97 | int armv7_setup_pmu(void); | 97 | int armv7_setup_pmu(void); |
| 98 | int armv7_start_pmu(void); | 98 | int armv7_start_pmu(void); |
| 99 | int armv7_stop_pmu(void); | 99 | int armv7_stop_pmu(void); |
| 100 | int armv7_request_interrupts(int *, int); | 100 | int armv7_request_interrupts(const int *, int); |
| 101 | void armv7_release_interrupts(int *, int); | 101 | void armv7_release_interrupts(const int *, int); |
| 102 | 102 | ||
| 103 | #endif | 103 | #endif |
diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c index 724ab9ce2526..1d34a02048bd 100644 --- a/arch/arm/oprofile/op_model_xscale.c +++ b/arch/arm/oprofile/op_model_xscale.c | |||
| @@ -17,12 +17,14 @@ | |||
| 17 | /* #define DEBUG */ | 17 | /* #define DEBUG */ |
| 18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
| 20 | #include <linux/err.h> | ||
| 20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
| 21 | #include <linux/oprofile.h> | 22 | #include <linux/oprofile.h> |
| 22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
| 24 | 25 | ||
| 25 | #include <asm/cputype.h> | 26 | #include <asm/cputype.h> |
| 27 | #include <asm/pmu.h> | ||
| 26 | 28 | ||
| 27 | #include "op_counter.h" | 29 | #include "op_counter.h" |
| 28 | #include "op_arm_model.h" | 30 | #include "op_arm_model.h" |
| @@ -33,17 +35,6 @@ | |||
| 33 | #define PMU_RESET (CCNT_RESET | PMN_RESET) | 35 | #define PMU_RESET (CCNT_RESET | PMN_RESET) |
| 34 | #define PMU_CNT64 0x008 /* Make CCNT count every 64th cycle */ | 36 | #define PMU_CNT64 0x008 /* Make CCNT count every 64th cycle */ |
| 35 | 37 | ||
| 36 | /* TODO do runtime detection */ | ||
| 37 | #ifdef CONFIG_ARCH_IOP32X | ||
| 38 | #define XSCALE_PMU_IRQ IRQ_IOP32X_CORE_PMU | ||
| 39 | #endif | ||
| 40 | #ifdef CONFIG_ARCH_IOP33X | ||
| 41 | #define XSCALE_PMU_IRQ IRQ_IOP33X_CORE_PMU | ||
| 42 | #endif | ||
| 43 | #ifdef CONFIG_ARCH_PXA | ||
| 44 | #define XSCALE_PMU_IRQ IRQ_PMU | ||
| 45 | #endif | ||
| 46 | |||
| 47 | /* | 38 | /* |
| 48 | * Different types of events that can be counted by the XScale PMU | 39 | * Different types of events that can be counted by the XScale PMU |
| 49 | * as used by Oprofile userspace. Here primarily for documentation | 40 | * as used by Oprofile userspace. Here primarily for documentation |
| @@ -367,6 +358,8 @@ static irqreturn_t xscale_pmu_interrupt(int irq, void *arg) | |||
| 367 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
| 368 | } | 359 | } |
| 369 | 360 | ||
| 361 | static const struct pmu_irqs *pmu_irqs; | ||
| 362 | |||
| 370 | static void xscale_pmu_stop(void) | 363 | static void xscale_pmu_stop(void) |
| 371 | { | 364 | { |
| 372 | u32 pmnc = read_pmnc(); | 365 | u32 pmnc = read_pmnc(); |
| @@ -374,20 +367,30 @@ static void xscale_pmu_stop(void) | |||
| 374 | pmnc &= ~PMU_ENABLE; | 367 | pmnc &= ~PMU_ENABLE; |
| 375 | write_pmnc(pmnc); | 368 | write_pmnc(pmnc); |
| 376 | 369 | ||
| 377 | free_irq(XSCALE_PMU_IRQ, results); | 370 | free_irq(pmu_irqs->irqs[0], results); |
| 371 | release_pmu(pmu_irqs); | ||
| 372 | pmu_irqs = NULL; | ||
| 378 | } | 373 | } |
| 379 | 374 | ||
| 380 | static int xscale_pmu_start(void) | 375 | static int xscale_pmu_start(void) |
| 381 | { | 376 | { |
| 382 | int ret; | 377 | int ret; |
| 383 | u32 pmnc = read_pmnc(); | 378 | u32 pmnc; |
| 379 | |||
| 380 | pmu_irqs = reserve_pmu(); | ||
| 381 | if (IS_ERR(pmu_irqs)) | ||
| 382 | return PTR_ERR(pmu_irqs); | ||
| 383 | |||
| 384 | pmnc = read_pmnc(); | ||
| 384 | 385 | ||
| 385 | ret = request_irq(XSCALE_PMU_IRQ, xscale_pmu_interrupt, IRQF_DISABLED, | 386 | ret = request_irq(pmu_irqs->irqs[0], xscale_pmu_interrupt, |
| 386 | "XScale PMU", (void *)results); | 387 | IRQF_DISABLED, "XScale PMU", (void *)results); |
| 387 | 388 | ||
| 388 | if (ret < 0) { | 389 | if (ret < 0) { |
| 389 | printk(KERN_ERR "oprofile: unable to request IRQ%d for XScale PMU\n", | 390 | printk(KERN_ERR "oprofile: unable to request IRQ%d for XScale PMU\n", |
| 390 | XSCALE_PMU_IRQ); | 391 | pmu_irqs->irqs[0]); |
| 392 | release_pmu(pmu_irqs); | ||
| 393 | pmu_irqs = NULL; | ||
| 391 | return ret; | 394 | return ret; |
| 392 | } | 395 | } |
| 393 | 396 | ||
