mm: mm_event supports vmstat
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / iommu / exynos-iommu-log.h
CommitLineData
40727f6e
JK
1/*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Data structure definition for Exynos IOMMU driver
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_IOMMU_LOG_H_
13#define _EXYNOS_IOMMU_LOG_H_
14
15#include <linux/mm.h>
16#include <linux/mm_types.h>
17#include <linux/ktime.h>
18#include <linux/hrtimer.h>
19#include <linux/gfp.h>
20#include <linux/vmalloc.h>
21#include <linux/device.h>
22
23enum sysmmu_event_log_event {
24 EVENT_SYSMMU_NONE, /* initialized value */
25 EVENT_SYSMMU_ENABLE,
26 EVENT_SYSMMU_DISABLE,
27 EVENT_SYSMMU_TLB_INV_RANGE,
28 EVENT_SYSMMU_TLB_INV_ALL,
29 EVENT_SYSMMU_POWERON,
30 EVENT_SYSMMU_POWEROFF,
31 EVENT_SYSMMU_IOMMU_ATTACH,
32 EVENT_SYSMMU_IOMMU_DETACH,
33 EVENT_SYSMMU_IOMMU_MAP,
34 EVENT_SYSMMU_IOMMU_UNMAP,
35 EVENT_SYSMMU_IOMMU_ALLOCSLPD,
36 EVENT_SYSMMU_IOMMU_FREESLPD,
37 EVENT_SYSMMU_IOVMM_MAP,
38 EVENT_SYSMMU_IOVMM_UNMAP
39};
40
41struct sysmmu_event_range {
42 u32 start;
43 u32 end;
44};
45
46struct sysmmu_event_IOMMU_MAP {
47 u32 start;
48 u32 end;
49 unsigned int pfn;
50};
51
52struct sysmmu_event_IOVMM_MAP {
53 u32 start;
54 u32 end;
55 unsigned int dummy;
56};
57
58/**
59 * event must be updated before eventdata because of eventdata.dev
60 * sysmmu_event_log is not protected by any locks. That means it permits
61 * some data inconsistency by race condition between updating and reading.
62 * However the problem arises when event is either IOMMU_ATTACH or
63 * IOMMU_DETACH because they stores a pointer to device descriptor to
64 * eventdata.dev and reading the sysmmu_event_log of those events refers
65 * to values pointed by eventdata.dev.
66 * Therefore, eventdata must be updated before event not to access invalid
67 * pointer by reading debugfs entries.
68 */
69struct sysmmu_event_log {
70 ktime_t timestamp;
71 union {
72 struct sysmmu_event_range range;
73 struct sysmmu_event_IOMMU_MAP iommu;
74 struct sysmmu_event_IOVMM_MAP iovmm;
75 u32 addr;
76 struct device *dev;
77 } eventdata;
78 enum sysmmu_event_log_event event;
79};
80
81struct exynos_iommu_event_log {
82 atomic_t index;
83 unsigned int log_len;
84 struct sysmmu_event_log *log;
85 struct dentry *debugfs_root;
86};
87
88/* sizeof(struct sysmmu_event_log) = 8 + 4 * 3 + 4 = 24 bytes */
89#define SYSMMU_LOG_LEN 1024
90#define IOMMU_LOG_LEN 4096
91#define IOVMM_LOG_LEN 512
92
93#define SYSMMU_DRVDATA_TO_LOG(data) (&(data)->log)
94#define IOMMU_PRIV_TO_LOG(data) (&(data)->log)
95#define IOMMU_TO_LOG(data) (&(to_exynos_domain(data))->log)
96#define IOVMM_TO_LOG(data) (&(data)->log)
97
98static inline struct sysmmu_event_log *sysmmu_event_log_get(
99 struct exynos_iommu_event_log *plog)
100{
101 struct sysmmu_event_log *log;
102 unsigned int index =
103 (unsigned int)atomic_inc_return(&plog->index) - 1;
104 log = &plog->log[index % plog->log_len];
105 log->timestamp = ktime_get();
106 return log;
107}
108
109#define DEFINE_SYSMMU_EVENT_LOG(evt) \
110static inline void SYSMMU_EVENT_LOG_##evt(struct exynos_iommu_event_log *plog) \
111{ \
112 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
113 log->event = EVENT_SYSMMU_##evt; \
114}
115
116#define DEFINE_SYSMMU_EVENT_LOG_1ADDR(evt) \
117static inline void SYSMMU_EVENT_LOG_##evt( \
118 struct exynos_iommu_event_log *plog, u32 addr) \
119{ \
120 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
121 log->eventdata.addr = addr; \
122 log->event = EVENT_SYSMMU_##evt; \
123}
124
125#define DEFINE_SYSMMU_EVENT_LOG_2ADDR(evt) \
126static inline void SYSMMU_EVENT_LOG_##evt(struct exynos_iommu_event_log *plog, \
127 u32 start, u32 end) \
128{ \
129 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
130 log->eventdata.range.start = start; \
131 log->eventdata.range.end = end; \
132 log->event = EVENT_SYSMMU_##evt; \
133}
134
135static inline void SYSMMU_EVENT_LOG_IOVMM_MAP(
136 struct exynos_iommu_event_log *plog,
137 u32 start, u32 end, unsigned int dummy)
138{
139 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
140 log->eventdata.iovmm.start = start;
141 log->eventdata.iovmm.end = end;
142 log->eventdata.iovmm.dummy = dummy;
143 log->event = EVENT_SYSMMU_IOVMM_MAP;
144}
145
146static inline void SYSMMU_EVENT_LOG_IOMMU_ATTACH(
147 struct exynos_iommu_event_log *plog, struct device *dev)
148{
149 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
150 log->eventdata.dev = dev;
151 log->event = EVENT_SYSMMU_IOMMU_ATTACH;
152}
153
154static inline void SYSMMU_EVENT_LOG_IOMMU_DETACH(
155 struct exynos_iommu_event_log *plog, struct device *dev)
156{
157 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
158 log->eventdata.dev = dev;
159 log->event = EVENT_SYSMMU_IOMMU_DETACH;
160}
161
162static inline void SYSMMU_EVENT_LOG_IOMMU_MAP(
163 struct exynos_iommu_event_log *plog,
164 u32 start, u32 end, unsigned int pfn)
165{
166 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
167 log->event = EVENT_SYSMMU_IOMMU_MAP;
168 log->eventdata.iommu.start = start;
169 log->eventdata.iommu.end = end;
170 log->eventdata.iommu.pfn = pfn;
171}
172
173int exynos_iommu_init_event_log(struct exynos_iommu_event_log *log,
174 unsigned int log_len);
175
176void sysmmu_add_log_to_debugfs(struct dentry *debugfs_root,
177 struct exynos_iommu_event_log *log, const char *name);
178
179void iommu_add_log_to_debugfs(struct dentry *debugfs_root,
180 struct exynos_iommu_event_log *log, const char *name);
181
182#if defined(CONFIG_EXYNOS_IOVMM)
183void iovmm_add_log_to_debugfs(struct dentry *debugfs_root,
184 struct exynos_iommu_event_log *log, const char *name);
185#else
186#define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
187#endif
188
189DEFINE_SYSMMU_EVENT_LOG(ENABLE)
190DEFINE_SYSMMU_EVENT_LOG(DISABLE)
191DEFINE_SYSMMU_EVENT_LOG(TLB_INV_ALL)
192DEFINE_SYSMMU_EVENT_LOG(POWERON)
193DEFINE_SYSMMU_EVENT_LOG(POWEROFF)
194
7f7407f2
JK
195DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOMMU_ALLOCSLPD)
196DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOMMU_FREESLPD)
40727f6e
JK
197
198DEFINE_SYSMMU_EVENT_LOG_2ADDR(TLB_INV_RANGE)
199DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOMMU_UNMAP)
200DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOVMM_UNMAP)
201
202#endif /*_EXYNOS_IOMMU_LOG_H_*/