Title: [8214] trunk/arch/blackfin: Task [#4796], revise previous commit, 1.
Revision
8214
Author
gyang
Date
2010-01-21 04:27:39 -0500 (Thu, 21 Jan 2010)

Log Message

Task [#4796], revise previous commit, 1. once entered nmi, it is not recoverable 2. lower the overhead of tick timer interrupt 

Modified Paths

Diff

Modified: trunk/arch/blackfin/Kconfig (8213 => 8214)


--- trunk/arch/blackfin/Kconfig	2010-01-21 09:18:51 UTC (rev 8213)
+++ trunk/arch/blackfin/Kconfig	2010-01-21 09:27:39 UTC (rev 8214)
@@ -661,7 +661,7 @@
 
 choice
 	prompt "Blackfin Exception Scratch Register"
-	default BFIN_SCRATCH_REG_RETE
+	default BFIN_SCRATCH_REG_RETN
 	help
 	  Select the resource to reserve for the Exception handler:
 	    - RETN: Non-Maskable Interrupt (NMI)

Modified: trunk/arch/blackfin/Kconfig.debug (8213 => 8214)


--- trunk/arch/blackfin/Kconfig.debug	2010-01-21 09:18:51 UTC (rev 8213)
+++ trunk/arch/blackfin/Kconfig.debug	2010-01-21 09:27:39 UTC (rev 8214)
@@ -241,14 +241,12 @@
 config NMI_WATCHDOG
 	bool "Enable NMI watchdog to help debuging lockup on SMP"
 	default n
-	depends on SMP
+	depends on (SMP && !BFIN_SCRATCH_REG_RETN)
 	help
 	  if any CPU in the system does not execute the period local timer
 	  interrupt for more than 5 seconds, then the NMI handler dumps debug
 	  information. This information can be used to debug the lockup.
 
-	  Note: this feature means can not select BFIN_SCRATCH_REG_RETN
-
 config CPLB_INFO
 	bool "Display the CPLB information"
 	help

Modified: trunk/arch/blackfin/include/asm/nmi.h (8213 => 8214)


--- trunk/arch/blackfin/include/asm/nmi.h	2010-01-21 09:18:51 UTC (rev 8213)
+++ trunk/arch/blackfin/include/asm/nmi.h	2010-01-21 09:27:39 UTC (rev 8214)
@@ -8,10 +8,5 @@
 #define _BFIN_NMI_H_
 
 #include <linux/nmi.h>
-#ifdef CONFIG_NMI_WATCHDOG
-void check_nmi_watchdog(unsigned int cpu);
-#else
-static inline void check_nmi_watchdog(unsigned int cpu) {};
-#endif
 
 #endif

Modified: trunk/arch/blackfin/kernel/nmi.c (8213 => 8214)


--- trunk/arch/blackfin/kernel/nmi.c	2010-01-21 09:18:51 UTC (rev 8213)
+++ trunk/arch/blackfin/kernel/nmi.c	2010-01-21 09:27:39 UTC (rev 8214)
@@ -37,17 +37,18 @@
 
 #define DRV_NAME "nmi-wdt"
 
-#define NMI_WDT_TIMEOUT 5
+#define NMI_WDT_TIMEOUT 5   /* 5 seconds */
+#define NMI_CHECK_TIMEOUT (4 * HZ) /* 4 seconds in jiffies */
 static int nmi_wdt_cpu = 1;
 
 static unsigned int timeout = NMI_WDT_TIMEOUT;
 static int nmi_active;
-static int panic_on_timeout;
 
 static unsigned short wdoga_ctl;
 static unsigned int wdoga_cnt;
 static struct corelock_slot saved_corelock;
 static atomic_t nmi_touched[NR_CPUS];
+static struct timer_list ntimer;
 
 enum {
 	COREA_ENTER_NMI = 0,
@@ -124,19 +125,20 @@
 	bfin_write_WDOGB_CTL(WDEN_ENABLE | ICTL_NMI);
 }
 
-static int nmi_wdt_running(void)
+static inline int nmi_wdt_running(void)
 {
 	return ((bfin_read_WDOGB_CTL() & WDEN_MASK) != WDEN_DISABLE);
 }
 
-static int nmi_wdt_set_timeout(unsigned long t)
+static inline int nmi_wdt_set_timeout(unsigned long t)
 {
-	u32 cnt;
+	u32 cnt, sclk;
 	int run;
 
-	cnt = t * get_sclk();
-	if (cnt < get_sclk()) {
-		printk(KERN_WARNING "NMI: timeout value is too large\n");
+	sclk = get_sclk();
+	cnt = t * sclk;
+	if (cnt < sclk) {
+		pr_warning("NMI: timeout value is too large\n");
 		return -EINVAL;
 	}
 
@@ -149,24 +151,59 @@
 	return 0;
 }
 
+int check_nmi_wdt_touched(void)
+{
+	unsigned int this_cpu = smp_processor_id();
+	unsigned int cpu;
+
+	cpumask_t mask = cpu_online_map;
+
+	if (!atomic_read(&nmi_touched[this_cpu]))
+		return 1;
+
+	atomic_set(&nmi_touched[this_cpu], 0);
+
+	cpu_clear(this_cpu, mask);
+	for_each_cpu_mask(cpu, mask) {
+		blackfin_dcache_invalidate_range(
+			(unsigned long)(&nmi_touched[cpu]),
+				(unsigned long)(&nmi_touched[cpu]));
+		if (!atomic_read(&nmi_touched[cpu]))
+			return 1;
+		atomic_set(&nmi_touched[cpu], 0);
+	}
+
+	return 0;
+}
+
+static void nmi_wdt_timer(void *data)
+{
+	if (!check_nmi_wdt_touched())
+		nmi_wdt_keepalive();
+
+	mod_timer(&ntimer, jiffies + NMI_CHECK_TIMEOUT);
+}
+
 static int __init init_nmi_wdt(void)
 {
 	nmi_wdt_set_timeout(timeout);
 	nmi_wdt_start();
 	nmi_active = true;
-	printk(KERN_INFO "nmi_wdt: initialized: timeout=%d sec\n", timeout);
+
+	init_timer(&ntimer);
+	ntimer.function = (void *)nmi_wdt_timer;
+	ntimer.expires = jiffies + NMI_CHECK_TIMEOUT;
+	add_timer(&ntimer);
+
+	pr_info("nmi_wdt: initialized: timeout=%d sec\n", timeout);
 	return 0;
 }
 device_initcall(init_nmi_wdt);
 
-static int __init setup_nmi_watchdog(char *str)
+void touch_nmi_watchdog(void)
 {
-	if (!strncmp(str, "panic", 5))
-		panic_on_timeout = true;
-
-	return 1;
+	atomic_set(&nmi_touched[smp_processor_id()], 1);
 }
-__setup("nmi_watchdog=", setup_nmi_watchdog);
 
 /* Suspend/resume support */
 #ifdef CONFIG_PM
@@ -211,27 +248,6 @@
 #endif	/* CONFIG_PM */
 
 
-void touch_nmi_watchdog(void)
-{
-	nmi_wdt_keepalive();
-}
-
-void check_nmi_watchdog(unsigned int cpu)
-{
-	atomic_set(&nmi_touched[cpu], 1);
-
-	blackfin_dcache_invalidate_range(
-		(unsigned long)(&nmi_touched[1 - cpu]),
-			(unsigned long)(&nmi_touched[1 - cpu]));
-
-	if (atomic_read(&nmi_touched[0]) == 1 &&
-			atomic_read(&nmi_touched[1]) == 1) {
-		atomic_set(&nmi_touched[0], 0);
-		atomic_set(&nmi_touched[1], 0);
-		touch_nmi_watchdog();
-	}
-}
-
 asmlinkage notrace void do_nmi(struct pt_regs *fp)
 {
 	unsigned int cpu = smp_processor_id();
@@ -268,18 +284,15 @@
 		set_nmi_event(COREA_ENTER_NMI);
 	}
 
-	printk(KERN_EMERG "NMI Watchdog detected LOCKUP, dump for CPU %d\n",
-							smp_processor_id());
+	pr_emerg("\nNMI Watchdog detected LOCKUP, dump for CPU %d\n", cpu);
 	dump_bfin_process(fp);
 	dump_bfin_mem(fp);
 	show_regs(fp);
 	dump_bfin_trace_buffer();
 	show_stack(current, (unsigned long *)fp);
-	printk(KERN_EMERG "\n\n");
 
 	if (cpu == nmi_wdt_cpu) {
-		if (!panic_on_timeout)
-			nmi_wdt_start();
+		pr_emerg("This fault is not recoverable, sorry!\n");
 
 		/* CoreA dump finished, restore the corelock */
 		restore_corelock();
@@ -293,7 +306,5 @@
 		wait_nmi_event(COREB_EXIT_NMI);
 	}
 
-	while (panic_on_timeout)
-			barrier();
 	nmi_exit();
 }

Modified: trunk/arch/blackfin/kernel/time-ts.c (8213 => 8214)


--- trunk/arch/blackfin/kernel/time-ts.c	2010-01-21 09:18:51 UTC (rev 8213)
+++ trunk/arch/blackfin/kernel/time-ts.c	2010-01-21 09:27:39 UTC (rev 8214)
@@ -315,7 +315,7 @@
 	smp_mb();
 	evt->event_handler(evt);
 
-	check_nmi_watchdog(cpu);
+	touch_nmi_watchdog();
 
 	return IRQ_HANDLED;
 }

Modified: trunk/arch/blackfin/mach-common/interrupt.S (8213 => 8214)


--- trunk/arch/blackfin/mach-common/interrupt.S	2010-01-21 09:18:51 UTC (rev 8213)
+++ trunk/arch/blackfin/mach-common/interrupt.S	2010-01-21 09:27:39 UTC (rev 8214)
@@ -201,6 +201,7 @@
 #ifndef CONFIG_NMI_WATCHDOG
 .weak _evt_nmi
 #else
+	/* Not take account of CPLBs, this handler will not return */
 	SAVE_ALL_SYS
 	r0 = sp;
 	r1 = retn;
@@ -209,45 +210,11 @@
 
 	ANOMALY_283_315_WORKAROUND(p4, r5)
 
-	/* Turn caches off, to ensure we don't get double exceptions */
-	P4.L = LO(IMEM_CONTROL);
-	P4.H = HI(IMEM_CONTROL);
-	R5 = [P4];
-	[--SP] = R5;
-	BITCLR(R5,ENICPLB_P);
-	CSYNC;
-	[P4] = R5;
-	SSYNC;
-
-	P4.L = LO(DMEM_CONTROL);
-	P4.H = HI(DMEM_CONTROL);
-	R5 = [P4];
-	[--SP] = R5;
-	BITCLR(R5,ENDCPLB_P);
-	CSYNC;
-	[P4] = R5;
-	SSYNC;
-
 	SP += -12;
 	call _do_nmi;
 	SP += 12;
-
-	R5 = [SP++];
-	P4.L = LO(DMEM_CONTROL);
-	P4.H = HI(DMEM_CONTROL);
-	CSYNC;
-	[P4] = R5;
-	SSYNC;
-
-	R5 = [SP++];
-	P4.L = LO(IMEM_CONTROL);
-	P4.H = HI(IMEM_CONTROL);
-	CSYNC;
-	[P4] = R5;
-	SSYNC;
-
-	trace_buffer_restore(p4, r5);
-	RESTORE_ALL_SYS
+1:
+	jump 1b;
 #endif
 	rtn;
 ENDPROC(_evt_nmi)
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to