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 /drivers/bus | |
| 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>
Diffstat (limited to 'drivers/bus')
| -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); |
