Example #1
0
static void chsc_process_sei_chp_avail(struct chsc_sei_nt0_area *sei_area)
{
    struct channel_path *chp;
    struct chp_id chpid;
    u8 *data;
    int num;

    CIO_CRW_EVENT(4, "chsc: channel path availability information\n");
    if (sei_area->rs != 0)
        return;
    data = sei_area->ccdf;
    chp_id_init(&chpid);
    for (num = 0; num <= __MAX_CHPID; num++) {
        if (!chp_test_bit(data, num))
            continue;
        chpid.id = num;

        CIO_CRW_EVENT(4, "Update information for channel path "
                      "%x.%02x\n", chpid.cssid, chpid.id);
        chp = chpid_to_chp(chpid);
        if (!chp) {
            chp_new(chpid);
            continue;
        }
        mutex_lock(&chp->lock);
        chsc_determine_base_channel_path_desc(chpid, &chp->desc);
        mutex_unlock(&chp->lock);
    }
}
Example #2
0
File: chp.c Project: 19Dan01/linux
/**
 * chp_update_desc - update channel-path description
 * @chp - channel-path
 *
 * Update the channel-path description of the specified channel-path.
 * Return zero on success, non-zero otherwise.
 */
int chp_update_desc(struct channel_path *chp)
{
	int rc;

	rc = chsc_determine_base_channel_path_desc(chp->chpid, &chp->desc);
	if (rc)
		return rc;

	rc = chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1);

	return rc;
}
Example #3
0
/**
 * chp_update_desc - update channel-path description
 * @chp - channel-path
 *
 * Update the channel-path description of the specified channel-path
 * including channel measurement related information.
 * Return zero on success, non-zero otherwise.
 */
int chp_update_desc(struct channel_path *chp)
{
	int rc;

	rc = chsc_determine_base_channel_path_desc(chp->chpid, &chp->desc);
	if (rc)
		return rc;

	/*
	 * Fetching the following data is optional. Not all machines or
	 * hypervisors implement the required chsc commands.
	 */
	chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1);
	chsc_get_channel_measurement_chars(chp);

	return 0;
}
Example #4
0
/**
 * chsc_chp_vary - propagate channel-path vary operation to subchannels
 * @chpid: channl-path ID
 * @on: non-zero for vary online, zero for vary offline
 */
int chsc_chp_vary(struct chp_id chpid, int on)
{
    struct channel_path *chp = chpid_to_chp(chpid);

    /* Wait until previous actions have settled. */
    css_wait_for_slow_path();
    /*
     * Redo PathVerification on the devices the chpid connects to
     */
    if (on) {
        /* Try to update the channel path descritor. */
        chsc_determine_base_channel_path_desc(chpid, &chp->desc);
        for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
                                   __s390_vary_chpid_on, &chpid);
    } else
        for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
                                   NULL, &chpid);

    return 0;
}
Example #5
0
/**
 * chp_new - register a new channel-path
 * @chpid - channel-path ID
 *
 * Create and register data structure representing new channel-path. Return
 * zero on success, non-zero otherwise.
 */
int chp_new(struct chp_id chpid)
{
	struct channel_path *chp;
	int ret;

	if (chp_is_registered(chpid))
		return 0;
	chp = kzalloc(sizeof(struct channel_path), GFP_KERNEL);
	if (!chp)
		return -ENOMEM;

	/* fill in status, etc. */
	chp->chpid = chpid;
	chp->state = 1;
	chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
	chp->dev.release = chp_release;
	dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);

	/* Obtain channel path description and fill it in. */
	ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
	if (ret)
		goto out_free;
	if ((chp->desc.flags & 0x80) == 0) {
		ret = -ENODEV;
		goto out_free;
	}
	/* Get channel-measurement characteristics. */
	if (css_chsc_characteristics.scmc && css_chsc_characteristics.secm) {
		ret = chsc_get_channel_measurement_chars(chp);
		if (ret)
			goto out_free;
	} else {
		chp->cmg = -1;
	}

	/* make it known to the system */
	ret = device_register(&chp->dev);
	if (ret) {
		CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n",
			      chpid.cssid, chpid.id, ret);
		goto out_free;
	}
	ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
	if (ret) {
		device_unregister(&chp->dev);
		goto out;
	}
	mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
	if (channel_subsystems[chpid.cssid]->cm_enabled) {
		ret = chp_add_cmg_attr(chp);
		if (ret) {
			sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
			device_unregister(&chp->dev);
			mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
			goto out;
		}
	}
	channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
	mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
	goto out;
out_free:
	kfree(chp);
out:
	return ret;
}