diff options
Diffstat (limited to 'arch/powerpc/oprofile/common.c')
-rw-r--r-- | arch/powerpc/oprofile/common.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 1a7ef7e246d2..a28cce1d6c24 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -29,6 +29,8 @@ static struct op_powerpc_model *model; | |||
29 | static struct op_counter_config ctr[OP_MAX_COUNTER]; | 29 | static struct op_counter_config ctr[OP_MAX_COUNTER]; |
30 | static struct op_system_config sys; | 30 | static struct op_system_config sys; |
31 | 31 | ||
32 | static int op_per_cpu_rc; | ||
33 | |||
32 | static void op_handle_interrupt(struct pt_regs *regs) | 34 | static void op_handle_interrupt(struct pt_regs *regs) |
33 | { | 35 | { |
34 | model->handle_interrupt(regs, ctr); | 36 | model->handle_interrupt(regs, ctr); |
@@ -36,25 +38,41 @@ static void op_handle_interrupt(struct pt_regs *regs) | |||
36 | 38 | ||
37 | static void op_powerpc_cpu_setup(void *dummy) | 39 | static void op_powerpc_cpu_setup(void *dummy) |
38 | { | 40 | { |
39 | model->cpu_setup(ctr); | 41 | int ret; |
42 | |||
43 | ret = model->cpu_setup(ctr); | ||
44 | |||
45 | if (ret != 0) | ||
46 | op_per_cpu_rc = ret; | ||
40 | } | 47 | } |
41 | 48 | ||
42 | static int op_powerpc_setup(void) | 49 | static int op_powerpc_setup(void) |
43 | { | 50 | { |
44 | int err; | 51 | int err; |
45 | 52 | ||
53 | op_per_cpu_rc = 0; | ||
54 | |||
46 | /* Grab the hardware */ | 55 | /* Grab the hardware */ |
47 | err = reserve_pmc_hardware(op_handle_interrupt); | 56 | err = reserve_pmc_hardware(op_handle_interrupt); |
48 | if (err) | 57 | if (err) |
49 | return err; | 58 | return err; |
50 | 59 | ||
51 | /* Pre-compute the values to stuff in the hardware registers. */ | 60 | /* Pre-compute the values to stuff in the hardware registers. */ |
52 | model->reg_setup(ctr, &sys, model->num_counters); | 61 | op_per_cpu_rc = model->reg_setup(ctr, &sys, model->num_counters); |
53 | 62 | ||
54 | /* Configure the registers on all cpus. */ | 63 | if (op_per_cpu_rc) |
64 | goto out; | ||
65 | |||
66 | /* Configure the registers on all cpus. If an error occurs on one | ||
67 | * of the cpus, op_per_cpu_rc will be set to the error */ | ||
55 | on_each_cpu(op_powerpc_cpu_setup, NULL, 0, 1); | 68 | on_each_cpu(op_powerpc_cpu_setup, NULL, 0, 1); |
56 | 69 | ||
57 | return 0; | 70 | out: if (op_per_cpu_rc) { |
71 | /* error on setup release the performance counter hardware */ | ||
72 | release_pmc_hardware(); | ||
73 | } | ||
74 | |||
75 | return op_per_cpu_rc; | ||
58 | } | 76 | } |
59 | 77 | ||
60 | static void op_powerpc_shutdown(void) | 78 | static void op_powerpc_shutdown(void) |
@@ -64,16 +82,29 @@ static void op_powerpc_shutdown(void) | |||
64 | 82 | ||
65 | static void op_powerpc_cpu_start(void *dummy) | 83 | static void op_powerpc_cpu_start(void *dummy) |
66 | { | 84 | { |
67 | model->start(ctr); | 85 | /* If any of the cpus have return an error, set the |
86 | * global flag to the error so it can be returned | ||
87 | * to the generic OProfile caller. | ||
88 | */ | ||
89 | int ret; | ||
90 | |||
91 | ret = model->start(ctr); | ||
92 | if (ret != 0) | ||
93 | op_per_cpu_rc = ret; | ||
68 | } | 94 | } |
69 | 95 | ||
70 | static int op_powerpc_start(void) | 96 | static int op_powerpc_start(void) |
71 | { | 97 | { |
98 | op_per_cpu_rc = 0; | ||
99 | |||
72 | if (model->global_start) | 100 | if (model->global_start) |
73 | model->global_start(ctr); | 101 | return model->global_start(ctr); |
74 | if (model->start) | 102 | if (model->start) { |
75 | on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); | 103 | on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); |
76 | return 0; | 104 | return op_per_cpu_rc; |
105 | } | ||
106 | return -EIO; /* No start function is defined for this | ||
107 | power architecture */ | ||
77 | } | 108 | } |
78 | 109 | ||
79 | static inline void op_powerpc_cpu_stop(void *dummy) | 110 | static inline void op_powerpc_cpu_stop(void *dummy) |
@@ -147,11 +178,13 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
147 | 178 | ||
148 | switch (cur_cpu_spec->oprofile_type) { | 179 | switch (cur_cpu_spec->oprofile_type) { |
149 | #ifdef CONFIG_PPC64 | 180 | #ifdef CONFIG_PPC64 |
150 | #ifdef CONFIG_PPC_CELL_NATIVE | 181 | #ifdef CONFIG_OPROFILE_CELL |
151 | case PPC_OPROFILE_CELL: | 182 | case PPC_OPROFILE_CELL: |
152 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 183 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
153 | return -ENODEV; | 184 | return -ENODEV; |
154 | model = &op_model_cell; | 185 | model = &op_model_cell; |
186 | ops->sync_start = model->sync_start; | ||
187 | ops->sync_stop = model->sync_stop; | ||
155 | break; | 188 | break; |
156 | #endif | 189 | #endif |
157 | case PPC_OPROFILE_RS64: | 190 | case PPC_OPROFILE_RS64: |