Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[sfrench/cifs-2.6.git] / arch / x86 / oprofile / op_model_ppro.c
index 2bf90fafa7b56a89e6e6e7627c623c57bad62b67..d769cda540823e12a0dbfbdba923ec481f07abfd 100644 (file)
@@ -30,19 +30,46 @@ static int counter_width = 32;
 
 static u64 *reset_value;
 
-static void ppro_fill_in_addresses(struct op_msrs * const msrs)
+static void ppro_shutdown(struct op_msrs const * const msrs)
 {
        int i;
 
-       for (i = 0; i < num_counters; i++) {
-               if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
-                       msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+       for (i = 0; i < num_counters; ++i) {
+               if (!msrs->counters[i].addr)
+                       continue;
+               release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+               release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
+       }
+       if (reset_value) {
+               kfree(reset_value);
+               reset_value = NULL;
        }
+}
+
+static int ppro_fill_in_addresses(struct op_msrs * const msrs)
+{
+       int i;
 
        for (i = 0; i < num_counters; i++) {
-               if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
-                       msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+               if (!reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+                       goto fail;
+               if (!reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) {
+                       release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+                       goto fail;
+               }
+               /* both registers must be reserved */
+               msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+               msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+               continue;
+       fail:
+               if (!counter_config[i].enabled)
+                       continue;
+               op_x86_warn_reserved(i);
+               ppro_shutdown(msrs);
+               return -EBUSY;
        }
+
+       return 0;
 }
 
 
@@ -78,26 +105,17 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
 
        /* clear all counters */
        for (i = 0; i < num_counters; ++i) {
-               if (unlikely(!msrs->controls[i].addr)) {
-                       if (counter_config[i].enabled && !smp_processor_id())
-                               /*
-                                * counter is reserved, this is on all
-                                * cpus, so report only for cpu #0
-                                */
-                               op_x86_warn_reserved(i);
+               if (!msrs->controls[i].addr)
                        continue;
-               }
                rdmsrl(msrs->controls[i].addr, val);
                if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
                        op_x86_warn_in_use(i);
                val &= model->reserved;
                wrmsrl(msrs->controls[i].addr, val);
-       }
-
-       /* avoid a false detection of ctr overflows in NMI handler */
-       for (i = 0; i < num_counters; ++i) {
-               if (unlikely(!msrs->counters[i].addr))
-                       continue;
+               /*
+                * avoid a false detection of ctr overflows in NMI *
+                * handler
+                */
                wrmsrl(msrs->counters[i].addr, -1LL);
        }
 
@@ -189,25 +207,6 @@ static void ppro_stop(struct op_msrs const * const msrs)
        }
 }
 
-static void ppro_shutdown(struct op_msrs const * const msrs)
-{
-       int i;
-
-       for (i = 0; i < num_counters; ++i) {
-               if (msrs->counters[i].addr)
-                       release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
-       }
-       for (i = 0; i < num_counters; ++i) {
-               if (msrs->controls[i].addr)
-                       release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
-       }
-       if (reset_value) {
-               kfree(reset_value);
-               reset_value = NULL;
-       }
-}
-
-
 struct op_x86_model_spec op_ppro_spec = {
        .num_counters           = 2,
        .num_controls           = 2,
@@ -239,11 +238,11 @@ static void arch_perfmon_setup_counters(void)
        if (eax.split.version_id == 0 && current_cpu_data.x86 == 6 &&
                current_cpu_data.x86_model == 15) {
                eax.split.version_id = 2;
-               eax.split.num_events = 2;
+               eax.split.num_counters = 2;
                eax.split.bit_width = 40;
        }
 
-       num_counters = eax.split.num_events;
+       num_counters = eax.split.num_counters;
 
        op_arch_perfmon_spec.num_counters = num_counters;
        op_arch_perfmon_spec.num_controls = num_counters;