Merge branch 'for-linus' of git://android.git.kernel.org/kernel/tegra
[pandora-kernel.git] / arch / arm / kernel / hw_breakpoint.c
index d600bd3..8dbc126 100644 (file)
@@ -238,8 +238,8 @@ static int enable_monitor_mode(void)
        ARM_DBG_READ(c1, 0, dscr);
 
        /* Ensure that halting mode is disabled. */
-       if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
-                               "Unable to access hardware resources.")) {
+       if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
+                       "halting debug mode enabled. Unable to access hardware resources.\n")) {
                ret = -EPERM;
                goto out;
        }
@@ -377,7 +377,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
                }
        }
 
-       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
+       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {
                ret = -EBUSY;
                goto out;
        }
@@ -423,7 +423,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
                }
        }
 
-       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+       if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
                return;
 
        /* Reset the control register. */
@@ -635,7 +635,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
        if (WARN_ONCE(!bp->overflow_handler &&
                (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
                 || !bp->hw.bp_target),
-                       "overflow handler required but none found")) {
+                       "overflow handler required but none found\n")) {
                ret = -EINVAL;
        }
 out:
@@ -836,9 +836,11 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 /*
  * One-time initialisation.
  */
-static void reset_ctrl_regs(void *unused)
+static void reset_ctrl_regs(void *info)
 {
-       int i;
+       int i, cpu = smp_processor_id();
+       u32 dbg_power;
+       cpumask_t *cpumask = info;
 
        /*
         * v7 debug contains save and restore registers so that debug state
@@ -849,6 +851,17 @@ static void reset_ctrl_regs(void *unused)
         * later on.
         */
        if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
+               /*
+                * Ensure sticky power-down is clear (i.e. debug logic is
+                * powered up).
+                */
+               asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
+               if ((dbg_power & 0x1) == 0) {
+                       pr_warning("CPU %d debug is powered down!\n", cpu);
+                       cpumask_or(cpumask, cpumask, cpumask_of(cpu));
+                       return;
+               }
+
                /*
                 * Unconditionally clear the lock by writing a value
                 * other than 0xC5ACCE55 to the access register.
@@ -887,6 +900,7 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
 static int __init arch_hw_breakpoint_init(void)
 {
        u32 dscr;
+       cpumask_t cpumask = { CPU_BITS_NONE };
 
        debug_arch = get_debug_arch();
 
@@ -911,13 +925,19 @@ static int __init arch_hw_breakpoint_init(void)
         * Reset the breakpoint resources. We assume that a halting
         * debugger will leave the world in a nice state for us.
         */
-       on_each_cpu(reset_ctrl_regs, NULL, 1);
+       on_each_cpu(reset_ctrl_regs, &cpumask, 1);
+       if (!cpumask_empty(&cpumask)) {
+               core_num_brps = 0;
+               core_num_reserved_brps = 0;
+               core_num_wrps = 0;
+               return 0;
+       }
 
        ARM_DBG_READ(c1, 0, dscr);
        if (dscr & ARM_DSCR_HDBGEN) {
                max_watchpoint_len = 4;
-               pr_warning("halting debug mode enabled. Assuming maximum "
-                          "watchpoint size of %u bytes.", max_watchpoint_len);
+               pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n",
+                          max_watchpoint_len);
        } else {
                /* Work out the maximum supported watchpoint length. */
                max_watchpoint_len = get_max_wp_len();