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