diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2016-01-31 15:29:27 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2016-05-13 08:01:55 -0400 |
commit | c400d5ebec1828ee00acb53890741a62b45fb23b (patch) | |
tree | 1acd18acb2b8dfe04181ac85624ac41892f27257 | |
parent | 885872b722b73b2026a48bdff4621f289be2b044 (diff) |
BUS: brcmstb_gisb: Hook to MIPS board_be_handler
MIPS kernels allow platforms to invoke a custom Bus Error handler, add the
necessary code to do this for Broadcom SoCs where the GISB bus error handler can be used.
We may get a bus error from an address decoded outside of the GISB bus space,
so we need to check the validity of such a capture before printing anything.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Cc: cernekee@gmail.com
Cc: arnd@arndb.de
Cc: jaedon.shin@gmail.com
Cc: pgynther@google.com
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12284/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | drivers/bus/brcmstb_gisb.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index f364fa4d24eb..72fe0a5a8bf3 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c | |||
@@ -30,6 +30,10 @@ | |||
30 | #include <asm/signal.h> | 30 | #include <asm/signal.h> |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #ifdef CONFIG_MIPS | ||
34 | #include <asm/traps.h> | ||
35 | #endif | ||
36 | |||
33 | #define ARB_ERR_CAP_CLEAR (1 << 0) | 37 | #define ARB_ERR_CAP_CLEAR (1 << 0) |
34 | #define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12) | 38 | #define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12) |
35 | #define ARB_ERR_CAP_STATUS_TEA (1 << 11) | 39 | #define ARB_ERR_CAP_STATUS_TEA (1 << 11) |
@@ -238,6 +242,29 @@ static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr, | |||
238 | } | 242 | } |
239 | #endif | 243 | #endif |
240 | 244 | ||
245 | #ifdef CONFIG_MIPS | ||
246 | static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup) | ||
247 | { | ||
248 | int ret = 0; | ||
249 | struct brcmstb_gisb_arb_device *gdev; | ||
250 | u32 cap_status; | ||
251 | |||
252 | list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) { | ||
253 | cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS); | ||
254 | |||
255 | /* Invalid captured address, bail out */ | ||
256 | if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) { | ||
257 | is_fixup = 1; | ||
258 | goto out; | ||
259 | } | ||
260 | |||
261 | ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error"); | ||
262 | } | ||
263 | out: | ||
264 | return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL; | ||
265 | } | ||
266 | #endif | ||
267 | |||
241 | static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id) | 268 | static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id) |
242 | { | 269 | { |
243 | brcmstb_gisb_arb_decode_addr(dev_id, "timeout"); | 270 | brcmstb_gisb_arb_decode_addr(dev_id, "timeout"); |
@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) | |||
355 | hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0, | 382 | hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0, |
356 | "imprecise external abort"); | 383 | "imprecise external abort"); |
357 | #endif | 384 | #endif |
385 | #ifdef CONFIG_MIPS | ||
386 | board_be_handler = brcmstb_bus_error_handler; | ||
387 | #endif | ||
358 | 388 | ||
359 | dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n", | 389 | dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n", |
360 | gdev->base, timeout_irq, tea_irq); | 390 | gdev->base, timeout_irq, tea_irq); |