]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
brcmfmac: check and dump trap info during sdio probe
authorArend van Spriel <arend.vanspriel@broadcom.com>
Thu, 14 Feb 2019 12:43:51 +0000 (13:43 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 19 Feb 2019 15:04:55 +0000 (17:04 +0200)
When the firmware crashes during the probe sequence we provide little
information on what really failed. This patch checks the sdpcm shared
location and show the trap information if a firmware trap has happened.

Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c

index 5f9de618c6795c141815657ff0e1ed9ca82741a5..4d104ab80fd8ec9bf7c68583c46cca7f2962fe39 100644 (file)
@@ -2999,21 +2999,35 @@ static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
        if (error < 0)
                return error;
 
-       seq_printf(seq,
-                  "dongle trap info: type 0x%x @ epc 0x%08x\n"
-                  "  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
-                  "  lr   0x%08x pc   0x%08x offset 0x%x\n"
-                  "  r0   0x%08x r1   0x%08x r2 0x%08x r3 0x%08x\n"
-                  "  r4   0x%08x r5   0x%08x r6 0x%08x r7 0x%08x\n",
-                  le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
-                  le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
-                  le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
-                  le32_to_cpu(tr.pc), sh->trap_addr,
-                  le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
-                  le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
-                  le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
-                  le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
-
+       if (seq)
+               seq_printf(seq,
+                          "dongle trap info: type 0x%x @ epc 0x%08x\n"
+                          "  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+                          "  lr   0x%08x pc   0x%08x offset 0x%x\n"
+                          "  r0   0x%08x r1   0x%08x r2 0x%08x r3 0x%08x\n"
+                          "  r4   0x%08x r5   0x%08x r6 0x%08x r7 0x%08x\n",
+                          le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+                          le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+                          le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+                          le32_to_cpu(tr.pc), sh->trap_addr,
+                          le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+                          le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+                          le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+                          le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
+       else
+               pr_debug("dongle trap info: type 0x%x @ epc 0x%08x\n"
+                        "  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+                        "  lr   0x%08x pc   0x%08x offset 0x%x\n"
+                        "  r0   0x%08x r1   0x%08x r2 0x%08x r3 0x%08x\n"
+                        "  r4   0x%08x r5   0x%08x r6 0x%08x r7 0x%08x\n",
+                        le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+                        le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+                        le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+                        le32_to_cpu(tr.pc), sh->trap_addr,
+                        le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+                        le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+                        le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+                        le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
        return 0;
 }
 
@@ -3067,8 +3081,10 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
        else if (sh.flags & SDPCM_SHARED_ASSERT)
                brcmf_err("assertion in dongle\n");
 
-       if (sh.flags & SDPCM_SHARED_TRAP)
+       if (sh.flags & SDPCM_SHARED_TRAP) {
                brcmf_err("firmware trap in dongle\n");
+               brcmf_sdio_trap_info(NULL, bus, &sh);
+       }
 
        return 0;
 }
@@ -4199,7 +4215,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
        } else {
                /* Disable F2 again */
                sdio_disable_func(sdiod->func2);
-               goto release;
+               goto checkdied;
        }
 
        if (brcmf_chip_sr_capable(bus->ci)) {
@@ -4220,8 +4236,10 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
        }
 
        /* If we didn't come up, turn off backplane clock */
-       if (err != 0)
+       if (err != 0) {
                brcmf_sdio_clkctl(bus, CLK_NONE, false);
+               goto checkdied;
+       }
 
        sdio_release_host(sdiod->func1);
 
@@ -4235,12 +4253,15 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
        err = brcmf_attach(sdiod->dev, sdiod->settings);
        if (err != 0) {
                brcmf_err("brcmf_attach failed\n");
-               goto fail;
+               sdio_claim_host(sdiod->func1);
+               goto checkdied;
        }
 
        /* ready */
        return;
 
+checkdied:
+       brcmf_sdio_checkdied(bus);
 release:
        sdio_release_host(sdiod->func1);
 fail: