aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMurali Karicheri2015-01-26 15:28:41 -0600
committerMurali Karicheri2015-01-30 16:57:09 -0600
commit8b20fd9a5e08f76cc7ae671f271f59e45bb02279 (patch)
treee0757479ba32ce6549b8f7e4b9a0771d496b8e12
parent6e06c6e6c72581cbeeb4dadfd38096db83435c00 (diff)
downloadlinux-8b20fd9a5e08f76cc7ae671f271f59e45bb02279.tar.gz
linux-8b20fd9a5e08f76cc7ae671f271f59e45bb02279.tar.xz
linux-8b20fd9a5e08f76cc7ae671f271f59e45bb02279.zip
ARM: keystone: add a work around to handle external abort
Currently on some devices, an async external abort happens first time exception handlers are enabled in kernel before switching to user space. This patch add a workaround to handle this once and allow any subsequent faults to be caught by the handler. Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
-rw-r--r--arch/arm/mach-keystone/keystone.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index 05f220211fc..d831ca983bc 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -28,6 +28,7 @@
28#include <linux/irqchip.h> 28#include <linux/irqchip.h>
29#include <linux/platform_data/davinci-clock.h> 29#include <linux/platform_data/davinci-clock.h>
30#include <linux/reboot.h> 30#include <linux/reboot.h>
31#include <linux/signal.h>
31 32
32#include <asm/setup.h> 33#include <asm/setup.h>
33#include <asm/smp_plat.h> 34#include <asm/smp_plat.h>
@@ -83,6 +84,24 @@ static bool is_coherent(struct device *dev)
83 return false; 84 return false;
84} 85}
85 86
87static bool ignore_first = true;
88static int keystone_async_ext_abort_fault(unsigned long addr, unsigned int fsr,
89 struct pt_regs *regs)
90{
91 /*
92 * if first time, ignore this as this seems to be a spurious one
93 * happening on some devices and we add this work around to handle
94 * this first time when kernel switch to handle user space
95 */
96 if (ignore_first) {
97 ignore_first = false;
98 return 0;
99 }
100
101 /* Subsequent ones should be handled as fault */
102 return 1;
103}
104
86static int keystone_platform_notifier(struct notifier_block *nb, 105static int keystone_platform_notifier(struct notifier_block *nb,
87 unsigned long event, void *_dev) 106 unsigned long event, void *_dev)
88{ 107{
@@ -118,6 +137,13 @@ static void __init keystone_init(void)
118 137
119 keystone_pm_runtime_init(); 138 keystone_pm_runtime_init();
120 of_platform_populate(NULL, keystone_dt_match_table, NULL, NULL); 139 of_platform_populate(NULL, keystone_dt_match_table, NULL, NULL);
140
141 /*
142 * Add a one time exception handler to catch asynchronous external
143 * abort when transitioning to use space
144 */
145 hook_fault_code(17, keystone_async_ext_abort_fault, SIGBUS, 0,
146 "async external abort handler");
121} 147}
122 148
123#define L2_INTERN_ASYNC_ERROR BIT(30) 149#define L2_INTERN_ASYNC_ERROR BIT(30)