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#include <linux/seq_file.h>
41#include <linux/slab.h>
42#include <linux/export.h>
43#include <drm/drmP.h>
44
45
46
47
48
49
50
51
52static const struct drm_info_list drm_proc_list[] = {
53 {"name", drm_name_info, 0},
54 {"vm", drm_vm_info, 0},
55 {"clients", drm_clients_info, 0},
56 {"bufs", drm_bufs_info, 0},
57 {"gem_names", drm_gem_name_info, DRIVER_GEM},
58#if DRM_DEBUG_CODE
59 {"vma", drm_vma_info, 0},
60#endif
61};
62#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
63
64static int drm_proc_open(struct inode *inode, struct file *file)
65{
66 struct drm_info_node* node = PDE_DATA(inode);
67
68 return single_open(file, node->info_ent->show, node);
69}
70
71static const struct file_operations drm_proc_fops = {
72 .owner = THIS_MODULE,
73 .open = drm_proc_open,
74 .read = seq_read,
75 .llseek = seq_lseek,
76 .release = single_release,
77};
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92static int drm_proc_create_files(const struct drm_info_list *files, int count,
93 struct proc_dir_entry *root, struct drm_minor *minor)
94{
95 struct drm_device *dev = minor->dev;
96 struct proc_dir_entry *ent;
97 struct drm_info_node *tmp;
98 int i;
99
100 for (i = 0; i < count; i++) {
101 u32 features = files[i].driver_features;
102
103 if (features != 0 &&
104 (dev->driver->driver_features & features) != features)
105 continue;
106
107 tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
108 if (!tmp)
109 return -1;
110
111 tmp->minor = minor;
112 tmp->info_ent = &files[i];
113 list_add(&tmp->list, &minor->proc_nodes.list);
114
115 ent = proc_create_data(files[i].name, S_IRUGO, root,
116 &drm_proc_fops, tmp);
117 if (!ent) {
118 DRM_ERROR("Cannot create /proc/dri/%u/%s\n",
119 minor->index, files[i].name);
120 list_del(&tmp->list);
121 kfree(tmp);
122 return -1;
123 }
124 }
125 return 0;
126}
127
128
129
130
131
132
133
134
135
136
137
138
139
140int drm_proc_init(struct drm_minor *minor, struct proc_dir_entry *root)
141{
142 char name[12];
143 int ret;
144
145 INIT_LIST_HEAD(&minor->proc_nodes.list);
146 sprintf(name, "%u", minor->index);
147 minor->proc_root = proc_mkdir(name, root);
148 if (!minor->proc_root) {
149 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
150 return -1;
151 }
152
153 ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,
154 minor->proc_root, minor);
155 if (ret) {
156 remove_proc_subtree(name, root);
157 minor->proc_root = NULL;
158 DRM_ERROR("Failed to create core drm proc files\n");
159 return ret;
160 }
161
162 return 0;
163}
164
165static int drm_proc_remove_files(const struct drm_info_list *files, int count,
166 struct drm_minor *minor)
167{
168 struct list_head *pos, *q;
169 struct drm_info_node *tmp;
170 int i;
171
172 for (i = 0; i < count; i++) {
173 list_for_each_safe(pos, q, &minor->proc_nodes.list) {
174 tmp = list_entry(pos, struct drm_info_node, list);
175 if (tmp->info_ent == &files[i]) {
176 remove_proc_entry(files[i].name,
177 minor->proc_root);
178 list_del(pos);
179 kfree(tmp);
180 }
181 }
182 }
183 return 0;
184}
185
186
187
188
189
190
191
192
193
194
195
196int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
197{
198 char name[64];
199
200 if (!root || !minor->proc_root)
201 return 0;
202
203 drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);
204
205 sprintf(name, "%d", minor->index);
206 remove_proc_subtree(name, root);
207 return 0;
208}
209
210