i915_gem_proc.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * Copyright © 2008 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. * IN THE SOFTWARE.
  22. *
  23. * Authors:
  24. * Eric Anholt <eric@anholt.net>
  25. * Keith Packard <keithp@keithp.com>
  26. *
  27. */
  28. #include "drmP.h"
  29. #include "drm.h"
  30. #include "i915_drm.h"
  31. #include "i915_drv.h"
  32. static int i915_gem_active_info(char *buf, char **start, off_t offset,
  33. int request, int *eof, void *data)
  34. {
  35. struct drm_minor *minor = (struct drm_minor *) data;
  36. struct drm_device *dev = minor->dev;
  37. drm_i915_private_t *dev_priv = dev->dev_private;
  38. struct drm_i915_gem_object *obj_priv;
  39. int len = 0;
  40. if (offset > DRM_PROC_LIMIT) {
  41. *eof = 1;
  42. return 0;
  43. }
  44. *start = &buf[offset];
  45. *eof = 0;
  46. DRM_PROC_PRINT("Active:\n");
  47. list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
  48. list)
  49. {
  50. struct drm_gem_object *obj = obj_priv->obj;
  51. if (obj->name) {
  52. DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
  53. obj, obj->name,
  54. obj->read_domains, obj->write_domain,
  55. obj_priv->last_rendering_seqno);
  56. } else {
  57. DRM_PROC_PRINT(" %p: %08x %08x %d\n",
  58. obj,
  59. obj->read_domains, obj->write_domain,
  60. obj_priv->last_rendering_seqno);
  61. }
  62. }
  63. if (len > request + offset)
  64. return request;
  65. *eof = 1;
  66. return len - offset;
  67. }
  68. static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
  69. int request, int *eof, void *data)
  70. {
  71. struct drm_minor *minor = (struct drm_minor *) data;
  72. struct drm_device *dev = minor->dev;
  73. drm_i915_private_t *dev_priv = dev->dev_private;
  74. struct drm_i915_gem_object *obj_priv;
  75. int len = 0;
  76. if (offset > DRM_PROC_LIMIT) {
  77. *eof = 1;
  78. return 0;
  79. }
  80. *start = &buf[offset];
  81. *eof = 0;
  82. DRM_PROC_PRINT("Flushing:\n");
  83. list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
  84. list)
  85. {
  86. struct drm_gem_object *obj = obj_priv->obj;
  87. if (obj->name) {
  88. DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
  89. obj, obj->name,
  90. obj->read_domains, obj->write_domain,
  91. obj_priv->last_rendering_seqno);
  92. } else {
  93. DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj,
  94. obj->read_domains, obj->write_domain,
  95. obj_priv->last_rendering_seqno);
  96. }
  97. }
  98. if (len > request + offset)
  99. return request;
  100. *eof = 1;
  101. return len - offset;
  102. }
  103. static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
  104. int request, int *eof, void *data)
  105. {
  106. struct drm_minor *minor = (struct drm_minor *) data;
  107. struct drm_device *dev = minor->dev;
  108. drm_i915_private_t *dev_priv = dev->dev_private;
  109. struct drm_i915_gem_object *obj_priv;
  110. int len = 0;
  111. if (offset > DRM_PROC_LIMIT) {
  112. *eof = 1;
  113. return 0;
  114. }
  115. *start = &buf[offset];
  116. *eof = 0;
  117. DRM_PROC_PRINT("Inactive:\n");
  118. list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
  119. list)
  120. {
  121. struct drm_gem_object *obj = obj_priv->obj;
  122. if (obj->name) {
  123. DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
  124. obj, obj->name,
  125. obj->read_domains, obj->write_domain,
  126. obj_priv->last_rendering_seqno);
  127. } else {
  128. DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj,
  129. obj->read_domains, obj->write_domain,
  130. obj_priv->last_rendering_seqno);
  131. }
  132. }
  133. if (len > request + offset)
  134. return request;
  135. *eof = 1;
  136. return len - offset;
  137. }
  138. static int i915_gem_request_info(char *buf, char **start, off_t offset,
  139. int request, int *eof, void *data)
  140. {
  141. struct drm_minor *minor = (struct drm_minor *) data;
  142. struct drm_device *dev = minor->dev;
  143. drm_i915_private_t *dev_priv = dev->dev_private;
  144. struct drm_i915_gem_request *gem_request;
  145. int len = 0;
  146. if (offset > DRM_PROC_LIMIT) {
  147. *eof = 1;
  148. return 0;
  149. }
  150. *start = &buf[offset];
  151. *eof = 0;
  152. DRM_PROC_PRINT("Request:\n");
  153. list_for_each_entry(gem_request, &dev_priv->mm.request_list,
  154. list)
  155. {
  156. DRM_PROC_PRINT(" %d @ %d\n",
  157. gem_request->seqno,
  158. (int) (jiffies - gem_request->emitted_jiffies));
  159. }
  160. if (len > request + offset)
  161. return request;
  162. *eof = 1;
  163. return len - offset;
  164. }
  165. static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
  166. int request, int *eof, void *data)
  167. {
  168. struct drm_minor *minor = (struct drm_minor *) data;
  169. struct drm_device *dev = minor->dev;
  170. drm_i915_private_t *dev_priv = dev->dev_private;
  171. int len = 0;
  172. if (offset > DRM_PROC_LIMIT) {
  173. *eof = 1;
  174. return 0;
  175. }
  176. *start = &buf[offset];
  177. *eof = 0;
  178. if (dev_priv->hw_status_page != NULL) {
  179. DRM_PROC_PRINT("Current sequence: %d\n",
  180. i915_get_gem_seqno(dev));
  181. } else {
  182. DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
  183. }
  184. DRM_PROC_PRINT("Waiter sequence: %d\n",
  185. dev_priv->mm.waiting_gem_seqno);
  186. DRM_PROC_PRINT("IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
  187. if (len > request + offset)
  188. return request;
  189. *eof = 1;
  190. return len - offset;
  191. }
  192. static int i915_interrupt_info(char *buf, char **start, off_t offset,
  193. int request, int *eof, void *data)
  194. {
  195. struct drm_minor *minor = (struct drm_minor *) data;
  196. struct drm_device *dev = minor->dev;
  197. drm_i915_private_t *dev_priv = dev->dev_private;
  198. int len = 0;
  199. if (offset > DRM_PROC_LIMIT) {
  200. *eof = 1;
  201. return 0;
  202. }
  203. *start = &buf[offset];
  204. *eof = 0;
  205. DRM_PROC_PRINT("Interrupt enable: %08x\n",
  206. I915_READ(IER));
  207. DRM_PROC_PRINT("Interrupt identity: %08x\n",
  208. I915_READ(IIR));
  209. DRM_PROC_PRINT("Interrupt mask: %08x\n",
  210. I915_READ(IMR));
  211. DRM_PROC_PRINT("Pipe A stat: %08x\n",
  212. I915_READ(PIPEASTAT));
  213. DRM_PROC_PRINT("Pipe B stat: %08x\n",
  214. I915_READ(PIPEBSTAT));
  215. DRM_PROC_PRINT("Interrupts received: %d\n",
  216. atomic_read(&dev_priv->irq_received));
  217. if (dev_priv->hw_status_page != NULL) {
  218. DRM_PROC_PRINT("Current sequence: %d\n",
  219. i915_get_gem_seqno(dev));
  220. } else {
  221. DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
  222. }
  223. DRM_PROC_PRINT("Waiter sequence: %d\n",
  224. dev_priv->mm.waiting_gem_seqno);
  225. DRM_PROC_PRINT("IRQ sequence: %d\n",
  226. dev_priv->mm.irq_gem_seqno);
  227. if (len > request + offset)
  228. return request;
  229. *eof = 1;
  230. return len - offset;
  231. }
  232. static int i915_hws_info(char *buf, char **start, off_t offset,
  233. int request, int *eof, void *data)
  234. {
  235. struct drm_minor *minor = (struct drm_minor *) data;
  236. struct drm_device *dev = minor->dev;
  237. drm_i915_private_t *dev_priv = dev->dev_private;
  238. int len = 0, i;
  239. volatile u32 *hws;
  240. if (offset > DRM_PROC_LIMIT) {
  241. *eof = 1;
  242. return 0;
  243. }
  244. hws = (volatile u32 *)dev_priv->hw_status_page;
  245. if (hws == NULL) {
  246. *eof = 1;
  247. return 0;
  248. }
  249. *start = &buf[offset];
  250. *eof = 0;
  251. for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
  252. DRM_PROC_PRINT("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
  253. i * 4,
  254. hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
  255. }
  256. if (len > request + offset)
  257. return request;
  258. *eof = 1;
  259. return len - offset;
  260. }
  261. static struct drm_proc_list {
  262. /** file name */
  263. const char *name;
  264. /** proc callback*/
  265. int (*f) (char *, char **, off_t, int, int *, void *);
  266. } i915_gem_proc_list[] = {
  267. {"i915_gem_active", i915_gem_active_info},
  268. {"i915_gem_flushing", i915_gem_flushing_info},
  269. {"i915_gem_inactive", i915_gem_inactive_info},
  270. {"i915_gem_request", i915_gem_request_info},
  271. {"i915_gem_seqno", i915_gem_seqno_info},
  272. {"i915_gem_interrupt", i915_interrupt_info},
  273. {"i915_gem_hws", i915_hws_info},
  274. };
  275. #define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
  276. int i915_gem_proc_init(struct drm_minor *minor)
  277. {
  278. struct proc_dir_entry *ent;
  279. int i, j;
  280. for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
  281. ent = create_proc_entry(i915_gem_proc_list[i].name,
  282. S_IFREG | S_IRUGO, minor->dev_root);
  283. if (!ent) {
  284. DRM_ERROR("Cannot create /proc/dri/.../%s\n",
  285. i915_gem_proc_list[i].name);
  286. for (j = 0; j < i; j++)
  287. remove_proc_entry(i915_gem_proc_list[i].name,
  288. minor->dev_root);
  289. return -1;
  290. }
  291. ent->read_proc = i915_gem_proc_list[i].f;
  292. ent->data = minor;
  293. }
  294. return 0;
  295. }
  296. void i915_gem_proc_cleanup(struct drm_minor *minor)
  297. {
  298. int i;
  299. if (!minor->dev_root)
  300. return;
  301. for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
  302. remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
  303. }