summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2017-09-08 21:01:38 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-09-28 07:29:42 +0200
commitcb09b356cd43fb079ea85128dcd17e5b65585fe8 (patch)
tree06e57e540762016ae5686a474024a942c610ced2 /drivers/s390
parentd4d287e81ff1924f0791fad0638551daec7742b5 (diff)
downloadlinux-cb09b356cd43fb079ea85128dcd17e5b65585fe8.tar.gz
linux-cb09b356cd43fb079ea85128dcd17e5b65585fe8.tar.bz2
linux-cb09b356cd43fb079ea85128dcd17e5b65585fe8.zip
s390/cmf: avg_utilization
All (but one) cmf related sysfs attributes have been converted to read directly from the measurement block using cmf_read. This is not possible for the avg_utilization attribute since this is an aggregation of several values for which cmf_read only returns average values. Move the computation of the utilization value to the cmf_read interface such that it can use the raw data. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/cmf.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 78fb492d9881..0b10221c4661 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -58,8 +58,9 @@
/* indices for READCMB */
enum cmb_index {
+ avg_utilization = -1,
/* basic and exended format: */
- cmb_ssch_rsch_count,
+ cmb_ssch_rsch_count = 0,
cmb_sample_count,
cmb_device_connect_time,
cmb_function_pending_time,
@@ -587,12 +588,29 @@ static int set_cmb(struct ccw_device *cdev, u32 mme)
return set_schib_wait(cdev, mme, 0, offset);
}
+/* calculate utilization in 0.1 percent units */
+static u64 __cmb_utilization(u64 device_connect_time, u64 function_pending_time,
+ u64 device_disconnect_time, u64 start_time)
+{
+ u64 utilization, elapsed_time;
+
+ utilization = time_to_nsec(device_connect_time +
+ function_pending_time +
+ device_disconnect_time);
+
+ elapsed_time = get_tod_clock() - start_time;
+ elapsed_time = tod_to_ns(elapsed_time);
+ elapsed_time /= 1000;
+
+ return elapsed_time ? (utilization / elapsed_time) : 0;
+}
+
static u64 read_cmb(struct ccw_device *cdev, int index)
{
struct cmb_data *cmb_data;
unsigned long flags;
struct cmb *cmb;
- int ret = 0;
+ u64 ret = 0;
u32 val;
spin_lock_irqsave(cdev->ccwlock, flags);
@@ -602,6 +620,12 @@ static u64 read_cmb(struct ccw_device *cdev, int index)
cmb = cmb_data->hw_block;
switch (index) {
+ case avg_utilization:
+ ret = __cmb_utilization(cmb->device_connect_time,
+ cmb->function_pending_time,
+ cmb->device_disconnect_time,
+ cdev->private->cmb_start_time);
+ goto out;
case cmb_ssch_rsch_count:
ret = cmb->ssch_rsch_count;
goto out;
@@ -841,7 +865,7 @@ static u64 read_cmbe(struct ccw_device *cdev, int index)
struct cmb_data *cmb_data;
unsigned long flags;
struct cmbe *cmb;
- int ret = 0;
+ u64 ret = 0;
u32 val;
spin_lock_irqsave(cdev->ccwlock, flags);
@@ -851,6 +875,12 @@ static u64 read_cmbe(struct ccw_device *cdev, int index)
cmb = cmb_data->hw_block;
switch (index) {
+ case avg_utilization:
+ ret = __cmb_utilization(cmb->device_connect_time,
+ cmb->function_pending_time,
+ cmb->device_disconnect_time,
+ cdev->private->cmb_start_time);
+ goto out;
case cmb_ssch_rsch_count:
ret = cmb->ssch_rsch_count;
goto out;
@@ -989,27 +1019,9 @@ static ssize_t cmb_show_avg_utilization(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct cmbdata data;
- u64 utilization;
- unsigned long t, u;
- int ret;
-
- ret = cmf_readall(to_ccwdev(dev), &data);
- if (ret == -EAGAIN || ret == -ENODEV)
- /* No data (yet/currently) available to use for calculation. */
- return sprintf(buf, "n/a\n");
- else if (ret)
- return ret;
-
- utilization = data.device_connect_time +
- data.function_pending_time +
- data.device_disconnect_time;
-
- /* calculate value in 0.1 percent units */
- t = data.elapsed_time / 1000;
- u = utilization / t;
+ unsigned long u = cmf_read(to_ccwdev(dev), avg_utilization);
- return sprintf(buf, "%02ld.%01ld%%\n", u/ 10, u - (u/ 10) * 10);
+ return sprintf(buf, "%02lu.%01lu%%\n", u / 10, u % 10);
}
#define cmf_attr(name) \