#include <linux/reboot.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
+#include <asm/kdebug.h>
 #include <asm/uaccess.h>
 #include "xpc.h"
 
        .notifier_call = xpc_system_reboot,
 };
 
+static int xpc_system_die(struct notifier_block *, unsigned long, void *);
+static struct notifier_block xpc_die_notifier = {
+       .notifier_call = xpc_system_die,
+};
+
 
 /*
  * Timer function to enforce the timelimit on the partition disengage request.
        /* take ourselves off of the reboot_notifier_list */
        (void) unregister_reboot_notifier(&xpc_reboot_notifier);
 
+       /* take ourselves off of the die_notifier list */
+       (void) unregister_die_notifier(&xpc_die_notifier);
+
        /* close down protections for IPI operations */
        xpc_restrict_IPI_ops();
 
 }
 
 
+/*
+ * Called when the system is about to be either restarted or halted.
+ */
+static void
+xpc_die_disengage(void)
+{
+       struct xpc_partition *part;
+       partid_t partid;
+       unsigned long engaged;
+       long time, print_time, disengage_request_timeout;
+
+
+       /* keep xpc_hb_checker thread from doing anything (just in case) */
+       xpc_exiting = 1;
+
+       xpc_vars->heartbeating_to_mask = 0;  /* indicate we're deactivated */
+
+       for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+               part = &xpc_partitions[partid];
+
+               if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+                                                       remote_vars_version)) {
+
+                       /* just in case it was left set by an earlier XPC */
+                       xpc_clear_partition_engaged(1UL << partid);
+                       continue;
+               }
+
+               if (xpc_partition_engaged(1UL << partid) ||
+                                       part->act_state != XPC_P_INACTIVE) {
+                       xpc_request_partition_disengage(part);
+                       xpc_mark_partition_disengaged(part);
+                       xpc_IPI_send_disengage(part);
+               }
+       }
+
+       print_time = rtc_time();
+       disengage_request_timeout = print_time +
+               (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
+
+       /* wait for all other partitions to disengage from us */
+
+       while ((engaged = xpc_partition_engaged(-1UL)) &&
+                       (time = rtc_time()) < disengage_request_timeout) {
+
+               if (time >= print_time) {
+                       dev_info(xpc_part, "waiting for remote partitions to "
+                               "disengage, engaged=0x%lx\n", engaged);
+                       print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL *
+                                               sn_rtc_cycles_per_second);
+               }
+       }
+       dev_info(xpc_part, "finished waiting for remote partitions to "
+                               "disengage, engaged=0x%lx\n", engaged);
+}
+
+
 /*
  * This function is called when the system is being rebooted.
  */
 }
 
 
+/*
+ * This function is called when the system is being rebooted.
+ */
+static int
+xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
+{
+       switch (event) {
+       case DIE_MACHINE_RESTART:
+       case DIE_MACHINE_HALT:
+               xpc_die_disengage();
+               break;
+       case DIE_MCA_MONARCH_ENTER:
+       case DIE_INIT_MONARCH_ENTER:
+               xpc_vars->heartbeat++;
+               xpc_vars->heartbeat_offline = 1;
+               break;
+       case DIE_MCA_MONARCH_LEAVE:
+       case DIE_INIT_MONARCH_LEAVE:
+               xpc_vars->heartbeat++;
+               xpc_vars->heartbeat_offline = 0;
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+
 int __init
 xpc_init(void)
 {
                dev_warn(xpc_part, "can't register reboot notifier\n");
        }
 
+       /* add ourselves to the die_notifier list (i.e., ia64die_chain) */
+       ret = register_die_notifier(&xpc_die_notifier);
+       if (ret != 0) {
+               dev_warn(xpc_part, "can't register die notifier\n");
+       }
+
 
        /*
         * Set the beating to other partitions into motion.  This is
                /* take ourselves off of the reboot_notifier_list */
                (void) unregister_reboot_notifier(&xpc_reboot_notifier);
 
+               /* take ourselves off of the die_notifier list */
+               (void) unregister_die_notifier(&xpc_die_notifier);
+
                del_timer_sync(&xpc_hb_timer);
                free_irq(SGI_XPC_ACTIVATE, NULL);
                xpc_restrict_IPI_ops();
 
                }
 
                dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
-                       " = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid,
-                       remote_vars->heartbeat, part->last_heartbeat,
-                       remote_vars->kdb_status,
+                       " = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n",
+                       partid, remote_vars->heartbeat, part->last_heartbeat,
+                       remote_vars->heartbeat_offline,
                        remote_vars->heartbeating_to_mask);
 
                if (((remote_vars->heartbeat == part->last_heartbeat) &&
-                       (remote_vars->kdb_status == 0)) ||
+                       (remote_vars->heartbeat_offline == 0)) ||
                             !xpc_hb_allowed(sn_partition_id, remote_vars)) {
 
                        XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);