b43: Add panic reason code that doesn't trigger restart
authorMichael Buesch <mb@bu3sch.de>
Mon, 19 May 2008 21:51:37 +0000 (23:51 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 22 May 2008 01:48:16 +0000 (21:48 -0400)
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: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/main.c

index f588dfa9c1d47c0805a1c8cfb47d37459ff0d794..f0041750355dad77c20dbcfec70ee0ae91fbaeae 100644 (file)
@@ -422,12 +422,21 @@ enum {
                                         B43_IRQ_RFKILL | \
                                         B43_IRQ_TX_OK)
 
+/* The firmware register to fetch the debug-IRQ reason from. */
+#define B43_DEBUGIRQ_REASON_REG                63
 /* Debug-IRQ reasons. */
 #define B43_DEBUGIRQ_PANIC             0       /* The firmware panic'ed */
 #define B43_DEBUGIRQ_DUMP_SHM          1       /* Dump shared SHM */
 #define B43_DEBUGIRQ_DUMP_REGS         2       /* Dump the microcode registers */
 #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.
  * The actual values defined here are (rate_in_mbps * 2).
  * Some code depends on this. Don't change it. */
index 6011747bb3b9fd5a85806efff9473beb8b47ee11..e1dfb40746766c0423ec3a88e0e39bbe5afbab41 100644 (file)
@@ -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);
 }
 
+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)
 {
        unsigned int i, cnt;
@@ -1672,15 +1696,12 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev)
        if (!dev->fw.opensource)
                return;
 
-       /* Microcode register 63 contains the debug-IRQ reason. */
-       reason = b43_shm_read16(dev, B43_SHM_SCRATCH, 63);
+       /* Read the register that contains the reason code for this IRQ. */
+       reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_DEBUGIRQ_REASON_REG);
+
        switch (reason) {
        case B43_DEBUGIRQ_PANIC:
-               /* The reason for the panic is in register 3. */
-               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");
+               b43_handle_firmware_panic(dev);
                break;
        case B43_DEBUGIRQ_DUMP_SHM:
                if (!B43_DEBUG)
@@ -1721,7 +1742,9 @@ static void handle_irq_ucode_debug(struct b43_wldev *dev)
                       reason);
        }
 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 */