static void
xpc_do_exit(enum xp_retval reason)
{
	short partid;
	int active_part_count, printed_waiting_msg = 0;
	struct xpc_partition *part;
	unsigned long printmsg_time, disengage_timeout = 0;

	/*                                                               */
	DBUG_ON(xpc_exiting == 1);

	/*
                                                             
                                                                
                                                       
  */
	xpc_exiting = 1;
	wake_up_interruptible(&xpc_activate_IRQ_wq);

	/*                                       */
	wait_for_completion(&xpc_discovery_exited);

	/*                                               */
	wait_for_completion(&xpc_hb_checker_exited);

	/*                                   */
	(void)msleep_interruptible(300);

	/*                                            */

	printmsg_time = jiffies + (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ);
	xpc_disengage_timedout = 0;

	do {
		active_part_count = 0;

		for (partid = 0; partid < xp_max_npartitions; partid++) {
			part = &xpc_partitions[partid];

			if (xpc_partition_disengaged(part) &&
			    part->act_state == XPC_P_AS_INACTIVE) {
				continue;
			}

			active_part_count++;

			XPC_DEACTIVATE_PARTITION(part, reason);

			if (part->disengage_timeout > disengage_timeout)
				disengage_timeout = part->disengage_timeout;
		}

		if (xpc_arch_ops.any_partition_engaged()) {
			if (time_is_before_jiffies(printmsg_time)) {
				dev_info(xpc_part, "waiting for remote "
					 "partitions to deactivate, timeout in "
					 "%ld seconds\n", (disengage_timeout -
					 jiffies) / HZ);
				printmsg_time = jiffies +
				    (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ);
				printed_waiting_msg = 1;
			}

		} else if (active_part_count > 0) {
			if (printed_waiting_msg) {
				dev_info(xpc_part, "waiting for local partition"
					 " to deactivate\n");
				printed_waiting_msg = 0;
			}

		} else {
			if (!xpc_disengage_timedout) {
				dev_info(xpc_part, "all partitions have "
					 "deactivated\n");
			}
			break;
		}

		/*                                   */
		(void)msleep_interruptible(300);

	} while (1);

	DBUG_ON(xpc_arch_ops.any_partition_engaged());

	xpc_teardown_rsvd_page();

	if (reason == xpUnloading) {
		(void)unregister_die_notifier(&xpc_die_notifier);
		(void)unregister_reboot_notifier(&xpc_reboot_notifier);
	}

	/*                                        */
	xpc_clear_interface();

	if (xpc_sysctl)
		unregister_sysctl_table(xpc_sysctl);

	xpc_teardown_partitions();

	if (is_shub())
		xpc_exit_sn2();
	else if (is_uv())
		xpc_exit_uv();
}
Example #2
0
static void
xpc_do_exit(enum xp_retval reason)
{
	short partid;
	int active_part_count, printed_waiting_msg = 0;
	struct xpc_partition *part;
	unsigned long printmsg_time, disengage_timeout = 0;

	/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
	DBUG_ON(xpc_exiting == 1);

	/*
	 * Let the heartbeat checker thread and the discovery thread
	 * (if one is running) know that they should exit. Also wake up
	 * the heartbeat checker thread in case it's sleeping.
	 */
	xpc_exiting = 1;
	wake_up_interruptible(&xpc_activate_IRQ_wq);

	/* wait for the discovery thread to exit */
	wait_for_completion(&xpc_discovery_exited);

	/* wait for the heartbeat checker thread to exit */
	wait_for_completion(&xpc_hb_checker_exited);

	/* sleep for a 1/3 of a second or so */
	(void)msleep_interruptible(300);

	/* wait for all partitions to become inactive */

	printmsg_time = jiffies + (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ);
	xpc_disengage_timedout = 0;

	do {
		active_part_count = 0;

		for (partid = 0; partid < xp_max_npartitions; partid++) {
			part = &xpc_partitions[partid];

			if (xpc_partition_disengaged(part) &&
			    part->act_state == XPC_P_AS_INACTIVE) {
				continue;
			}

			active_part_count++;

			XPC_DEACTIVATE_PARTITION(part, reason);

			if (part->disengage_timeout > disengage_timeout)
				disengage_timeout = part->disengage_timeout;
		}

		if (xpc_any_partition_engaged()) {
			if (time_is_before_jiffies(printmsg_time)) {
				dev_info(xpc_part, "waiting for remote "
					 "partitions to deactivate, timeout in "
					 "%ld seconds\n", (disengage_timeout -
					 jiffies) / HZ);
				printmsg_time = jiffies +
				    (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ);
				printed_waiting_msg = 1;
			}

		} else if (active_part_count > 0) {
			if (printed_waiting_msg) {
				dev_info(xpc_part, "waiting for local partition"
					 " to deactivate\n");
				printed_waiting_msg = 0;
			}

		} else {
			if (!xpc_disengage_timedout) {
				dev_info(xpc_part, "all partitions have "
					 "deactivated\n");
			}
			break;
		}

		/* sleep for a 1/3 of a second or so */
		(void)msleep_interruptible(300);

	} while (1);

	DBUG_ON(xpc_any_partition_engaged());
	DBUG_ON(xpc_any_hbs_allowed() != 0);

	xpc_teardown_rsvd_page();

	if (reason == xpUnloading) {
		(void)unregister_die_notifier(&xpc_die_notifier);
		(void)unregister_reboot_notifier(&xpc_reboot_notifier);
	}

	/* clear the interface to XPC's functions */
	xpc_clear_interface();

	if (xpc_sysctl)
		unregister_sysctl_table(xpc_sysctl);

	xpc_teardown_partitions();

	if (is_shub())
		xpc_exit_sn2();
	else if (is_uv())
		xpc_exit_uv();
}
Example #3
0
static void
xpc_do_exit(enum xp_retval reason)
{
    short partid;
    int active_part_count, printed_waiting_msg = 0;
    struct xpc_partition *part;
    unsigned long printmsg_time, disengage_request_timeout = 0;

    /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
    DBUG_ON(xpc_exiting == 1);

    /*
     * Let the heartbeat checker thread and the discovery thread
     * (if one is running) know that they should exit. Also wake up
     * the heartbeat checker thread in case it's sleeping.
     */
    xpc_exiting = 1;
    wake_up_interruptible(&xpc_act_IRQ_wq);

    /* ignore all incoming interrupts */
    free_irq(SGI_XPC_ACTIVATE, NULL);

    /* wait for the discovery thread to exit */
    wait_for_completion(&xpc_discovery_exited);

    /* wait for the heartbeat checker thread to exit */
    wait_for_completion(&xpc_hb_checker_exited);

    /* sleep for a 1/3 of a second or so */
    (void)msleep_interruptible(300);

    /* wait for all partitions to become inactive */

    printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
    xpc_disengage_request_timedout = 0;

    do {
        active_part_count = 0;

        for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
            part = &xpc_partitions[partid];

            if (xpc_partition_disengaged(part) &&
                    part->act_state == XPC_P_INACTIVE) {
                continue;
            }

            active_part_count++;

            XPC_DEACTIVATE_PARTITION(part, reason);

            if (part->disengage_request_timeout >
                    disengage_request_timeout) {
                disengage_request_timeout =
                    part->disengage_request_timeout;
            }
        }

        if (xpc_partition_engaged(-1UL)) {
            if (time_after(jiffies, printmsg_time)) {
                dev_info(xpc_part, "waiting for remote "
                         "partitions to disengage, timeout in "
                         "%ld seconds\n",
                         (disengage_request_timeout - jiffies)
                         / HZ);
                printmsg_time = jiffies +
                                (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
                printed_waiting_msg = 1;
            }

        } else if (active_part_count > 0) {
            if (printed_waiting_msg) {
                dev_info(xpc_part, "waiting for local partition"
                         " to disengage\n");
                printed_waiting_msg = 0;
            }

        } else {
            if (!xpc_disengage_request_timedout) {
                dev_info(xpc_part, "all partitions have "
                         "disengaged\n");
            }
            break;
        }

        /* sleep for a 1/3 of a second or so */
        (void)msleep_interruptible(300);

    } while (1);

    DBUG_ON(xpc_partition_engaged(-1UL));

    /* indicate to others that our reserved page is uninitialized */
    xpc_rsvd_page->vars_pa = 0;

    /* now it's time to eliminate our heartbeat */
    del_timer_sync(&xpc_hb_timer);
    DBUG_ON(xpc_vars->heartbeating_to_mask != 0);

    if (reason == xpUnloading) {
        /* 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();

    /* clear the interface to XPC's functions */
    xpc_clear_interface();

    if (xpc_sysctl)
        unregister_sysctl_table(xpc_sysctl);

    kfree(xpc_remote_copy_buffer_base);
}