2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
5 * Data structure definition for Exynos IOMMU driver
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.
12 #ifndef _EXYNOS_IOMMU_LOG_H_
13 #define _EXYNOS_IOMMU_LOG_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>
23 enum sysmmu_event_log_event
{
24 EVENT_SYSMMU_NONE
, /* initialized value */
27 EVENT_SYSMMU_TLB_INV_RANGE
,
28 EVENT_SYSMMU_TLB_INV_VPN
,
29 EVENT_SYSMMU_TLB_INV_ALL
,
30 EVENT_SYSMMU_FLPD_FLUSH
,
32 EVENT_SYSMMU_DF_UNLOCK
,
33 EVENT_SYSMMU_DF_UNLOCK_ALL
,
36 EVENT_SYSMMU_BLOCK
, /* TODO: consider later */
37 EVENT_SYSMMU_UNBLOCK
, /* TODO: consider later */
38 #ifdef CONFIG_PM_RUNTIME
40 EVENT_SYSMMU_POWEROFF
,
42 EVENT_SYSMMU_IOMMU_ATTACH
,
43 EVENT_SYSMMU_IOMMU_DETACH
,
44 EVENT_SYSMMU_IOMMU_MAP
,
45 EVENT_SYSMMU_IOMMU_UNMAP
,
46 EVENT_SYSMMU_IOMMU_ALLOCSLPD
,
47 EVENT_SYSMMU_IOMMU_FREESLPD
,
48 EVENT_SYSMMU_IOVMM_MAP
,
49 EVENT_SYSMMU_IOVMM_UNMAP
52 struct sysmmu_event_range
{
57 struct sysmmu_event_PBLMM
{
61 struct sysmmu_event_PBSET
{
67 struct sysmmu_event_IOMMU_MAP
{
73 struct sysmmu_event_IOVMM_MAP
{
80 * event must be updated before eventdata because of eventdata.dev
81 * sysmmu_event_log is not protected by any locks. That means it permits
82 * some data inconsistency by race condition between updating and reading.
83 * However the problem arises when event is either IOMMU_ATTACH or
84 * IOMMU_DETACH because they stores a pointer to device descriptor to
85 * eventdata.dev and reading the sysmmu_event_log of those events refers
86 * to values pointed by eventdata.dev.
87 * Therefore, eventdata must be updated before event not to access invalid
88 * pointer by reading debugfs entries.
90 struct sysmmu_event_log
{
93 struct sysmmu_event_range range
;
94 struct sysmmu_event_PBLMM pblmm
;
95 struct sysmmu_event_PBSET pbset
;
96 struct sysmmu_event_IOMMU_MAP iommu
;
97 struct sysmmu_event_IOVMM_MAP iovmm
;
101 enum sysmmu_event_log_event event
;
104 struct exynos_iommu_event_log
{
106 unsigned int log_len
;
107 struct page
*page_log
;
108 struct sysmmu_event_log
*log
;
109 struct dentry
*debugfs_root
;
112 /* sizeof(struct sysmmu_event_log) = 8 + 4 * 3 + 4 = 24 bytes */
113 #define SYSMMU_LOG_LEN 1024
114 #define IOMMU_LOG_LEN 4096
115 #define IOVMM_LOG_LEN 512
117 #ifdef CONFIG_EXYNOS_IOMMU_EVENT_LOG
119 #define SYSMMU_DRVDATA_TO_LOG(data) (&(data)->log)
120 #define IOMMU_PRIV_TO_LOG(data) (&(data)->log)
121 #define IOMMU_TO_LOG(data) (&((struct exynos_iommu_domain *)(data)->priv)->log)
122 #define IOVMM_TO_LOG(data) (&(data)->log)
124 static inline struct sysmmu_event_log
*sysmmu_event_log_get(
125 struct exynos_iommu_event_log
*plog
)
127 struct sysmmu_event_log
*log
;
129 (unsigned int)atomic_inc_return(&plog
->index
) - 1;
130 log
= &plog
->log
[index
% plog
->log_len
];
131 log
->timestamp
= ktime_get();
135 #define DEFINE_SYSMMU_EVENT_LOG(evt) \
136 static inline void SYSMMU_EVENT_LOG_##evt(struct exynos_iommu_event_log *plog) \
138 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
139 log->event = EVENT_SYSMMU_##evt; \
142 #define DEFINE_SYSMMU_EVENT_LOG_1ADDR(evt) \
143 static inline void SYSMMU_EVENT_LOG_##evt( \
144 struct exynos_iommu_event_log *plog, u32 addr) \
146 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
147 log->eventdata.addr = addr; \
148 log->event = EVENT_SYSMMU_##evt; \
151 #define DEFINE_SYSMMU_EVENT_LOG_2ADDR(evt) \
152 static inline void SYSMMU_EVENT_LOG_##evt(struct exynos_iommu_event_log *plog, \
153 u32 start, u32 end) \
155 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
156 log->eventdata.range.start = start; \
157 log->eventdata.range.end = end; \
158 log->event = EVENT_SYSMMU_##evt; \
161 /* MMU_CFG is stored at pblmm.lmm for System MMU 3.1 and 3.2 */
162 static inline void SYSMMU_EVENT_LOG_PBLMM(struct exynos_iommu_event_log
*plog
,
163 u32 lmm
, u32 buf_num
)
165 struct sysmmu_event_log
*log
= sysmmu_event_log_get(plog
);
166 log
->eventdata
.pblmm
.lmm
= lmm
;
167 log
->eventdata
.pblmm
.buf_num
= buf_num
;
168 log
->event
= EVENT_SYSMMU_PBLMM
;
171 /* PB index is stored at pbset.config for System MMU 3.1 and 3.2 */
172 static inline void SYSMMU_EVENT_LOG_PBSET(struct exynos_iommu_event_log
*plog
,
173 u32 config
, u32 start
, u32 end
)
175 struct sysmmu_event_log
*log
= sysmmu_event_log_get(plog
);
176 log
->eventdata
.pbset
.config
= config
;
177 log
->eventdata
.pbset
.start
= start
;
178 log
->eventdata
.pbset
.end
= end
;
179 log
->event
= EVENT_SYSMMU_PBSET
;
182 static inline void SYSMMU_EVENT_LOG_IOVMM_MAP(
183 struct exynos_iommu_event_log
*plog
,
184 u32 start
, u32 end
, unsigned int dummy
)
186 struct sysmmu_event_log
*log
= sysmmu_event_log_get(plog
);
187 log
->eventdata
.iovmm
.start
= start
;
188 log
->eventdata
.iovmm
.end
= end
;
189 log
->eventdata
.iovmm
.dummy
= dummy
;
190 log
->event
= EVENT_SYSMMU_IOVMM_MAP
;
193 static inline void SYSMMU_EVENT_LOG_IOMMU_ATTACH(
194 struct exynos_iommu_event_log
*plog
, struct device
*dev
)
196 struct sysmmu_event_log
*log
= sysmmu_event_log_get(plog
);
197 log
->eventdata
.dev
= dev
;
198 log
->event
= EVENT_SYSMMU_IOMMU_ATTACH
;
201 static inline void SYSMMU_EVENT_LOG_IOMMU_DETACH(
202 struct exynos_iommu_event_log
*plog
, struct device
*dev
)
204 struct sysmmu_event_log
*log
= sysmmu_event_log_get(plog
);
205 log
->eventdata
.dev
= dev
;
206 log
->event
= EVENT_SYSMMU_IOMMU_DETACH
;
209 static inline void SYSMMU_EVENT_LOG_IOMMU_MAP(
210 struct exynos_iommu_event_log
*plog
,
211 u32 start
, u32 end
, unsigned int pfn
)
213 struct sysmmu_event_log
*log
= sysmmu_event_log_get(plog
);
214 log
->event
= EVENT_SYSMMU_IOMMU_MAP
;
215 log
->eventdata
.iommu
.start
= start
;
216 log
->eventdata
.iommu
.end
= end
;
217 log
->eventdata
.iommu
.pfn
= pfn
;
220 int exynos_iommu_init_event_log(struct exynos_iommu_event_log
*log
,
221 unsigned int log_len
);
223 static inline void exynos_iommu_free_event_log(
224 struct exynos_iommu_event_log
*plog
, unsigned int log_len
)
227 __free_pages(plog
->page_log
, get_order(sizeof(*(plog
->log
)) * log_len
));
230 void sysmmu_add_log_to_debugfs(struct dentry
*debugfs_root
,
231 struct exynos_iommu_event_log
*log
, const char *name
);
233 void iommu_add_log_to_debugfs(struct dentry
*debugfs_root
,
234 struct exynos_iommu_event_log
*log
, const char *name
);
236 #if defined(CONFIG_EXYNOS_IOVMM) || defined(CONFIG_EXYNOS_IOVMM_V6)
237 void iovmm_add_log_to_debugfs(struct dentry
*debugfs_root
,
238 struct exynos_iommu_event_log
*log
, const char *name
);
240 #define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
243 #else /* !CONFIG_EXYNOS_IOMMU_EVENT_LOG */
245 #define SYSMMU_DRVDATA_TO_LOG(data) NULL
246 #define IOMMU_PRIV_TO_LOG(data) NULL
247 #define IOMMU_TO_LOG(data) NULL
248 #define IOVMM_TO_LOG(data) NULL
250 static inline int exynos_iommu_init_event_log(
251 struct exynos_iommu_event_log
*log
, unsigned int log_len
)
256 #define exynos_iommu_free_event_log(plog, log_len) do { } while (0)
258 #define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
260 #define DEFINE_SYSMMU_EVENT_LOG(event) \
261 static inline void SYSMMU_EVENT_LOG_##event( \
262 struct exynos_iommu_event_log *plog) \
266 #define DEFINE_SYSMMU_EVENT_LOG_1ADDR(event) \
267 static inline void SYSMMU_EVENT_LOG_##event( \
268 struct exynos_iommu_event_log *plog, u32 start) \
272 #define DEFINE_SYSMMU_EVENT_LOG_2ADDR(event) \
273 static inline void SYSMMU_EVENT_LOG_##event( \
274 struct exynos_iommu_event_log *plog, u32 start, u32 end) \
278 static inline void SYSMMU_EVENT_LOG_PBLMM(struct exynos_iommu_event_log
*plog
,
279 u32 lmm
, u32 buf_num
)
283 static inline void SYSMMU_EVENT_LOG_PBSET(struct exynos_iommu_event_log
*plog
,
284 u32 config
, u32 start
, u32 end
)
288 static inline void SYSMMU_EVENT_LOG_IOMMU_MAP(
289 struct exynos_iommu_event_log
*plog
,
290 u32 start
, u32 end
, unsigned int pfn
)
294 static inline void SYSMMU_EVENT_LOG_IOVMM_MAP(
295 struct exynos_iommu_event_log
*plog
,
296 u32 start
, u32 end
, size_t dummy
)
300 static inline void SYSMMU_EVENT_LOG_IOMMU_ATTACH(
301 struct exynos_iommu_event_log
*plog
, struct device
*dev
)
305 static inline void SYSMMU_EVENT_LOG_IOMMU_DETACH(
306 struct exynos_iommu_event_log
*plog
, struct device
*dev
)
310 #define sysmmu_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
311 #define iommu_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
312 #define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
314 #endif /* CONFIG_EXYNOS_IOMMU_EVENT_LOG */
316 DEFINE_SYSMMU_EVENT_LOG(ENABLE
)
317 DEFINE_SYSMMU_EVENT_LOG(DISABLE
)
318 DEFINE_SYSMMU_EVENT_LOG(TLB_INV_ALL
)
319 DEFINE_SYSMMU_EVENT_LOG(DF_UNLOCK_ALL
)
320 DEFINE_SYSMMU_EVENT_LOG(BLOCK
)
321 DEFINE_SYSMMU_EVENT_LOG(UNBLOCK
)
322 #ifdef CONFIG_PM_RUNTIME
323 DEFINE_SYSMMU_EVENT_LOG(POWERON
)
324 DEFINE_SYSMMU_EVENT_LOG(POWEROFF
)
327 DEFINE_SYSMMU_EVENT_LOG_1ADDR(TLB_INV_VPN
)
328 DEFINE_SYSMMU_EVENT_LOG_1ADDR(FLPD_FLUSH
)
329 DEFINE_SYSMMU_EVENT_LOG_1ADDR(DF
)
330 DEFINE_SYSMMU_EVENT_LOG_1ADDR(DF_UNLOCK
)
331 DEFINE_SYSMMU_EVENT_LOG_1ADDR(IOMMU_ALLOCSLPD
)
332 DEFINE_SYSMMU_EVENT_LOG_1ADDR(IOMMU_FREESLPD
)
334 DEFINE_SYSMMU_EVENT_LOG_2ADDR(TLB_INV_RANGE
)
335 DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOMMU_UNMAP
)
336 DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOVMM_UNMAP
)
338 #endif /*_EXYNOS_IOMMU_LOG_H_*/