Blame view

drivers/iommu/omap-iommu-debug.c 6.4 KB
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * omap iommu: debugfs interface
   *
   * Copyright (C) 2008-2009 Nokia Corporation
   *
   * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  #include <linux/err.h>
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
14
  #include <linux/io.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
16
  #include <linux/uaccess.h>
69c2c1963   Suman Anna   iommu/omap: Move ...
17
  #include <linux/pm_runtime.h>
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
18
  #include <linux/debugfs.h>
2ab7c8481   Tony Lindgren   ARM: OMAP2+: Move...
19
  #include <linux/platform_data/iommu-omap.h>
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
20

2f7702af6   Ido Yariv   ARM: OMAP2+: Move...
21
  #include "omap-iopgtable.h"
ed1c7de29   Tony Lindgren   ARM: OMAP2+: Move...
22
  #include "omap-iommu.h"
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
23

14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
24
25
26
  static DEFINE_MUTEX(iommu_debug_lock);
  
  static struct dentry *iommu_debug_root;
c5cf5c537   Suman Anna   iommu/omap: Fix b...
27
28
29
30
  static inline bool is_omap_iommu_detached(struct omap_iommu *obj)
  {
  	return !obj->domain;
  }
69c2c1963   Suman Anna   iommu/omap: Move ...
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
  #define pr_reg(name)							\
  	do {								\
  		ssize_t bytes;						\
  		const char *str = "%20s: %08x
  ";			\
  		const int maxcol = 32;					\
  		bytes = snprintf(p, maxcol, str, __stringify(name),	\
  				 iommu_read_reg(obj, MMU_##name));	\
  		p += bytes;						\
  		len -= bytes;						\
  		if (len < maxcol)					\
  			goto out;					\
  	} while (0)
  
  static ssize_t
  omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
  {
  	char *p = buf;
  
  	pr_reg(REVISION);
  	pr_reg(IRQSTATUS);
  	pr_reg(IRQENABLE);
  	pr_reg(WALKING_ST);
  	pr_reg(CNTL);
  	pr_reg(FAULT_AD);
  	pr_reg(TTB);
  	pr_reg(LOCK);
  	pr_reg(LD_TLB);
  	pr_reg(CAM);
  	pr_reg(RAM);
  	pr_reg(GFLUSH);
  	pr_reg(FLUSH_ENTRY);
  	pr_reg(READ_CAM);
  	pr_reg(READ_RAM);
  	pr_reg(EMU_FAULT_AD);
  out:
  	return p - buf;
  }
  
  static ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf,
  				   ssize_t bytes)
  {
  	if (!obj || !buf)
  		return -EINVAL;
  
  	pm_runtime_get_sync(obj->dev);
  
  	bytes = omap2_iommu_dump_ctx(obj, buf, bytes);
  
  	pm_runtime_put_sync(obj->dev);
  
  	return bytes;
  }
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
84
85
86
  static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
  			       size_t count, loff_t *ppos)
  {
61c753526   Suman Anna   iommu/omap: Integ...
87
  	struct omap_iommu *obj = file->private_data;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
88
89
  	char *p, *buf;
  	ssize_t bytes;
c5cf5c537   Suman Anna   iommu/omap: Fix b...
90
91
  	if (is_omap_iommu_detached(obj))
  		return -EPERM;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
92
93
94
95
96
97
  	buf = kmalloc(count, GFP_KERNEL);
  	if (!buf)
  		return -ENOMEM;
  	p = buf;
  
  	mutex_lock(&iommu_debug_lock);
6c32df437   Ohad Ben-Cohen   omap: iommu: omap...
98
  	bytes = omap_iommu_dump_ctx(obj, p, count);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
99
100
101
102
103
104
105
  	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
  
  	mutex_unlock(&iommu_debug_lock);
  	kfree(buf);
  
  	return bytes;
  }
69c2c1963   Suman Anna   iommu/omap: Move ...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  static int
  __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
  {
  	int i;
  	struct iotlb_lock saved;
  	struct cr_regs tmp;
  	struct cr_regs *p = crs;
  
  	pm_runtime_get_sync(obj->dev);
  	iotlb_lock_get(obj, &saved);
  
  	for_each_iotlb_cr(obj, num, i, tmp) {
  		if (!iotlb_cr_valid(&tmp))
  			continue;
  		*p++ = tmp;
  	}
  
  	iotlb_lock_set(obj, &saved);
  	pm_runtime_put_sync(obj->dev);
  
  	return  p - crs;
  }
  
  static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
e203db293   Salva Peiró   iommu/omap: Fix d...
130
  			     struct seq_file *s)
69c2c1963   Suman Anna   iommu/omap: Move ...
131
  {
6798a8caa   Joe Perches   fs/seq_file: conv...
132
133
  	seq_printf(s, "%08x %08x %01x
  ", cr->cam, cr->ram,
a5c0e0b4a   Suman Anna   iommu/omap: Align...
134
  		   (cr->cam & MMU_CAM_P) ? 1 : 0);
6798a8caa   Joe Perches   fs/seq_file: conv...
135
  	return 0;
69c2c1963   Suman Anna   iommu/omap: Move ...
136
  }
e203db293   Salva Peiró   iommu/omap: Fix d...
137
  static size_t omap_dump_tlb_entries(struct omap_iommu *obj, struct seq_file *s)
69c2c1963   Suman Anna   iommu/omap: Move ...
138
139
140
  {
  	int i, num;
  	struct cr_regs *cr;
69c2c1963   Suman Anna   iommu/omap: Move ...
141

e203db293   Salva Peiró   iommu/omap: Fix d...
142
  	num = obj->nr_tlb_entries;
69c2c1963   Suman Anna   iommu/omap: Move ...
143
144
145
146
147
148
149
  
  	cr = kcalloc(num, sizeof(*cr), GFP_KERNEL);
  	if (!cr)
  		return 0;
  
  	num = __dump_tlb_entries(obj, cr, num);
  	for (i = 0; i < num; i++)
e203db293   Salva Peiró   iommu/omap: Fix d...
150
  		iotlb_dump_cr(obj, cr + i, s);
69c2c1963   Suman Anna   iommu/omap: Move ...
151
  	kfree(cr);
e203db293   Salva Peiró   iommu/omap: Fix d...
152
  	return 0;
69c2c1963   Suman Anna   iommu/omap: Move ...
153
  }
e203db293   Salva Peiró   iommu/omap: Fix d...
154
  static int debug_read_tlb(struct seq_file *s, void *data)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
155
  {
e203db293   Salva Peiró   iommu/omap: Fix d...
156
  	struct omap_iommu *obj = s->private;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
157

c5cf5c537   Suman Anna   iommu/omap: Fix b...
158
159
  	if (is_omap_iommu_detached(obj))
  		return -EPERM;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
160
  	mutex_lock(&iommu_debug_lock);
e203db293   Salva Peiró   iommu/omap: Fix d...
161
162
163
164
165
  	seq_printf(s, "%8s %8s
  ", "cam:", "ram:");
  	seq_puts(s, "-----------------------------------------
  ");
  	omap_dump_tlb_entries(obj, s);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
166
167
  
  	mutex_unlock(&iommu_debug_lock);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
168

e203db293   Salva Peiró   iommu/omap: Fix d...
169
  	return 0;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
170
  }
9c83e9f38   Suman Anna   iommu/omap: Switc...
171
  static void dump_ioptable(struct seq_file *s)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
172
  {
9c83e9f38   Suman Anna   iommu/omap: Switc...
173
174
175
176
  	int i, j;
  	u32 da;
  	u32 *iopgd, *iopte;
  	struct omap_iommu *obj = s->private;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
177
178
179
180
181
  
  	spin_lock(&obj->page_table_lock);
  
  	iopgd = iopgd_offset(obj, 0);
  	for (i = 0; i < PTRS_PER_IOPGD; i++, iopgd++) {
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
182
183
184
185
186
  		if (!*iopgd)
  			continue;
  
  		if (!(*iopgd & IOPGD_TABLE)) {
  			da = i << IOPGD_SHIFT;
9c83e9f38   Suman Anna   iommu/omap: Switc...
187
188
  			seq_printf(s, "1: 0x%08x 0x%08x
  ", da, *iopgd);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
189
190
191
192
  			continue;
  		}
  
  		iopte = iopte_offset(iopgd, 0);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
193
194
195
196
197
  		for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) {
  			if (!*iopte)
  				continue;
  
  			da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
9c83e9f38   Suman Anna   iommu/omap: Switc...
198
199
  			seq_printf(s, "2: 0x%08x 0x%08x
  ", da, *iopte);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
200
201
  		}
  	}
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
202

9c83e9f38   Suman Anna   iommu/omap: Switc...
203
  	spin_unlock(&obj->page_table_lock);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
204
  }
9c83e9f38   Suman Anna   iommu/omap: Switc...
205
  static int debug_read_pagetable(struct seq_file *s, void *data)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
206
  {
9c83e9f38   Suman Anna   iommu/omap: Switc...
207
  	struct omap_iommu *obj = s->private;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
208

c5cf5c537   Suman Anna   iommu/omap: Fix b...
209
210
  	if (is_omap_iommu_detached(obj))
  		return -EPERM;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
211
  	mutex_lock(&iommu_debug_lock);
9c83e9f38   Suman Anna   iommu/omap: Switc...
212
213
214
215
216
  	seq_printf(s, "L: %8s %8s
  ", "da:", "pte:");
  	seq_puts(s, "--------------------------
  ");
  	dump_ioptable(s);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
217
218
  
  	mutex_unlock(&iommu_debug_lock);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
219

9c83e9f38   Suman Anna   iommu/omap: Switc...
220
  	return 0;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
221
  }
9c83e9f38   Suman Anna   iommu/omap: Switc...
222
223
224
225
226
227
228
229
230
231
232
233
  #define DEBUG_SEQ_FOPS_RO(name)						       \
  	static int debug_open_##name(struct inode *inode, struct file *file)   \
  	{								       \
  		return single_open(file, debug_read_##name, inode->i_private); \
  	}								       \
  									       \
  	static const struct file_operations debug_##name##_fops = {	       \
  		.open		= debug_open_##name,			       \
  		.read		= seq_read,				       \
  		.llseek		= seq_lseek,				       \
  		.release	= single_release,			       \
  	}
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
234
235
  #define DEBUG_FOPS_RO(name)						\
  	static const struct file_operations debug_##name##_fops = {	\
234e34058   Stephen Boyd   simple_open: auto...
236
  		.open = simple_open,					\
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
237
  		.read = debug_read_##name,				\
c0b0aca0e   Arnd Bergmann   arm/omap: use gen...
238
  		.llseek = generic_file_llseek,				\
5b39a37ab   Suman Anna   iommu/omap: Remov...
239
  	}
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
240

14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
241
  DEBUG_FOPS_RO(regs);
e203db293   Salva Peiró   iommu/omap: Fix d...
242
  DEBUG_SEQ_FOPS_RO(tlb);
9c83e9f38   Suman Anna   iommu/omap: Switc...
243
  DEBUG_SEQ_FOPS_RO(pagetable);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
244
245
246
247
  
  #define __DEBUG_ADD_FILE(attr, mode)					\
  	{								\
  		struct dentry *dent;					\
61c753526   Suman Anna   iommu/omap: Integ...
248
249
  		dent = debugfs_create_file(#attr, mode, obj->debug_dir,	\
  					   obj, &debug_##attr##_fops);	\
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
250
  		if (!dent)						\
61c753526   Suman Anna   iommu/omap: Integ...
251
  			goto err;					\
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
252
  	}
ff3a2b73b   Joe Perches   drivers/iommu/oma...
253
  #define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 0400)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
254

61c753526   Suman Anna   iommu/omap: Integ...
255
  void omap_iommu_debugfs_add(struct omap_iommu *obj)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
256
  {
61c753526   Suman Anna   iommu/omap: Integ...
257
  	struct dentry *d;
46451d622   Ohad Ben-Cohen   iommu/omap: fix e...
258

61c753526   Suman Anna   iommu/omap: Integ...
259
260
  	if (!iommu_debug_root)
  		return;
46451d622   Ohad Ben-Cohen   iommu/omap: fix e...
261

61c753526   Suman Anna   iommu/omap: Integ...
262
263
264
  	obj->debug_dir = debugfs_create_dir(obj->name, iommu_debug_root);
  	if (!obj->debug_dir)
  		return;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
265

61c753526   Suman Anna   iommu/omap: Integ...
266
  	d = debugfs_create_u8("nr_tlb_entries", 0400, obj->debug_dir,
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
267
268
  			      (u8 *)&obj->nr_tlb_entries);
  	if (!d)
61c753526   Suman Anna   iommu/omap: Integ...
269
  		return;
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
270

14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
271
272
  	DEBUG_ADD_FILE_RO(regs);
  	DEBUG_ADD_FILE_RO(tlb);
3ca5db072   Suman Anna   iommu/omap: Make ...
273
  	DEBUG_ADD_FILE_RO(pagetable);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
274

61c753526   Suman Anna   iommu/omap: Integ...
275
  	return;
46451d622   Ohad Ben-Cohen   iommu/omap: fix e...
276

61c753526   Suman Anna   iommu/omap: Integ...
277
278
  err:
  	debugfs_remove_recursive(obj->debug_dir);
46451d622   Ohad Ben-Cohen   iommu/omap: fix e...
279
  }
61c753526   Suman Anna   iommu/omap: Integ...
280
  void omap_iommu_debugfs_remove(struct omap_iommu *obj)
46451d622   Ohad Ben-Cohen   iommu/omap: fix e...
281
  {
61c753526   Suman Anna   iommu/omap: Integ...
282
283
  	if (!obj->debug_dir)
  		return;
46451d622   Ohad Ben-Cohen   iommu/omap: fix e...
284

61c753526   Suman Anna   iommu/omap: Integ...
285
  	debugfs_remove_recursive(obj->debug_dir);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
286
  }
61c753526   Suman Anna   iommu/omap: Integ...
287
  void __init omap_iommu_debugfs_init(void)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
288
  {
61c753526   Suman Anna   iommu/omap: Integ...
289
290
291
292
  	iommu_debug_root = debugfs_create_dir("omap_iommu", NULL);
  	if (!iommu_debug_root)
  		pr_err("can't create debugfs dir
  ");
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
293
  }
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
294

61c753526   Suman Anna   iommu/omap: Integ...
295
  void __exit omap_iommu_debugfs_exit(void)
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
296
  {
61c753526   Suman Anna   iommu/omap: Integ...
297
  	debugfs_remove(iommu_debug_root);
14e0e6796   Hiroshi DOYU   OMAP: iommu: add ...
298
  }