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 "drmP.h"
42
43
44
45
46
47
48
49
50static struct drm_info_list drm_proc_list[] = {
51 {"name", drm_name_info, 0},
52 {"vm", drm_vm_info, 0},
53 {"clients", drm_clients_info, 0},
54 {"queues", drm_queues_info, 0},
55 {"bufs", drm_bufs_info, 0},
56 {"gem_names", drm_gem_name_info, DRIVER_GEM},
57 {"gem_objects", drm_gem_object_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(inode)->data;
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
92int drm_proc_create_files(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 char name[64];
99 int i, ret;
100
101 for (i = 0; i < count; i++) {
102 u32 features = files[i].driver_features;
103
104 if (features != 0 &&
105 (dev->driver->driver_features & features) != features)
106 continue;
107
108 tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
109 if (tmp == NULL) {
110 ret = -1;
111 goto fail;
112 }
113 tmp->minor = minor;
114 tmp->info_ent = &files[i];
115 list_add(&tmp->list, &minor->proc_nodes.list);
116
117 ent = proc_create_data(files[i].name, S_IRUGO, root,
118 &drm_proc_fops, tmp);
119 if (!ent) {
120 DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
121 name, files[i].name);
122 list_del(&tmp->list);
123 kfree(tmp);
124 ret = -1;
125 goto fail;
126 }
127
128 }
129 return 0;
130
131fail:
132 for (i = 0; i < count; i++)
133 remove_proc_entry(drm_proc_list[i].name, minor->proc_root);
134 return ret;
135}
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150int drm_proc_init(struct drm_minor *minor, int minor_id,
151 struct proc_dir_entry *root)
152{
153 struct drm_device *dev = minor->dev;
154 char name[64];
155 int ret;
156
157 INIT_LIST_HEAD(&minor->proc_nodes.list);
158 sprintf(name, "%d", minor_id);
159 minor->proc_root = proc_mkdir(name, root);
160 if (!minor->proc_root) {
161 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
162 return -1;
163 }
164
165 ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,
166 minor->proc_root, minor);
167 if (ret) {
168 remove_proc_entry(name, root);
169 minor->proc_root = NULL;
170 DRM_ERROR("Failed to create core drm proc files\n");
171 return ret;
172 }
173
174 if (dev->driver->proc_init) {
175 ret = dev->driver->proc_init(minor);
176 if (ret) {
177 DRM_ERROR("DRM: Driver failed to initialize "
178 "/proc/dri.\n");
179 return ret;
180 }
181 }
182 return 0;
183}
184
185int drm_proc_remove_files(struct drm_info_list *files, int count,
186 struct drm_minor *minor)
187{
188 struct list_head *pos, *q;
189 struct drm_info_node *tmp;
190 int i;
191
192 for (i = 0; i < count; i++) {
193 list_for_each_safe(pos, q, &minor->proc_nodes.list) {
194 tmp = list_entry(pos, struct drm_info_node, list);
195 if (tmp->info_ent == &files[i]) {
196 remove_proc_entry(files[i].name,
197 minor->proc_root);
198 list_del(pos);
199 kfree(tmp);
200 }
201 }
202 }
203 return 0;
204}
205
206
207
208
209
210
211
212
213
214
215
216int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
217{
218 struct drm_device *dev = minor->dev;
219 char name[64];
220
221 if (!root || !minor->proc_root)
222 return 0;
223
224 if (dev->driver->proc_cleanup)
225 dev->driver->proc_cleanup(minor);
226
227 drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);
228
229 sprintf(name, "%d", minor->index);
230 remove_proc_entry(name, root);
231
232 return 0;
233}
234
235