Commit c400d5eb authored by Florian Fainelli's avatar Florian Fainelli Committed by Ralf Baechle

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: default avatarFlorian 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 885872b7
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <asm/signal.h> #include <asm/signal.h>
#endif #endif
#ifdef CONFIG_MIPS
#include <asm/traps.h>
#endif
#define ARB_ERR_CAP_CLEAR (1 << 0) #define ARB_ERR_CAP_CLEAR (1 << 0)
#define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12) #define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12)
#define ARB_ERR_CAP_STATUS_TEA (1 << 11) #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,6 +242,29 @@ static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
} }
#endif #endif
#ifdef CONFIG_MIPS
static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup)
{
int ret = 0;
struct brcmstb_gisb_arb_device *gdev;
u32 cap_status;
list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) {
cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
/* Invalid captured address, bail out */
if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) {
is_fixup = 1;
goto out;
}
ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error");
}
out:
return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
}
#endif
static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id) static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
{ {
brcmstb_gisb_arb_decode_addr(dev_id, "timeout"); brcmstb_gisb_arb_decode_addr(dev_id, "timeout");
...@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) ...@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0, hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
"imprecise external abort"); "imprecise external abort");
#endif #endif
#ifdef CONFIG_MIPS
board_be_handler = brcmstb_bus_error_handler;
#endif
dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n", dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
gdev->base, timeout_irq, tea_irq); gdev->base, timeout_irq, tea_irq);
......
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