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