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. */
 
        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;
        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)
                       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 */