Linux-2.6.12-rc2
[deliverable/linux.git] / drivers / s390 / cio / cmf.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
3 *
4 * Linux on zSeries Channel Measurement Facility support
5 *
6 * Copyright 2000,2003 IBM Corporation
7 *
8 * Author: Arnd Bergmann <arndb@de.ibm.com>
9 *
10 * original idea from Natarajan Krishnaswami <nkrishna@us.ibm.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/bootmem.h>
28#include <linux/device.h>
29#include <linux/init.h>
30#include <linux/list.h>
31#include <linux/module.h>
32#include <linux/moduleparam.h>
33
34#include <asm/ccwdev.h>
35#include <asm/cio.h>
36#include <asm/cmb.h>
37
38#include "cio.h"
39#include "css.h"
40#include "device.h"
41#include "ioasm.h"
42#include "chsc.h"
43
44/* parameter to enable cmf during boot, possible uses are:
45 * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be
46 * used on any subchannel
47 * "s390cmf=<num>" -- enable cmf and allocate enough memory to measure
48 * <num> subchannel, where <num> is an integer
49 * between 1 and 65535, default is 1024
50 */
51#define ARGSTRING "s390cmf"
52
53/* indices for READCMB */
54enum cmb_index {
55 /* basic and exended format: */
56 cmb_ssch_rsch_count,
57 cmb_sample_count,
58 cmb_device_connect_time,
59 cmb_function_pending_time,
60 cmb_device_disconnect_time,
61 cmb_control_unit_queuing_time,
62 cmb_device_active_only_time,
63 /* extended format only: */
64 cmb_device_busy_time,
65 cmb_initial_command_response_time,
66};
67
68/**
69 * enum cmb_format - types of supported measurement block formats
70 *
71 * @CMF_BASIC: traditional channel measurement blocks supported
72 * by all machines that we run on
73 * @CMF_EXTENDED: improved format that was introduced with the z990
74 * machine
75 * @CMF_AUTODETECT: default: use extended format when running on a z990
76 * or later machine, otherwise fall back to basic format
77 **/
78enum cmb_format {
79 CMF_BASIC,
80 CMF_EXTENDED,
81 CMF_AUTODETECT = -1,
82};
83/**
84 * format - actual format for all measurement blocks
85 *
86 * The format module parameter can be set to a value of 0 (zero)
87 * or 1, indicating basic or extended format as described for
88 * enum cmb_format.
89 */
90static int format = CMF_AUTODETECT;
91module_param(format, bool, 0444);
92
93/**
94 * struct cmb_operations - functions to use depending on cmb_format
95 *
96 * all these functions operate on a struct cmf_device. There is only
97 * one instance of struct cmb_operations because all cmf_device
98 * objects are guaranteed to be of the same type.
99 *
100 * @alloc: allocate memory for a channel measurement block,
101 * either with the help of a special pool or with kmalloc
102 * @free: free memory allocated with @alloc
103 * @set: enable or disable measurement
104 * @readall: read a measurement block in a common format
105 * @reset: clear the data in the associated measurement block and
106 * reset its time stamp
107 */
108struct cmb_operations {
109 int (*alloc) (struct ccw_device*);
110 void(*free) (struct ccw_device*);
111 int (*set) (struct ccw_device*, u32);
112 u64 (*read) (struct ccw_device*, int);
113 int (*readall)(struct ccw_device*, struct cmbdata *);
114 void (*reset) (struct ccw_device*);
115
116 struct attribute_group *attr_group;
117};
118static struct cmb_operations *cmbops;
119
120/* our user interface is designed in terms of nanoseconds,
121 * while the hardware measures total times in its own
122 * unit.*/
123static inline u64 time_to_nsec(u32 value)
124{
125 return ((u64)value) * 128000ull;
126}
127
128/*
129 * Users are usually interested in average times,
130 * not accumulated time.
131 * This also helps us with atomicity problems
132 * when reading sinlge values.
133 */
134static inline u64 time_to_avg_nsec(u32 value, u32 count)
135{
136 u64 ret;
137
138 /* no samples yet, avoid division by 0 */
139 if (count == 0)
140 return 0;
141