Example #1
0
/*
 * 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;
}
Example #2
0
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_PARTITIONS);

    spin_lock_irqsave(&part->act_lock, irq_flags);

    if (part->act_state == XPC_P_DEACTIVATING) {
        part->act_state = XPC_P_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_ACTIVATION_REQ);
    part->act_state = XPC_P_ACTIVATING;

    XPC_SET_REASON(part, 0, 0);
    spin_unlock_irqrestore(&part->act_lock, irq_flags);

    dev_dbg(xpc_part, "bringing partition %d up\n", partid);

    /*
     * Register the remote partition's AMOs with SAL so it can handle
     * and cleanup errors within that address range should the remote
     * partition go down. We don't unregister this range because it is
     * difficult to tell when outstanding writes to the remote partition
     * are finished and thus when it is safe to unregister. This should
     * not result in wasted space in the SAL xp_addr_region table because
     * we should get the same page for remote_amos_page_pa after module
     * reloads and system reboots.
     */
    if (sn_register_xp_addr_region(part->remote_amos_page_pa,
                                   PAGE_SIZE, 1) < 0) {
        dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
                 "xp_addr region\n", partid);

        spin_lock_irqsave(&part->act_lock, irq_flags);
        part->act_state = XPC_P_INACTIVE;
        XPC_SET_REASON(part, xpPhysAddrRegFailed, __LINE__);
        spin_unlock_irqrestore(&part->act_lock, irq_flags);
        part->remote_rp_pa = 0;
        return 0;
    }

    xpc_allow_hb(partid, xpc_vars);
    xpc_IPI_send_activated(part);

    /*
     * xpc_partition_up() holds this thread and marks this partition as
     * XPC_P_ACTIVE by calling xpc_hb_mark_active().
     */
    (void)xpc_partition_up(part);

    xpc_disallow_hb(partid, xpc_vars);
    xpc_mark_partition_inactive(part);

    if (part->reason == xpReactivating) {
        /* interrupting ourselves results in activating partition */
        xpc_IPI_send_reactivate(part);
    }

    return 0;
}