summaryrefslogtreecommitdiff
path: root/drivers/iommu/qcom/msm_iommu_perfmon.h
blob: 45683f4ebd886dcacfab90093d57d131344febdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/irqreturn.h>

#ifndef MSM_IOMMU_PERFMON_H
#define MSM_IOMMU_PERFMON_H

/**
 * struct iommu_pmon_counter - container for a performance counter.
 * @counter_no:          counter number within the group
 * @absolute_counter_no: counter number within IOMMU PMU
 * @value:               cached counter value
 * @overflow_count:      no of times counter has overflowed
 * @enabled:             indicates whether counter is enabled or not
 * @current_event_class: current selected event class, -1 if none
 * @counter_dir:         debugfs directory for this counter
 * @cnt_group:           group this counter belongs to
 */
struct iommu_pmon_counter {
	unsigned int counter_no;
	unsigned int absolute_counter_no;
	unsigned long value;
	unsigned long overflow_count;
	unsigned int enabled;
	int current_event_class;
	struct dentry *counter_dir;
	struct iommu_pmon_cnt_group *cnt_group;
};

/**
 * struct iommu_pmon_cnt_group - container for a perf mon counter group.
 * @grp_no:       group number
 * @num_counters: number of counters in this group
 * @counters:     list of counter in this group
 * @group_dir:    debugfs directory for this group
 * @pmon:         pointer to the iommu_pmon object this group belongs to
 */
struct iommu_pmon_cnt_group {
	unsigned int grp_no;
	unsigned int num_counters;
	struct iommu_pmon_counter *counters;
	struct dentry *group_dir;
	struct iommu_pmon *pmon;
};

/**
 * struct iommu_info - container for a perf mon iommu info.
 * @iommu_name: name of the iommu from device tree
 * @base:       virtual base address for this iommu
 * @evt_irq:    irq number for event overflow interrupt
 * @iommu_dev:  pointer to iommu device
 * @ops:        iommu access operations pointer.
 * @hw_ops:     iommu pm hw access operations pointer.
 * @always_on:  1 if iommu is always on, 0 otherwise.
 */
struct iommu_info {
	const char *iommu_name;
	void *base;
	int evt_irq;
	struct device *iommu_dev;
	struct iommu_access_ops *ops;
	struct iommu_pm_hw_ops *hw_ops;
	unsigned int always_on;
};

/**
 * struct iommu_pmon - main container for a perf mon data.
 * @iommu_dir:            debugfs directory for this iommu
 * @iommu:                iommu_info instance
 * @iommu_list:           iommu_list head
 * @cnt_grp:              list of counter groups
 * @num_groups:           number of counter groups
 * @num_counters:         number of counters per group
 * @event_cls_supported:  an array of event classes supported for this PMU
 * @nevent_cls_supported: number of event classes supported.
 * @enabled:              Indicates whether perf. mon is enabled or not
 * @iommu_attached        Indicates whether iommu is attached or not.
 * @lock:                 mutex used to synchronize access to shared data
 */
struct iommu_pmon {
	struct dentry *iommu_dir;
	struct iommu_info iommu;
	struct list_head iommu_list;
	struct iommu_pmon_cnt_group *cnt_grp;
	u32 num_groups;
	u32 num_counters;
	u32 *event_cls_supported;
	u32 nevent_cls_supported;
	unsigned int enabled;
	unsigned int iommu_attach_count;
	struct mutex lock;
};

/**
 * struct iommu_hw_ops - Callbacks for accessing IOMMU HW
 * @initialize_hw: Call to do any initialization before enabling ovf interrupts
 * @is_hw_access_ok: Returns 1 if we can access HW, 0 otherwise
 * @grp_enable: Call to enable a counter group
 * @grp_disable: Call to disable a counter group
 * @enable_pm: Call to enable PM
 * @disable_pm: Call to disable PM
 * @reset_counters:  Call to reset counters
 * @check_for_overflow:  Call to check for overflow
 * @evt_ovfl_int_handler: Overflow interrupt handler callback
 * @counter_enable: Call to enable counters
 * @counter_disable: Call to disable counters
 * @ovfl_int_enable: Call to enable overflow interrupts
 * @ovfl_int_disable: Call to disable overflow interrupts
 * @set_event_class: Call to set event class
 * @read_counter: Call to read a counter value
 */
struct iommu_pm_hw_ops {
	void (*initialize_hw)(const struct iommu_pmon *);
	unsigned int (*is_hw_access_OK)(const struct iommu_pmon *);
	void (*grp_enable)(struct iommu_info *, unsigned int);
	void (*grp_disable)(struct iommu_info *, unsigned int);
	void (*enable_pm)(struct iommu_info *);
	void (*disable_pm)(struct iommu_info *);
	void (*reset_counters)(const struct iommu_info *);
	void (*check_for_overflow)(struct iommu_pmon *);
	irqreturn_t (*evt_ovfl_int_handler)(int, void *);
	void (*counter_enable)(struct iommu_info *,
			       struct iommu_pmon_counter *);
	void (*counter_disable)(struct iommu_info *,
			       struct iommu_pmon_counter *);
	void (*ovfl_int_enable)(struct iommu_info *,
				const struct iommu_pmon_counter *);
	void (*ovfl_int_disable)(struct iommu_info *,
				const struct iommu_pmon_counter *);
	void (*set_event_class)(struct iommu_pmon *pmon, unsigned int,
				unsigned int);
	unsigned int (*read_counter)(struct iommu_pmon_counter *);
};

#define MSM_IOMMU_PMU_NO_EVENT_CLASS -1

#ifdef CONFIG_MSM_IOMMU_PMON

/**
 * Get pointer to PMU hardware access functions for IOMMUv0 PMU
 */
struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v0(void);

/**
 * Get pointer to PMU hardware access functions for IOMMUv1 PMU
 */
struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v1(void);

/**
 * Allocate memory for performance monitor structure. Must
 * be called before iommu_pm_iommu_register
 */
struct iommu_pmon *msm_iommu_pm_alloc(struct device *iommu_dev);

/**
 * Free memory previously allocated with iommu_pm_alloc
 */
void msm_iommu_pm_free(struct device *iommu_dev);

/**
 * Register iommu with the performance monitor module.
 */
int msm_iommu_pm_iommu_register(struct iommu_pmon *info);

/**
 * Unregister iommu with the performance monitor module.
 */
void msm_iommu_pm_iommu_unregister(struct device *dev);

/**
 * Called by iommu driver when attaching is complete
 * Must NOT be called with IOMMU mutexes held.
 * @param iommu_dev IOMMU device that is attached
  */
void msm_iommu_attached(struct device *dev);

/**
 * Called by iommu driver before detaching.
 * Must NOT be called with IOMMU mutexes held.
 * @param iommu_dev IOMMU device that is going to be detached
  */
void msm_iommu_detached(struct device *dev);
#else
static inline struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v0(void)
{
	return NULL;
}

static inline struct iommu_pm_hw_ops *iommu_pm_get_hw_ops_v1(void)
{
	return NULL;
}

static inline struct iommu_pmon *msm_iommu_pm_alloc(struct device *iommu_dev)
{
	return NULL;
}

static inline void msm_iommu_pm_free(struct device *iommu_dev)
{
	return;
}

static inline int msm_iommu_pm_iommu_register(struct iommu_pmon *info)
{
	return -EIO;
}

static inline void msm_iommu_pm_iommu_unregister(struct device *dev)
{
}

static inline void msm_iommu_attached(struct device *dev)
{
}

static inline void msm_iommu_detached(struct device *dev)
{
}
#endif
#endif