Commit d6517c4c authored by Jesper Nilsson's avatar Jesper Nilsson

CRISv32: Better handling of watchdog bite

Don't enter watchdog handling if we're already in watchdog handling.

Also some minor formatting tweaks.
Signed-off-by: default avatarJesper Nilsson <jesper.nilsson@axis.com>
parent dbd3c7e1
...@@ -57,7 +57,6 @@ static int __init etrax_init_cont_rotime(void) ...@@ -57,7 +57,6 @@ static int __init etrax_init_cont_rotime(void)
} }
arch_initcall(etrax_init_cont_rotime); arch_initcall(etrax_init_cont_rotime);
unsigned long timer_regs[NR_CPUS] = unsigned long timer_regs[NR_CPUS] =
{ {
regi_timer0, regi_timer0,
...@@ -69,9 +68,8 @@ unsigned long timer_regs[NR_CPUS] = ...@@ -69,9 +68,8 @@ unsigned long timer_regs[NR_CPUS] =
extern int set_rtc_mmss(unsigned long nowtime); extern int set_rtc_mmss(unsigned long nowtime);
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
static int static int cris_time_freq_notifier(struct notifier_block *nb,
cris_time_freq_notifier(struct notifier_block *nb, unsigned long val, unsigned long val, void *data);
void *data);
static struct notifier_block cris_time_freq_notifier_block = { static struct notifier_block cris_time_freq_notifier_block = {
.notifier_call = cris_time_freq_notifier, .notifier_call = cris_time_freq_notifier,
...@@ -88,7 +86,6 @@ unsigned long get_ns_in_jiffie(void) ...@@ -88,7 +86,6 @@ unsigned long get_ns_in_jiffie(void)
return ns; return ns;
} }
/* From timer MDS describing the hardware watchdog: /* From timer MDS describing the hardware watchdog:
* 4.3.1 Watchdog Operation * 4.3.1 Watchdog Operation
* The watchdog timer is an 8-bit timer with a configurable start value. * The watchdog timer is an 8-bit timer with a configurable start value.
...@@ -110,11 +107,18 @@ static short int watchdog_key = 42; /* arbitrary 7 bit number */ ...@@ -110,11 +107,18 @@ static short int watchdog_key = 42; /* arbitrary 7 bit number */
* is used though, so set this really low. */ * is used though, so set this really low. */
#define WATCHDOG_MIN_FREE_PAGES 8 #define WATCHDOG_MIN_FREE_PAGES 8
/* for reliable NICE_DOGGY behaviour */
static int bite_in_progress;
void reset_watchdog(void) void reset_watchdog(void)
{ {
#if defined(CONFIG_ETRAX_WATCHDOG) #if defined(CONFIG_ETRAX_WATCHDOG)
reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; reg_timer_rw_wd_ctrl wd_ctrl = { 0 };
#if defined(CONFIG_ETRAX_WATCHDOG_NICE_DOGGY)
if (unlikely(bite_in_progress))
return;
#endif
/* Only keep watchdog happy as long as we have memory left! */ /* Only keep watchdog happy as long as we have memory left! */
if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
/* Reset the watchdog with the inverse of the old key */ /* Reset the watchdog with the inverse of the old key */
...@@ -149,7 +153,9 @@ void handle_watchdog_bite(struct pt_regs *regs) ...@@ -149,7 +153,9 @@ void handle_watchdog_bite(struct pt_regs *regs)
#if defined(CONFIG_ETRAX_WATCHDOG) #if defined(CONFIG_ETRAX_WATCHDOG)
extern int cause_of_death; extern int cause_of_death;
nmi_enter();
oops_in_progress = 1; oops_in_progress = 1;
bite_in_progress = 1;
printk(KERN_WARNING "Watchdog bite\n"); printk(KERN_WARNING "Watchdog bite\n");
/* Check if forced restart or unexpected watchdog */ /* Check if forced restart or unexpected watchdog */
...@@ -171,6 +177,7 @@ void handle_watchdog_bite(struct pt_regs *regs) ...@@ -171,6 +177,7 @@ void handle_watchdog_bite(struct pt_regs *regs)
printk(KERN_WARNING "Oops: bitten by watchdog\n"); printk(KERN_WARNING "Oops: bitten by watchdog\n");
show_registers(regs); show_registers(regs);
oops_in_progress = 0; oops_in_progress = 0;
printk("\n"); /* Flush mtdoops. */
#ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY #ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
reset_watchdog(); reset_watchdog();
#endif #endif
...@@ -203,7 +210,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id) ...@@ -203,7 +210,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
/* Reset watchdog otherwise it resets us! */ /* Reset watchdog otherwise it resets us! */
reset_watchdog(); reset_watchdog();
/* Update statistics. */ /* Update statistics. */
update_process_times(user_mode(regs)); update_process_times(user_mode(regs));
cris_do_profile(regs); /* Save profiling information */ cris_do_profile(regs); /* Save profiling information */
...@@ -214,7 +221,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id) ...@@ -214,7 +221,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
/* Call the real timer interrupt handler */ /* Call the real timer interrupt handler */
xtime_update(1); xtime_update(1);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */ /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */
...@@ -294,14 +301,13 @@ void __init time_init(void) ...@@ -294,14 +301,13 @@ void __init time_init(void)
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&cris_time_freq_notifier_block, cpufreq_register_notifier(&cris_time_freq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
#endif #endif
} }
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
static int static int cris_time_freq_notifier(struct notifier_block *nb,
cris_time_freq_notifier(struct notifier_block *nb, unsigned long val, unsigned long val, void *data)
void *data)
{ {
struct cpufreq_freqs *freqs = data; struct cpufreq_freqs *freqs = data;
if (val == CPUFREQ_POSTCHANGE) { if (val == CPUFREQ_POSTCHANGE) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment