1 /* proc.c -- /proc support for DRM -*- linux-c -*-
2  * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
3  *
4  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6  * All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the next
16  * paragraph) shall be included in all copies or substantial portions of the
17  * Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  *
27  * Authors:
28  *    Rickard E. (Rik) Faith <faith@valinux.com>
29  */
30 
31 #define __NO_VERSION__
32 #include "drmP.h"
33 
34 static struct proc_dir_entry *drm_root	   = NULL;
35 static struct proc_dir_entry *drm_dev_root = NULL;
36 static char		     drm_slot_name[64];
37 
38 static int	   drm_name_info(char *buf, char **start, off_t offset,
39 				 int len, int *eof, void *data);
40 static int	   drm_vm_info(char *buf, char **start, off_t offset,
41 			       int len, int *eof, void *data);
42 static int	   drm_clients_info(char *buf, char **start, off_t offset,
43 				    int len, int *eof, void *data);
44 static int	   drm_queues_info(char *buf, char **start, off_t offset,
45 				   int len, int *eof, void *data);
46 static int	   drm_bufs_info(char *buf, char **start, off_t offset,
47 				 int len, int *eof, void *data);
48 #if DRM_DEBUG_CODE
49 static int	   drm_vma_info(char *buf, char **start, off_t offset,
50 				int len, int *eof, void *data);
51 #endif
52 #if DRM_DMA_HISTOGRAM
53 static int	   drm_histo_info(char *buf, char **start, off_t offset,
54 				  int len, int *eof, void *data);
55 #endif
56 
57 struct drm_proc_list {
58 	const char *name;
59 	int	   (*f)(char *, char **, off_t, int, int *, void *);
60 } drm_proc_list[] = {
61 	{ "name",    drm_name_info    },
62 	{ "mem",     drm_mem_info     },
63 	{ "vm",	     drm_vm_info      },
64 	{ "clients", drm_clients_info },
65 	{ "queues",  drm_queues_info  },
66 	{ "bufs",    drm_bufs_info    },
67 #if DRM_DEBUG_CODE
68 	{ "vma",     drm_vma_info     },
69 #endif
70 #if DRM_DMA_HISTOGRAM
71 	{ "histo",   drm_histo_info   },
72 #endif
73 };
74 #define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
75 
drm_proc_init(drm_device_t * dev)76 int drm_proc_init(drm_device_t *dev)
77 {
78 	struct proc_dir_entry *ent;
79 	int		      i, j;
80 
81 	drm_root = create_proc_entry("dri", S_IFDIR, NULL);
82 	if (!drm_root) {
83 		DRM_ERROR("Cannot create /proc/dri\n");
84 		return -1;
85 	}
86 
87 				/* Instead of doing this search, we should
88 				   add some global support for /proc/dri. */
89 	for (i = 0; i < 8; i++) {
90 		sprintf(drm_slot_name, "dri/%d", i);
91 		drm_dev_root = create_proc_entry(drm_slot_name, S_IFDIR, NULL);
92 		if (!drm_dev_root) {
93 			DRM_ERROR("Cannot create /proc/%s\n", drm_slot_name);
94 			remove_proc_entry("dri", NULL);
95 			break;
96 		}
97 		if (drm_dev_root->nlink == 2) break;
98 		drm_dev_root = NULL;
99 	}
100 	if (!drm_dev_root) {
101 		DRM_ERROR("Cannot find slot in /proc/dri\n");
102 		return -1;
103 	}
104 
105 	for (i = 0; i < DRM_PROC_ENTRIES; i++) {
106 		ent = create_proc_entry(drm_proc_list[i].name,
107 					S_IFREG|S_IRUGO, drm_dev_root);
108 		if (!ent) {
109 			DRM_ERROR("Cannot create /proc/%s/%s\n",
110 				  drm_slot_name, drm_proc_list[i].name);
111 			for (j = 0; j < i; j++)
112 				remove_proc_entry(drm_proc_list[i].name,
113 						  drm_dev_root);
114 			remove_proc_entry(drm_slot_name, NULL);
115 			remove_proc_entry("dri", NULL);
116 			return -1;
117 		}
118 		ent->read_proc = drm_proc_list[i].f;
119 		ent->data      = dev;
120 	}
121 
122 	return 0;
123 }
124 
125 
drm_proc_cleanup(void)126 int drm_proc_cleanup(void)
127 {
128 	int i;
129 
130 	if (drm_root) {
131 		if (drm_dev_root) {
132 			for (i = 0; i < DRM_PROC_ENTRIES; i++) {
133 				remove_proc_entry(drm_proc_list[i].name,
134 						  drm_dev_root);
135 			}
136 			remove_proc_entry(drm_slot_name, NULL);
137 		}
138 		remove_proc_entry("dri", NULL);
139 		remove_proc_entry(DRM_NAME, NULL);
140 	}
141 	drm_root = drm_dev_root = NULL;
142 	return 0;
143 }
144 
drm_name_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)145 static int drm_name_info(char *buf, char **start, off_t offset, int len,
146 			 int *eof, void *data)
147 {
148 	drm_device_t *dev = (drm_device_t *)data;
149 
150 	if (offset > 0) return 0; /* no partial requests */
151 	len  = 0;
152 	*eof = 1;
153 
154 	if (dev->unique) {
155 		DRM_PROC_PRINT("%s 0x%x %s\n",
156 			       dev->name, dev->device, dev->unique);
157 	} else {
158 		DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
159 	}
160 	return len;
161 }
162 
_drm_vm_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)163 static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
164 			int *eof, void *data)
165 {
166 	drm_device_t *dev = (drm_device_t *)data;
167 	drm_map_t    *map;
168 				/* Hardcoded from _DRM_FRAME_BUFFER,
169                                    _DRM_REGISTERS, _DRM_SHM, and
170                                    _DRM_AGP. */
171 	const char   *types[] = { "FB", "REG", "SHM", "AGP" };
172 	const char   *type;
173 	int	     i;
174 
175 	if (offset > 0) return 0; /* no partial requests */
176 	len  = 0;
177 	*eof = 1;
178 	DRM_PROC_PRINT("slot	 offset	      size type flags	 "
179 		       "address mtrr\n\n");
180 	for (i = 0; i < dev->map_count; i++) {
181 		map = dev->maplist[i];
182 		if (map->type < 0 || map->type > 3) type = "??";
183 		else				    type = types[map->type];
184 		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
185 			       i,
186 			       map->offset,
187 			       map->size,
188 			       type,
189 			       map->flags,
190 			       (unsigned long)map->handle);
191 		if (map->mtrr < 0) {
192 			DRM_PROC_PRINT("none\n");
193 		} else {
194 			DRM_PROC_PRINT("%4d\n", map->mtrr);
195 		}
196 	}
197 
198 	return len;
199 }
200 
drm_vm_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)201 static int drm_vm_info(char *buf, char **start, off_t offset, int len,
202 		       int *eof, void *data)
203 {
204 	drm_device_t *dev = (drm_device_t *)data;
205 	int	     ret;
206 
207 	down(&dev->struct_sem);
208 	ret = _drm_vm_info(buf, start, offset, len, eof, data);
209 	up(&dev->struct_sem);
210 	return ret;
211 }
212 
213 
_drm_queues_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)214 static int _drm_queues_info(char *buf, char **start, off_t offset, int len,
215 			    int *eof, void *data)
216 {
217 	drm_device_t *dev = (drm_device_t *)data;
218 	int	     i;
219 	drm_queue_t  *q;
220 
221 	if (offset > 0) return 0; /* no partial requests */
222 	len  = 0;
223 	*eof = 1;
224 	DRM_PROC_PRINT("  ctx/flags   use   fin"
225 		       "   blk/rw/rwf  wait    flushed	   queued"
226 		       "      locks\n\n");
227 	for (i = 0; i < dev->queue_count; i++) {
228 		q = dev->queuelist[i];
229 		atomic_inc(&q->use_count);
230 		DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
231 				   "%5d/0x%03x %5d %5d"
232 				   " %5d/%c%c/%c%c%c %5Zd %10d %10d %10d\n",
233 				   i,
234 				   q->flags,
235 				   atomic_read(&q->use_count),
236 				   atomic_read(&q->finalization),
237 				   atomic_read(&q->block_count),
238 				   atomic_read(&q->block_read) ? 'r' : '-',
239 				   atomic_read(&q->block_write) ? 'w' : '-',
240 				   waitqueue_active(&q->read_queue) ? 'r':'-',
241 				   waitqueue_active(&q->write_queue) ? 'w':'-',
242 				   waitqueue_active(&q->flush_queue) ? 'f':'-',
243 				   DRM_BUFCOUNT(&q->waitlist),
244 				   atomic_read(&q->total_flushed),
245 				   atomic_read(&q->total_queued),
246 				   atomic_read(&q->total_locks));
247 		atomic_dec(&q->use_count);
248 	}
249 
250 	return len;
251 }
252 
drm_queues_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)253 static int drm_queues_info(char *buf, char **start, off_t offset, int len,
254 			   int *eof, void *data)
255 {
256 	drm_device_t *dev = (drm_device_t *)data;
257 	int	     ret;
258 
259 	down(&dev->struct_sem);
260 	ret = _drm_queues_info(buf, start, offset, len, eof, data);
261 	up(&dev->struct_sem);
262 	return ret;
263 }
264 
265 /* drm_bufs_info is called whenever a process reads
266    /dev/drm/<dev>/bufs. */
267 
_drm_bufs_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)268 static int _drm_bufs_info(char *buf, char **start, off_t offset, int len,
269 			  int *eof, void *data)
270 {
271 	drm_device_t	 *dev = (drm_device_t *)data;
272 	drm_device_dma_t *dma = dev->dma;
273 	int		 i;
274 
275 	if (!dma)	return 0;
276 	if (offset > 0) return 0; /* no partial requests */
277 	len  = 0;
278 	*eof = 1;
279 	DRM_PROC_PRINT(" o     size count  free	 segs pages    kB\n\n");
280 	for (i = 0; i <= DRM_MAX_ORDER; i++) {
281 		if (dma->bufs[i].buf_count)
282 			DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
283 				       i,
284 				       dma->bufs[i].buf_size,
285 				       dma->bufs[i].buf_count,
286 				       atomic_read(&dma->bufs[i]
287 						   .freelist.count),
288 				       dma->bufs[i].seg_count,
289 				       dma->bufs[i].seg_count
290 				       *(1 << dma->bufs[i].page_order),
291 				       (dma->bufs[i].seg_count
292 					* (1 << dma->bufs[i].page_order))
293 				       * PAGE_SIZE / 1024);
294 	}
295 	DRM_PROC_PRINT("\n");
296 	for (i = 0; i < dma->buf_count; i++) {
297 		if (i && !(i%32)) DRM_PROC_PRINT("\n");
298 		DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
299 	}
300 	DRM_PROC_PRINT("\n");
301 
302 	return len;
303 }
304 
drm_bufs_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)305 static int drm_bufs_info(char *buf, char **start, off_t offset, int len,
306 			 int *eof, void *data)
307 {
308 	drm_device_t *dev = (drm_device_t *)data;
309 	int	     ret;
310 
311 	down(&dev->struct_sem);
312 	ret = _drm_bufs_info(buf, start, offset, len, eof, data);
313 	up(&dev->struct_sem);
314 	return ret;
315 }
316 
317 
_drm_clients_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)318 static int _drm_clients_info(char *buf, char **start, off_t offset, int len,
319 			     int *eof, void *data)
320 {
321 	drm_device_t *dev = (drm_device_t *)data;
322 	drm_file_t   *priv;
323 
324 	if (offset > 0) return 0; /* no partial requests */
325 	len  = 0;
326 	*eof = 1;
327 	DRM_PROC_PRINT("a dev	pid    uid	magic	  ioctls\n\n");
328 	for (priv = dev->file_first; priv; priv = priv->next) {
329 		DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
330 			       priv->authenticated ? 'y' : 'n',
331 			       priv->minor,
332 			       priv->pid,
333 			       priv->uid,
334 			       priv->magic,
335 			       priv->ioctl_count);
336 	}
337 
338 	return len;
339 }
340 
drm_clients_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)341 static int drm_clients_info(char *buf, char **start, off_t offset, int len,
342 			    int *eof, void *data)
343 {
344 	drm_device_t *dev = (drm_device_t *)data;
345 	int	     ret;
346 
347 	down(&dev->struct_sem);
348 	ret = _drm_clients_info(buf, start, offset, len, eof, data);
349 	up(&dev->struct_sem);
350 	return ret;
351 }
352 
353 #if DRM_DEBUG_CODE
354 
355 #define DRM_VMA_VERBOSE 0
356 
_drm_vma_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)357 static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
358 			 int *eof, void *data)
359 {
360 	drm_device_t	      *dev = (drm_device_t *)data;
361 	drm_vma_entry_t	      *pt;
362 	struct vm_area_struct *vma;
363 #if DRM_VMA_VERBOSE
364 	unsigned long	      i;
365 	unsigned long	      address;
366 	pgd_t		      *pgd;
367 	pmd_t		      *pmd;
368 	pte_t		      *pte;
369 #endif
370 #if defined(__i386__)
371 	unsigned int	      pgprot;
372 #endif
373 
374 	if (offset > 0) return 0; /* no partial requests */
375 	len  = 0;
376 	*eof = 1;
377 	DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
378 		       atomic_read(&dev->vma_count),
379 		       high_memory, virt_to_phys(high_memory));
380 	for (pt = dev->vmalist; pt; pt = pt->next) {
381 		if (!(vma = pt->vma)) continue;
382 		DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
383 			       pt->pid,
384 			       vma->vm_start,
385 			       vma->vm_end,
386 			       vma->vm_flags & VM_READ	   ? 'r' : '-',
387 			       vma->vm_flags & VM_WRITE	   ? 'w' : '-',
388 			       vma->vm_flags & VM_EXEC	   ? 'x' : '-',
389 			       vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
390 			       vma->vm_flags & VM_LOCKED   ? 'l' : '-',
391 			       vma->vm_flags & VM_IO	   ? 'i' : '-',
392 			       VM_OFFSET(vma));
393 
394 #if defined(__i386__)
395 		pgprot = pgprot_val(vma->vm_page_prot);
396 		DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
397 			       pgprot & _PAGE_PRESENT  ? 'p' : '-',
398 			       pgprot & _PAGE_RW       ? 'w' : 'r',
399 			       pgprot & _PAGE_USER     ? 'u' : 's',
400 			       pgprot & _PAGE_PWT      ? 't' : 'b',
401 			       pgprot & _PAGE_PCD      ? 'u' : 'c',
402 			       pgprot & _PAGE_ACCESSED ? 'a' : '-',
403 			       pgprot & _PAGE_DIRTY    ? 'd' : '-',
404 			       pgprot & _PAGE_PSE      ? 'm' : 'k',
405 			       pgprot & _PAGE_GLOBAL   ? 'g' : 'l' );
406 #endif
407 		DRM_PROC_PRINT("\n");
408 #if 0
409 		for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
410 			pgd = pgd_offset(vma->vm_mm, i);
411 			pmd = pmd_offset(pgd, i);
412 			pte = pte_offset(pmd, i);
413 			if (pte_present(*pte)) {
414 				address = __pa(pte_page(*pte))
415 					+ (i & (PAGE_SIZE-1));
416 				DRM_PROC_PRINT("      0x%08lx -> 0x%08lx"
417 					       " %c%c%c%c%c\n",
418 					       i,
419 					       address,
420 					       pte_read(*pte)  ? 'r' : '-',
421 					       pte_write(*pte) ? 'w' : '-',
422 					       pte_exec(*pte)  ? 'x' : '-',
423 					       pte_dirty(*pte) ? 'd' : '-',
424 					       pte_young(*pte) ? 'a' : '-' );
425 			} else {
426 				DRM_PROC_PRINT("      0x%08lx\n", i);
427 			}
428 		}
429 #endif
430 	}
431 
432 	return len;
433 }
434 
drm_vma_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)435 static int drm_vma_info(char *buf, char **start, off_t offset, int len,
436 			int *eof, void *data)
437 {
438 	drm_device_t *dev = (drm_device_t *)data;
439 	int	     ret;
440 
441 	down(&dev->struct_sem);
442 	ret = _drm_vma_info(buf, start, offset, len, eof, data);
443 	up(&dev->struct_sem);
444 	return ret;
445 }
446 #endif
447 
448 
449 #if DRM_DMA_HISTOGRAM
_drm_histo_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)450 static int _drm_histo_info(char *buf, char **start, off_t offset, int len,
451 			   int *eof, void *data)
452 {
453 	drm_device_t	 *dev = (drm_device_t *)data;
454 	drm_device_dma_t *dma = dev->dma;
455 	int		 i;
456 	unsigned long	 slot_value = DRM_DMA_HISTOGRAM_INITIAL;
457 	unsigned long	 prev_value = 0;
458 	drm_buf_t	 *buffer;
459 
460 	if (offset > 0) return 0; /* no partial requests */
461 	len  = 0;
462 	*eof = 1;
463 
464 	DRM_PROC_PRINT("general statistics:\n");
465 	DRM_PROC_PRINT("total	 %10u\n", atomic_read(&dev->histo.total));
466 	DRM_PROC_PRINT("open	 %10u\n", atomic_read(&dev->total_open));
467 	DRM_PROC_PRINT("close	 %10u\n", atomic_read(&dev->total_close));
468 	DRM_PROC_PRINT("ioctl	 %10u\n", atomic_read(&dev->total_ioctl));
469 	DRM_PROC_PRINT("irq	 %10u\n", atomic_read(&dev->total_irq));
470 	DRM_PROC_PRINT("ctx	 %10u\n", atomic_read(&dev->total_ctx));
471 
472 	DRM_PROC_PRINT("\nlock statistics:\n");
473 	DRM_PROC_PRINT("locks	 %10u\n", atomic_read(&dev->total_locks));
474 	DRM_PROC_PRINT("unlocks	 %10u\n", atomic_read(&dev->total_unlocks));
475 	DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
476 	DRM_PROC_PRINT("sleeps	 %10u\n", atomic_read(&dev->total_sleeps));
477 
478 
479 	if (dma) {
480 		DRM_PROC_PRINT("\ndma statistics:\n");
481 		DRM_PROC_PRINT("prio	 %10u\n",
482 			       atomic_read(&dma->total_prio));
483 		DRM_PROC_PRINT("bytes	 %10u\n",
484 			       atomic_read(&dma->total_bytes));
485 		DRM_PROC_PRINT("dmas	 %10u\n",
486 			       atomic_read(&dma->total_dmas));
487 		DRM_PROC_PRINT("missed:\n");
488 		DRM_PROC_PRINT("  dma	 %10u\n",
489 			       atomic_read(&dma->total_missed_dma));
490 		DRM_PROC_PRINT("  lock	 %10u\n",
491 			       atomic_read(&dma->total_missed_lock));
492 		DRM_PROC_PRINT("  free	 %10u\n",
493 			       atomic_read(&dma->total_missed_free));
494 		DRM_PROC_PRINT("  sched	 %10u\n",
495 			       atomic_read(&dma->total_missed_sched));
496 		DRM_PROC_PRINT("tried	 %10u\n",
497 			       atomic_read(&dma->total_tried));
498 		DRM_PROC_PRINT("hit	 %10u\n",
499 			       atomic_read(&dma->total_hit));
500 		DRM_PROC_PRINT("lost	 %10u\n",
501 			       atomic_read(&dma->total_lost));
502 
503 		buffer = dma->next_buffer;
504 		if (buffer) {
505 			DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
506 		} else {
507 			DRM_PROC_PRINT("next_buffer    none\n");
508 		}
509 		buffer = dma->this_buffer;
510 		if (buffer) {
511 			DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
512 		} else {
513 			DRM_PROC_PRINT("this_buffer    none\n");
514 		}
515 	}
516 
517 
518 	DRM_PROC_PRINT("\nvalues:\n");
519 	if (dev->lock.hw_lock) {
520 		DRM_PROC_PRINT("lock	       0x%08x\n",
521 			       dev->lock.hw_lock->lock);
522 	} else {
523 		DRM_PROC_PRINT("lock		     none\n");
524 	}
525 	DRM_PROC_PRINT("context_flag   0x%08lx\n", dev->context_flag);
526 	DRM_PROC_PRINT("interrupt_flag 0x%08lx\n", dev->interrupt_flag);
527 	DRM_PROC_PRINT("dma_flag       0x%08lx\n", dev->dma_flag);
528 
529 	DRM_PROC_PRINT("queue_count    %10d\n",	 dev->queue_count);
530 	DRM_PROC_PRINT("last_context   %10d\n",	 dev->last_context);
531 	DRM_PROC_PRINT("last_switch    %10lu\n", dev->last_switch);
532 	DRM_PROC_PRINT("last_checked   %10d\n",	 dev->last_checked);
533 
534 
535 	DRM_PROC_PRINT("\n		       q2d	  d2c	     c2f"
536 		       "	q2c	   q2f	      dma	 sch"
537 		       "	ctx	  lacq	     lhld\n\n");
538 	for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
539 		DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
540 			       " %10u %10u %10u %10u %10u\n",
541 			       i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
542 			       i == DRM_DMA_HISTOGRAM_SLOTS - 1
543 			       ? prev_value : slot_value ,
544 
545 			       atomic_read(&dev->histo
546 					   .queued_to_dispatched[i]),
547 			       atomic_read(&dev->histo
548 					   .dispatched_to_completed[i]),
549 			       atomic_read(&dev->histo
550 					   .completed_to_freed[i]),
551 
552 			       atomic_read(&dev->histo
553 					   .queued_to_completed[i]),
554 			       atomic_read(&dev->histo
555 					   .queued_to_freed[i]),
556 			       atomic_read(&dev->histo.dma[i]),
557 			       atomic_read(&dev->histo.schedule[i]),
558 			       atomic_read(&dev->histo.ctx[i]),
559 			       atomic_read(&dev->histo.lacq[i]),
560 			       atomic_read(&dev->histo.lhld[i]));
561 		prev_value = slot_value;
562 		slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
563 	}
564 	return len;
565 }
566 
drm_histo_info(char * buf,char ** start,off_t offset,int len,int * eof,void * data)567 static int drm_histo_info(char *buf, char **start, off_t offset, int len,
568 			  int *eof, void *data)
569 {
570 	drm_device_t *dev = (drm_device_t *)data;
571 	int	     ret;
572 
573 	down(&dev->struct_sem);
574 	ret = _drm_histo_info(buf, start, offset, len, eof, data);
575 	up(&dev->struct_sem);
576 	return ret;
577 }
578 #endif
579