MIPS: OCTEON: watchdog: don't jump to bootloader without entry address
authorAaro Koskinen <aaro.koskinen@iki.fi>
Fri, 27 Jun 2014 21:59:50 +0000 (00:59 +0300)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 1 Aug 2014 22:06:42 +0000 (00:06 +0200)
If CONFIG_HOTPLUG_CPU is set, the driver thinks bootloader entry
address is configured and we should jump there. However, this is
not necessarily true if the kernel is booted on a system
with older/incompatible bootloader.

Add dynamic checks for the bootloader entry address.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: linux-watchdog@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: David Daney <ddaney.cavm@gmail.com>
Cc: linux-watchdog@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/7201/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
drivers/watchdog/octeon-wdt-main.c

index 4baf2d788920484f5f9fe8d752d9f51ecf7b63fb..8453531545dfee189ee28077d55e6b37e807df2f 100644 (file)
@@ -145,35 +145,39 @@ static void __init octeon_wdt_build_stage1(void)
 
        uasm_i_mfc0(&p, K0, C0_STATUS);
 #ifdef CONFIG_HOTPLUG_CPU
-       uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader);
+       if (octeon_bootloader_entry_addr)
+               uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI),
+                             label_enter_bootloader);
 #endif
        /* Force 64-bit addressing enabled */
        uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
        uasm_i_mtc0(&p, K0, C0_STATUS);
 
 #ifdef CONFIG_HOTPLUG_CPU
-       uasm_i_mfc0(&p, K0, C0_EBASE);
-       /* Coreid number in K0 */
-       uasm_i_andi(&p, K0, K0, 0xf);
-       /* 8 * coreid in bits 16-31 */
-       uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
-       uasm_i_ori(&p, K0, K0, 0x8001);
-       uasm_i_dsll_safe(&p, K0, K0, 16);
-       uasm_i_ori(&p, K0, K0, 0x0700);
-       uasm_i_drotr_safe(&p, K0, K0, 32);
-       /*
-        * Should result in: 0x8001,0700,0000,8*coreid which is
-        * CVMX_CIU_WDOGX(coreid) - 0x0500
-        *
-        * Now ld K0, CVMX_CIU_WDOGX(coreid)
-        */
-       uasm_i_ld(&p, K0, 0x500, K0);
-       /*
-        * If bit one set handle the NMI as a watchdog event.
-        * otherwise transfer control to bootloader.
-        */
-       uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
-       uasm_i_nop(&p);
+       if (octeon_bootloader_entry_addr) {
+               uasm_i_mfc0(&p, K0, C0_EBASE);
+               /* Coreid number in K0 */
+               uasm_i_andi(&p, K0, K0, 0xf);
+               /* 8 * coreid in bits 16-31 */
+               uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
+               uasm_i_ori(&p, K0, K0, 0x8001);
+               uasm_i_dsll_safe(&p, K0, K0, 16);
+               uasm_i_ori(&p, K0, K0, 0x0700);
+               uasm_i_drotr_safe(&p, K0, K0, 32);
+               /*
+                * Should result in: 0x8001,0700,0000,8*coreid which is
+                * CVMX_CIU_WDOGX(coreid) - 0x0500
+                *
+                * Now ld K0, CVMX_CIU_WDOGX(coreid)
+                */
+               uasm_i_ld(&p, K0, 0x500, K0);
+               /*
+                * If bit one set handle the NMI as a watchdog event.
+                * otherwise transfer control to bootloader.
+                */
+               uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
+               uasm_i_nop(&p);
+       }
 #endif
 
        /* Clear Dcache so cvmseg works right. */
@@ -194,11 +198,13 @@ static void __init octeon_wdt_build_stage1(void)
        uasm_i_dmfc0(&p, K0, C0_DESAVE);
 
 #ifdef CONFIG_HOTPLUG_CPU
-       uasm_build_label(&l, p, label_enter_bootloader);
-       /* Jump to the bootloader and restore K0 */
-       UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
-       uasm_i_jr(&p, K0);
-       uasm_i_dmfc0(&p, K0, C0_DESAVE);
+       if (octeon_bootloader_entry_addr) {
+               uasm_build_label(&l, p, label_enter_bootloader);
+               /* Jump to the bootloader and restore K0 */
+               UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
+               uasm_i_jr(&p, K0);
+               uasm_i_dmfc0(&p, K0, C0_DESAVE);
+       }
 #endif
        uasm_resolve_relocs(relocs, labels);