Commit 0f987e6c authored by Peter Oberparleiter's avatar Peter Oberparleiter Committed by Alexander Gordeev
Browse files

s390/cio: export CHPID operating speed



Add a per-CHPID sysfs attribute named "speed_bps" that provides the
operating speed of the associated channel path in bits per second,
or 0 if the operating speed is not available.

Example:

$ cat /sys/devices/css0/chp0.32/speed_bps
32G

Reviewed-by: default avatarVineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarPeter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parent 5e6bb10e
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -392,6 +392,35 @@ static ssize_t chp_esc_show(struct device *dev,
}
static DEVICE_ATTR(esc, 0444, chp_esc_show, NULL);

static char apply_max_suffix(unsigned long *value, unsigned long base)
{
	static char suffixes[] = { 0, 'K', 'M', 'G', 'T' };
	int i;

	for (i = 0; i < ARRAY_SIZE(suffixes) - 1; i++) {
		if (*value < base || *value % base != 0)
			break;
		*value /= base;
	}

	return suffixes[i];
}

static ssize_t speed_bps_show(struct device *dev,
			      struct device_attribute *attr, char *buf)
{
	struct channel_path *chp = to_channelpath(dev);
	unsigned long speed = chp->speed;
	char suffix;

	suffix = apply_max_suffix(&speed, 1000);

	return suffix ? sysfs_emit(buf, "%lu%c\n", speed, suffix) :
			sysfs_emit(buf, "%lu\n", speed);
}

static DEVICE_ATTR_RO(speed_bps);

static ssize_t util_string_read(struct file *filp, struct kobject *kobj,
				struct bin_attribute *attr, char *buf,
				loff_t off, size_t count)
@@ -423,6 +452,7 @@ static struct attribute *chp_attrs[] = {
	&dev_attr_chid.attr,
	&dev_attr_chid_external.attr,
	&dev_attr_esc.attr,
	&dev_attr_speed_bps.attr,
	NULL,
};
static struct attribute_group chp_attr_group = {
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct channel_path {
	int cmg;
	int shared;
	int extended;
	unsigned long speed;
	struct cmg_chars cmg_chars;
};

+18 −2
Original line number Diff line number Diff line
@@ -1066,6 +1066,18 @@ chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
	}
}

static unsigned long scmc_get_speed(u32 s, u32 p)
{
	unsigned long speed = s;

	if (!p)
		p = 8;
	while (p--)
		speed *= 10;

	return speed;
}

int chsc_get_channel_measurement_chars(struct channel_path *chp)
{
	unsigned long flags;
@@ -1086,16 +1098,19 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
		u32 : 21;
		u32 chpid : 8;
		u32 cmcv : 5;
		u32 : 11;
		u32 : 7;
		u32 cmgp : 4;
		u32 cmgq : 8;
		u32 cmg : 8;
		u32 zeroes3;
		u32 : 16;
		u32 cmgs : 16;
		u32 data[NR_MEASUREMENT_CHARS];
	} *scmc_area;

	chp->shared = -1;
	chp->cmg = -1;
	chp->extended = 0;
	chp->speed = 0;

	if (!css_chsc_characteristics.scmc || !css_chsc_characteristics.secm)
		return -EINVAL;
@@ -1126,6 +1141,7 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
	chp->cmg = scmc_area->cmg;
	chp->shared = scmc_area->shared;
	chp->extended = scmc_area->extended;
	chp->speed = scmc_get_speed(scmc_area->cmgs, scmc_area->cmgp);
	chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
				  (struct cmg_chars *) &scmc_area->data);
out: