/*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.13 $)
+ * linux/drivers/s390/cio/cmf.c
*
* Linux on zSeries Channel Measurement Facility support
*
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/timex.h> /* get_clock() */
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include <asm/cmb.h>
+#include <asm/div64.h>
#include "cio.h"
#include "css.h"
#include "device.h"
#include "ioasm.h"
+#include "chsc.h"
/* parameter to enable cmf during boot, possible uses are:
* "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be
/* msch can silently fail, so do it again if necessary */
for (retry = 0; retry < 3; retry++) {
/* prepare schib */
- stsch(sch->irq, schib);
+ stsch(sch->schid, schib);
schib->pmcw.mme = mme;
schib->pmcw.mbfc = mbfc;
/* address can be either a block address or a block index */
schib->pmcw.mbi = address;
/* try to submit it */
- switch(ret = msch_err(sch->irq, schib)) {
+ switch(ret = msch_err(sch->schid, schib)) {
case 0:
break;
case 1:
ret = -EINVAL;
break;
}
- stsch(sch->irq, schib); /* restore the schib */
+ stsch(sch->schid, schib); /* restore the schib */
if (ret)
break;
time = get_clock() - cdev->private->cmb_start_time;
spin_unlock_irqrestore(cdev->ccwlock, flags);
- *data = (struct cmbdata) {
- /* we only know values before device_busy_time */
- .size = offsetof(struct cmbdata, device_busy_time),
-
- /* conver to nanoseconds */
- .elapsed_time = (time * 1000) >> 12,
-
- /* copy data to new structure */
- .ssch_rsch_count = cmb.ssch_rsch_count,
- .sample_count = cmb.sample_count,
-
- /* time fields are converted to nanoseconds while copying */
- .device_connect_time
- = time_to_nsec(cmb.device_connect_time),
- .function_pending_time
- = time_to_nsec(cmb.function_pending_time),
- .device_disconnect_time
- = time_to_nsec(cmb.device_disconnect_time),
- .control_unit_queuing_time
- = time_to_nsec(cmb.control_unit_queuing_time),
- .device_active_only_time
- = time_to_nsec(cmb.device_active_only_time),
- };
+ memset(data, 0, sizeof(struct cmbdata));
+
+ /* we only know values before device_busy_time */
+ data->size = offsetof(struct cmbdata, device_busy_time);
+
+ /* convert to nanoseconds */
+ data->elapsed_time = (time * 1000) >> 12;
+
+ /* copy data to new structure */
+ data->ssch_rsch_count = cmb.ssch_rsch_count;
+ data->sample_count = cmb.sample_count;
+
+ /* time fields are converted to nanoseconds while copying */
+ data->device_connect_time = time_to_nsec(cmb.device_connect_time);
+ data->function_pending_time = time_to_nsec(cmb.function_pending_time);
+ data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+ data->control_unit_queuing_time
+ = time_to_nsec(cmb.control_unit_queuing_time);
+ data->device_active_only_time
+ = time_to_nsec(cmb.device_active_only_time);
return 0;
}
free_cmbe (struct ccw_device *cdev)
{
spin_lock_irq(cdev->ccwlock);
- if (cdev->private->cmb)
- kfree(cdev->private->cmb);
+ kfree(cdev->private->cmb);
cdev->private->cmb = NULL;
spin_unlock_irq(cdev->ccwlock);
time = get_clock() - cdev->private->cmb_start_time;
spin_unlock_irqrestore(cdev->ccwlock, flags);
- *data = (struct cmbdata) {
- /* we only know values before device_busy_time */
- .size = offsetof(struct cmbdata, device_busy_time),
-
- /* conver to nanoseconds */
- .elapsed_time = (time * 1000) >> 12,
-
- /* copy data to new structure */
- .ssch_rsch_count = cmb.ssch_rsch_count,
- .sample_count = cmb.sample_count,
-
- /* time fields are converted to nanoseconds while copying */
- .device_connect_time
- = time_to_nsec(cmb.device_connect_time),
- .function_pending_time
- = time_to_nsec(cmb.function_pending_time),
- .device_disconnect_time
- = time_to_nsec(cmb.device_disconnect_time),
- .control_unit_queuing_time
- = time_to_nsec(cmb.control_unit_queuing_time),
- .device_active_only_time
- = time_to_nsec(cmb.device_active_only_time),
- .device_busy_time
- = time_to_nsec(cmb.device_busy_time),
- .initial_command_response_time
- = time_to_nsec(cmb.initial_command_response_time),
- };
+ memset (data, 0, sizeof(struct cmbdata));
+
+ /* we only know values before device_busy_time */
+ data->size = offsetof(struct cmbdata, device_busy_time);
+
+ /* conver to nanoseconds */
+ data->elapsed_time = (time * 1000) >> 12;
+
+ /* copy data to new structure */
+ data->ssch_rsch_count = cmb.ssch_rsch_count;
+ data->sample_count = cmb.sample_count;
+
+ /* time fields are converted to nanoseconds while copying */
+ data->device_connect_time = time_to_nsec(cmb.device_connect_time);
+ data->function_pending_time = time_to_nsec(cmb.function_pending_time);
+ data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+ data->control_unit_queuing_time
+ = time_to_nsec(cmb.control_unit_queuing_time);
+ data->device_active_only_time
+ = time_to_nsec(cmb.device_active_only_time);
+ data->device_busy_time = time_to_nsec(cmb.device_busy_time);
+ data->initial_command_response_time
+ = time_to_nsec(cmb.initial_command_response_time);
return 0;
}
}
static ssize_t
-cmb_show_avg_sample_interval(struct device *dev, char *buf)
+cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev;
long interval;
}
static ssize_t
-cmb_show_avg_utilization(struct device *dev, char *buf)
+cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cmbdata data;
u64 utilization;
}
#define cmf_attr(name) \
-static ssize_t show_ ## name (struct device * dev, char * buf) \
+static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
static DEVICE_ATTR(name, 0444, show_ ## name, NULL);
#define cmf_attr_avg(name) \
-static ssize_t show_avg_ ## name (struct device * dev, char * buf) \
+static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL);
.attrs = cmf_attributes_ext,
};
-static ssize_t cmb_enable_show(struct device *dev, char *buf)
+static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0);
}
-static ssize_t cmb_enable_store(struct device *dev, const char *buf, size_t c)
+static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c)
{
struct ccw_device *cdev;
int ret;
see if we are running on z990 or up, otherwise fall back to basic mode. */
if (format == CMF_AUTODETECT) {
- if (!MACHINE_NEW_STIDP) {
+ if (!css_characteristics_avail ||
+ !css_general_characteristics.ext_mb) {
format = CMF_BASIC;
} else {
format = CMF_EXTENDED;