/*
 * Start the process of deactivating the specified partition.
 */
void
xpc_deactivate_partition(const int line, struct xpc_partition *part,
			 enum xp_retval reason)
{
	unsigned long irq_flags;

	spin_lock_irqsave(&part->act_lock, irq_flags);

	if (part->act_state == XPC_P_AS_INACTIVE) {
		XPC_SET_REASON(part, reason, line);
		spin_unlock_irqrestore(&part->act_lock, irq_flags);
		if (reason == xpReactivating) {
			/* we interrupt ourselves to reactivate partition */
			xpc_request_partition_reactivation(part);
		}
		return;
	}
	if (part->act_state == XPC_P_AS_DEACTIVATING) {
		if ((part->reason == xpUnloading && reason != xpUnloading) ||
		    reason == xpReactivating) {
			XPC_SET_REASON(part, reason, line);
		}
		spin_unlock_irqrestore(&part->act_lock, irq_flags);
		return;
	}

	part->act_state = XPC_P_AS_DEACTIVATING;
	XPC_SET_REASON(part, reason, line);

	spin_unlock_irqrestore(&part->act_lock, irq_flags);

	/* ask remote partition to deactivate with regard to us */
	xpc_request_partition_deactivation(part);

	/* set a timelimit on the disengage phase of the deactivation request */
	part->disengage_timeout = jiffies + (xpc_disengage_timelimit * HZ);
	part->disengage_timer.expires = part->disengage_timeout;
	add_timer(&part->disengage_timer);

	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
		XPC_PARTID(part), reason);

	xpc_partition_going_down(part, reason);
}
Exemple #2
0
/*
 * Notify other partitions to deactivate from us by first disengaging from all
 * references to our memory.
 */
static void
xpc_die_deactivate(void)
{
	struct xpc_partition *part;
	short partid;
	int any_engaged;
	long keep_waiting;
	long wait_to_print;

	/* keep xpc_hb_checker thread from doing anything (just in case) */
	xpc_exiting = 1;

	xpc_disallow_all_hbs();	/*indicate we're deactivated */

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

		if (xpc_partition_engaged(partid) ||
		    part->act_state != XPC_P_AS_INACTIVE) {
			xpc_request_partition_deactivation(part);
			xpc_indicate_partition_disengaged(part);
		}
	}

	/*
	 * Though we requested that all other partitions deactivate from us,
	 * we only wait until they've all disengaged or we've reached the
	 * defined timelimit.
	 *
	 * Given that one iteration through the following while-loop takes
	 * approximately 200 microseconds, calculate the #of loops to take
	 * before bailing and the #of loops before printing a waiting message.
	 */
	keep_waiting = xpc_disengage_timelimit * 1000 * 5;
	wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL * 1000 * 5;

	while (1) {
		any_engaged = xpc_any_partition_engaged();
		if (!any_engaged) {
			dev_info(xpc_part, "all partitions have deactivated\n");
			break;
		}

		if (!keep_waiting--) {
			for (partid = 0; partid < xp_max_npartitions;
			     partid++) {
				if (xpc_partition_engaged(partid)) {
					dev_info(xpc_part, "deactivate from "
						 "remote partition %d timed "
						 "out\n", partid);
				}
			}
			break;
		}

		if (!wait_to_print--) {
			dev_info(xpc_part, "waiting for remote partitions to "
				 "deactivate, timeout in %ld seconds\n",
				 keep_waiting / (1000 * 5));
			wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL *
			    1000 * 5;
		}

		udelay(200);
	}
}