Commit afa83e23 authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

b43: Add panic reason code that doesn't trigger restart

Add a firmware panic reason code that doesn't trigger a restart.
This is useful for firmware debugging and avoiding endless
restart loops. We can use FWPANIC_DIE to halt the firmware at a
well defined point.
Signed-off-by: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 68217832
...@@ -422,12 +422,21 @@ enum { ...@@ -422,12 +422,21 @@ enum {
B43_IRQ_RFKILL | \ B43_IRQ_RFKILL | \
B43_IRQ_TX_OK) B43_IRQ_TX_OK)
/* The firmware register to fetch the debug-IRQ reason from. */
#define B43_DEBUGIRQ_REASON_REG 63
/* Debug-IRQ reasons. */ /* Debug-IRQ reasons. */
#define B43_DEBUGIRQ_PANIC 0 /* The firmware panic'ed */ #define B43_DEBUGIRQ_PANIC 0 /* The firmware panic'ed */
#define B43_DEBUGIRQ_DUMP_SHM 1 /* Dump shared SHM */ #define B43_DEBUGIRQ_DUMP_SHM 1 /* Dump shared SHM */
#define B43_DEBUGIRQ_DUMP_REGS 2 /* Dump the microcode registers */ #define B43_DEBUGIRQ_DUMP_REGS 2 /* Dump the microcode registers */
#define B43_DEBUGIRQ_ACK 0xFFFF /* The host writes that to ACK the IRQ */ #define B43_DEBUGIRQ_ACK 0xFFFF /* The host writes that to ACK the IRQ */
/* The firmware register to fetch the panic reason from. */
#define B43_FWPANIC_REASON_REG 3
/* Firmware panic reason codes */
#define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */
#define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */
/* Device specific rate values. /* Device specific rate values.
* The actual values defined here are (rate_in_mbps * 2). * The actual values defined here are (rate_in_mbps * 2).
* Some code depends on this. Don't change it. */ * Some code depends on this. Don't change it. */
......
...@@ -1662,6 +1662,30 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) ...@@ -1662,6 +1662,30 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
} }
static void b43_handle_firmware_panic(struct b43_wldev *dev)
{
u16 reason;
/* Read the register that contains the reason code for the panic. */
reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_FWPANIC_REASON_REG);
b43err(dev->wl, "Whoopsy, firmware panic! Reason: %u\n", reason);
switch (reason) {
default:
b43dbg(dev->wl, "The panic reason is unknown.\n");
/* fallthrough */
case B43_FWPANIC_DIE:
/* Do not restart the controller or firmware.
* The device is nonfunctional from now on.
* Restarting would result in this panic to trigger again,
* so we avoid that recursion. */
break;
case B43_FWPANIC_RESTART:
b43_controller_restart(dev, "Microcode panic");
break;
}
}
static void handle_irq_ucode_debug(struct b43_wldev *dev) static void handle_irq_ucode_debug(struct b43_wldev *dev)
{ {
unsigned int i, cnt; unsigned int i, cnt;
...@@ -1672,15 +1696,12 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev) ...@@ -1672,15 +1696,12 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev)
if (!dev->fw.opensource) if (!dev->fw.opensource)
return; return;
/* Microcode register 63 contains the debug-IRQ reason. */ /* Read the register that contains the reason code for this IRQ. */
reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 63); reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_DEBUGIRQ_REASON_REG);
switch (reason) { switch (reason) {
case B43_DEBUGIRQ_PANIC: case B43_DEBUGIRQ_PANIC:
/* The reason for the panic is in register 3. */ b43_handle_firmware_panic(dev);
reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 3);
b43err(dev->wl, "Whoopsy, the microcode panic'ed! Reason: %u\n",
reason);
b43_controller_restart(dev, "Microcode panic");
break; break;
case B43_DEBUGIRQ_DUMP_SHM: case B43_DEBUGIRQ_DUMP_SHM:
if (!B43_DEBUG) if (!B43_DEBUG)
...@@ -1721,7 +1742,9 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev) ...@@ -1721,7 +1742,9 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev)
reason); reason);
} }
out: out:
b43_shm_write16(dev, B43_SHM_SCRATCH, 63, B43_DEBUGIRQ_ACK); /* Acknowledge the debug-IRQ, so the firmware can continue. */
b43_shm_write16(dev, B43_SHM_SCRATCH,
B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK);
} }
/* Interrupt handler bottom-half */ /* Interrupt handler bottom-half */
......
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