/* * When XPC HB determines that a partition has come up, it will create a new * kthread and that kthread will call this function to attempt to set up the * basic infrastructure used for Cross Partition Communication with the newly * upped partition. * * The kthread that was created by XPC HB and which setup the XPC * infrastructure will remain assigned to the partition becoming the channel * manager for that partition until the partition is deactivating, at which * time the kthread will teardown the XPC infrastructure and then exit. */ static int xpc_activating(void *__partid) { short partid = (u64)__partid; struct xpc_partition *part = &xpc_partitions[partid]; unsigned long irq_flags; DBUG_ON(partid < 0 || partid >= xp_max_npartitions); spin_lock_irqsave(&part->act_lock, irq_flags); if (part->act_state == XPC_P_AS_DEACTIVATING) { part->act_state = XPC_P_AS_INACTIVE; spin_unlock_irqrestore(&part->act_lock, irq_flags); part->remote_rp_pa = 0; return 0; } /* indicate the thread is activating */ DBUG_ON(part->act_state != XPC_P_AS_ACTIVATION_REQ); part->act_state = XPC_P_AS_ACTIVATING; XPC_SET_REASON(part, 0, 0); spin_unlock_irqrestore(&part->act_lock, irq_flags); dev_dbg(xpc_part, "activating partition %d\n", partid); xpc_allow_hb(partid); if (xpc_setup_ch_structures(part) == xpSuccess) { (void)xpc_part_ref(part); /* this will always succeed */ if (xpc_make_first_contact(part) == xpSuccess) { xpc_mark_partition_active(part); xpc_channel_mgr(part); /* won't return until partition is deactivating */ } xpc_part_deref(part); xpc_teardown_ch_structures(part); } xpc_disallow_hb(partid); xpc_mark_partition_inactive(part); if (part->reason == xpReactivating) { /* interrupting ourselves results in activating partition */ xpc_request_partition_reactivation(part); } return 0; }
/* * 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); }