blob: f554d5781c592fd36acc84dbc562b353c60daecb [file] [log] [blame]
Chris Wilson9eb4de12010-02-12 13:28:40 +00001/*
2 * Copyright © 2007 Intel Corporation
3 * Copyright © 2009 Intel Corporation
4 * Copyright © 2010 Intel Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 *
25 * Authors:
26 * Eric Anholt <eric@anholt.net>
27 * Carl Worth <cworth@cworth.org>
28 * Chris Wilson <chris@chris-wilson.co.uk>
29 *
30 */
31
32/** @file intel_decode.c
33 * This file contains code to print out batchbuffer contents in a
34 * human-readable format.
35 *
36 * The current version only supports i915 packets, and only pretty-prints a
37 * subset of them. The intention is for it to make just a best attempt to
38 * decode, but never crash in the process.
39 */
40
41#define _GNU_SOURCE
42#include <stdio.h>
43#include <stdlib.h>
44#include <stdarg.h>
45#include <string.h>
Chris Wilsona3a78632010-12-01 21:51:59 +000046#include <unistd.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000047#include <inttypes.h>
48#include <errno.h>
49#include <sys/stat.h>
50#include <err.h>
Imre Deak5efd3d32012-10-10 16:04:39 +030051#include <assert.h>
Daniel Vetter7ee9f162012-01-09 23:38:17 +010052#include <intel_bufmgr.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000053
Chris Wilson9eb4de12010-02-12 13:28:40 +000054#include "intel_chipset.h"
55#include "intel_gpu_tools.h"
56#include "instdone.h"
57
58static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -070059print_instdone(uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000060{
Ben Widawsky155aa1e2013-04-22 11:07:35 -070061 int i;
62 static int once;
Chris Wilson95374222010-04-08 11:56:57 +010063
Ben Widawsky155aa1e2013-04-22 11:07:35 -070064 if (!once) {
65 init_instdone_definitions(devid);
66 once = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +000067 }
68
Ben Widawsky155aa1e2013-04-22 11:07:35 -070069 for (i = 0; i < num_instdone_bits; i++) {
70 int busy = 0;
71
72 if (instdone_bits[i].reg == INST_DONE_1) {
73 if (!(instdone1 & instdone_bits[i].bit))
74 busy = 1;
75 } else {
76 if (!(instdone & instdone_bits[i].bit))
77 busy = 1;
78 }
79
80 if (busy)
81 printf(" busy: %s\n", instdone_bits[i].name);
82 }
Chris Wilson9eb4de12010-02-12 13:28:40 +000083}
84
85static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +000086print_i830_pgtbl_err(unsigned int reg)
87{
88 const char *str;
89
90 switch((reg >> 3) & 0xf) {
91 case 0x1: str = "Overlay TLB"; break;
92 case 0x2: str = "Display A TLB"; break;
93 case 0x3: str = "Host TLB"; break;
94 case 0x4: str = "Render TLB"; break;
95 case 0x5: str = "Display C TLB"; break;
96 case 0x6: str = "Mapping TLB"; break;
97 case 0x7: str = "Command Stream TLB"; break;
98 case 0x8: str = "Vertex Buffer TLB"; break;
99 case 0x9: str = "Display B TLB"; break;
100 case 0xa: str = "Reserved System Memory"; break;
101 case 0xb: str = "Compressor TLB"; break;
102 case 0xc: str = "Binner TLB"; break;
103 default: str = "unknown"; break;
104 }
105
106 if (str)
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700107 printf(" source = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000108
109 switch(reg & 0x7) {
110 case 0x0: str = "Invalid GTT"; break;
111 case 0x1: str = "Invalid GTT PTE"; break;
112 case 0x2: str = "Invalid Memory"; break;
113 case 0x3: str = "Invalid TLB miss"; break;
114 case 0x4: str = "Invalid PTE data"; break;
115 case 0x5: str = "Invalid LocalMemory not present"; break;
116 case 0x6: str = "Invalid Tiling"; break;
117 case 0x7: str = "Host to CAM"; break;
118 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700119 printf(" error = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000120}
121
122static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100123print_i915_pgtbl_err(unsigned int reg)
124{
125 if (reg & (1 << 29))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700126 printf(" Cursor A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100127 if (reg & (1 << 28))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700128 printf(" Cursor B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100129 if (reg & (1 << 27))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700130 printf(" MT: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100131 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700132 printf(" MT: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100133 if (reg & (1 << 25))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700134 printf(" LC: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100135 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700136 printf(" LC: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100137 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700138 printf(" BIN VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100139 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700140 printf(" BIN Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100141 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700142 printf(" CS VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100143 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700144 printf(" CS Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100145 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700146 printf(" CS: Invalid GTT\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100147 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700148 printf(" Overlay: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100149 if (reg & (1 << 16))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700150 printf(" Overlay: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100151 if (reg & (1 << 14))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700152 printf(" Display C: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100153 if (reg & (1 << 12))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700154 printf(" Display C: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100155 if (reg & (1 << 10))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700156 printf(" Display B: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100157 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700158 printf(" Display B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100159 if (reg & (1 << 6))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700160 printf(" Display A: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100161 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700162 printf(" Display A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100163 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700164 printf(" Host Invalid PTE data\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100165 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700166 printf(" Host Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100167}
168
169static void
Chris Wilson89343952010-10-22 11:33:08 +0100170print_i965_pgtbl_err(unsigned int reg)
171{
172 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700173 printf(" Invalid Sampler Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100174 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700175 printf(" Invalid Render Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100176 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700177 printf(" Invalid Instruction/State Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100178 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700179 printf(" There is no ROC, this cannot occur!\n");
Chris Wilson89343952010-10-22 11:33:08 +0100180 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700181 printf(" Invalid GTT entry during Vertex Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100182 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700183 printf(" Invalid GTT entry during Command Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100184 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700185 printf(" Invalid GTT entry during CS\n");
Chris Wilson89343952010-10-22 11:33:08 +0100186 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700187 printf(" Invalid GTT entry during Cursor Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100188 if (reg & (1 << 17))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700189 printf(" Invalid GTT entry during Overlay Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100190 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700191 printf(" Invalid GTT entry during Display B Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100192 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700193 printf(" Invalid GTT entry during Display A Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100194 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700195 printf(" Valid PTE references illegal memory\n");
Chris Wilson89343952010-10-22 11:33:08 +0100196 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700197 printf(" Invalid GTT entry during fetch for host\n");
Chris Wilson89343952010-10-22 11:33:08 +0100198}
199
200static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000201print_pgtbl_err(unsigned int reg, unsigned int devid)
202{
203 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100204 return print_i965_pgtbl_err(reg);
Chris Wilson41570d92011-02-14 15:56:14 +0000205 } else if (IS_GEN3(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100206 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000207 } else {
208 return print_i830_pgtbl_err(reg);
209 }
210}
211
212static void
Daniel Vetterd5109532011-10-21 19:06:08 +0200213print_snb_fence(unsigned int devid, uint64_t fence)
214{
215 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700216 fence & 1 ? "" : "in",
217 fence & (1<<1) ? 'y' : 'x',
218 (int)(((fence>>32)&0xfff)+1)*128,
219 (uint32_t)fence & 0xfffff000,
220 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
Daniel Vetterd5109532011-10-21 19:06:08 +0200221}
222
223static void
224print_i965_fence(unsigned int devid, uint64_t fence)
225{
226 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700227 fence & 1 ? "" : "in",
228 fence & (1<<1) ? 'y' : 'x',
229 (int)(((fence>>2)&0x1ff)+1)*128,
230 (uint32_t)fence & 0xfffff000,
231 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
Daniel Vetterd5109532011-10-21 19:06:08 +0200232}
233
234static void
Daniel Vettercf5db112011-03-14 11:20:17 +0100235print_i915_fence(unsigned int devid, uint64_t fence)
236{
237 unsigned tile_width;
238 if ((fence & 12) && !IS_915(devid))
239 tile_width = 128;
240 else
241 tile_width = 512;
242
243 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700244 fence & 1 ? "" : "in",
245 fence & 12 ? 'y' : 'x',
246 (1<<((fence>>4)&0xf))*tile_width,
247 (uint32_t)fence & 0xff00000,
248 1<<(20 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100249}
250
251static void
252print_i830_fence(unsigned int devid, uint64_t fence)
253{
254 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700255 fence & 1 ? "" : "in",
256 fence & 12 ? 'y' : 'x',
257 (1<<((fence>>4)&0xf))*128,
258 (uint32_t)fence & 0x7f80000,
259 1<<(19 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100260}
261
262static void
263print_fence(unsigned int devid, uint64_t fence)
264{
Daniel Vetterd5109532011-10-21 19:06:08 +0200265 if (IS_GEN6(devid) || IS_GEN7(devid)) {
266 return print_snb_fence(devid, fence);
267 } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
268 return print_i965_fence(devid, fence);
Daniel Vettercf5db112011-03-14 11:20:17 +0100269 } else if (IS_GEN3(devid)) {
270 return print_i915_fence(devid, fence);
271 } else {
272 return print_i830_fence(devid, fence);
273 }
274}
275
276static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700277read_data_file(FILE *file)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000278{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700279 struct drm_intel_decode *decode_ctx = NULL;
280 uint32_t devid = PCI_CHIP_I855_GM;
281 uint32_t *data = NULL;
282 long long unsigned fence;
283 int data_size = 0, count = 0, line_number = 0, matched;
284 char *line = NULL;
285 size_t line_size;
286 uint32_t offset, value;
287 uint32_t gtt_offset = 0, new_gtt_offset;
288 const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
289 char *ring_name = NULL;
290 int is_batch = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000291
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700292 while (getline(&line, &line_size, file) > 0) {
293 char *dashes;
294 line_number++;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000295
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700296 dashes = strstr(line, "---");
297 if (dashes) {
298 char *new_ring_name = malloc(dashes - line);
299 strncpy(new_ring_name, line, dashes - line);
300 new_ring_name[dashes - line - 1] = '\0';
Daniel Vetter73c21042011-10-11 13:14:02 +0200301
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700302 matched = sscanf(dashes, "--- gtt_offset = 0x%08x\n",
303 &new_gtt_offset);
304 if (matched == 1) {
305 if (count) {
306 printf("%s (%s) at 0x%08x:\n",
307 buffer_type[is_batch],
308 ring_name,
309 gtt_offset);
310 drm_intel_decode_set_batch_pointer(decode_ctx,
311 data, gtt_offset,
312 count);
313 drm_intel_decode(decode_ctx);
314 count = 0;
315 }
316 gtt_offset = new_gtt_offset;
317 is_batch = 1;
318 free(ring_name);
319 ring_name = new_ring_name;
320 continue;
321 }
322
323 matched = sscanf(dashes, "--- ringbuffer = 0x%08x\n",
324 &new_gtt_offset);
325 if (matched == 1) {
326 if (count) {
327 printf("%s (%s) at 0x%08x:\n",
328 buffer_type[is_batch],
329 ring_name,
330 gtt_offset);
331 drm_intel_decode_set_batch_pointer(decode_ctx,
332 data, gtt_offset,
333 count);
334 drm_intel_decode(decode_ctx);
335 count = 0;
336 }
337 gtt_offset = new_gtt_offset;
338 is_batch = 0;
339 free(ring_name);
340 ring_name = new_ring_name;
341 continue;
342 }
343 }
344
345 matched = sscanf(line, "%08x : %08x", &offset, &value);
346 if (matched != 2) {
347 unsigned int reg;
348
349 /* display reg section is after the ringbuffers, don't mix them */
Chris Wilson98eb5a52011-01-09 13:26:50 +0000350 if (count) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200351 printf("%s (%s) at 0x%08x:\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700352 buffer_type[is_batch],
353 ring_name,
354 gtt_offset);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100355 drm_intel_decode_set_batch_pointer(decode_ctx,
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700356 data, gtt_offset,
357 count);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100358 drm_intel_decode(decode_ctx);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000359 count = 0;
360 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000361
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700362 printf("%s", line);
363
364 matched = sscanf(line, "PCI ID: 0x%04x\n", &reg);
365 if (matched == 0)
366 matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
367 if (matched == 0) {
368 const char *pci_id_start = strstr(line, "PCI ID");
369 if (pci_id_start)
370 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", &reg);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000371 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700372 if (matched == 1) {
373 devid = reg;
374 printf("Detected GEN%i chipset\n",
375 intel_gen(devid));
376
377 decode_ctx = drm_intel_decode_context_alloc(devid);
378 }
379
380 matched = sscanf(line, " ACTHD: 0x%08x\n", &reg);
381 if (matched == 1)
382 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
383
384 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", &reg);
385 if (matched == 1 && reg)
386 print_pgtbl_err(reg, devid);
387
388 matched = sscanf(line, " INSTDONE: 0x%08x\n", &reg);
389 if (matched == 1)
390 print_instdone(devid, reg, -1);
391
392 matched = sscanf(line, " INSTDONE1: 0x%08x\n", &reg);
393 if (matched == 1)
394 print_instdone(devid, -1, reg);
395
396 matched = sscanf(line, " fence[%i] = %Lx\n", &reg, &fence);
397 if (matched == 2)
398 print_fence(devid, fence);
399
Chris Wilson98eb5a52011-01-09 13:26:50 +0000400 continue;
401 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700402
403 count++;
404
405 if (count > data_size) {
406 data_size = data_size ? data_size * 2 : 1024;
407 data = realloc(data, data_size * sizeof (uint32_t));
408 if (data == NULL) {
409 fprintf(stderr, "Out of memory.\n");
410 exit(1);
411 }
412 }
413
414 data[count-1] = value;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000415 }
416
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700417 if (count) {
418 printf("%s (%s) at 0x%08x:\n",
419 buffer_type[is_batch],
420 ring_name,
421 gtt_offset);
422 drm_intel_decode_set_batch_pointer(decode_ctx,
423 data, gtt_offset,
424 count);
425 drm_intel_decode(decode_ctx);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000426 }
427
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700428 free(data);
429 free(line);
430 free(ring_name);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000431}
432
433int
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700434main(int argc, char *argv[])
Chris Wilson9eb4de12010-02-12 13:28:40 +0000435{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700436 FILE *file;
437 const char *path;
438 char *filename = NULL;
439 struct stat st;
440 int error;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000441
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700442 if (argc > 2) {
443 fprintf(stderr,
444 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
445 "Usage:\n"
446 "\t%s [<file>]\n"
447 "\n"
448 "With no arguments, debugfs-dri-directory is probed for in "
449 "/debug and \n"
450 "/sys/kernel/debug. Otherwise, it may be "
451 "specified. If a file is given,\n"
452 "it is parsed as an GPU dump in the format of "
453 "/debug/dri/0/i915_error_state.\n",
454 argv[0]);
455 return 1;
456 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000457
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700458 if (argc == 1) {
459 if (isatty(0)) {
460 path = "/debug/dri";
461 error = stat(path, &st);
462 if (error != 0) {
463 path = "/sys/kernel/debug/dri";
464 error = stat(path, &st);
465 if (error != 0) {
466 errx(1,
467 "Couldn't find i915 debugfs directory.\n\n"
468 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
469 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
470 }
471 }
472 } else {
473 read_data_file(stdin);
474 exit(0);
Chris Wilsona3a78632010-12-01 21:51:59 +0000475 }
Chris Wilsona3a78632010-12-01 21:51:59 +0000476 } else {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700477 path = argv[1];
478 error = stat(path, &st);
479 if (error != 0) {
480 fprintf(stderr, "Error opening %s: %s\n",
481 path, strerror(errno));
482 exit(1);
483 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000484 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000485
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700486 if (S_ISDIR(st.st_mode)) {
487 int ret;
Imre Deak5efd3d32012-10-10 16:04:39 +0300488
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700489 ret = asprintf(&filename, "%s/i915_error_state", path);
Imre Deak5efd3d32012-10-10 16:04:39 +0300490 assert(ret > 0);
Chris Wilson68a95f02011-01-25 16:34:08 +0000491 file = fopen(filename, "r");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700492 if (!file) {
493 int minor;
494 for (minor = 0; minor < 64; minor++) {
495 free(filename);
496 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
497 assert(ret > 0);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000498
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700499 file = fopen(filename, "r");
500 if (file)
501 break;
502 }
503 }
504 if (!file) {
505 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
506 path);
507 exit (1);
508 }
509 } else {
510 file = fopen(path, "r");
511 if (!file) {
512 fprintf(stderr, "Failed to open %s: %s\n",
513 path, strerror(errno));
514 exit (1);
515 }
516 }
Chris Wilson68a95f02011-01-25 16:34:08 +0000517
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700518 read_data_file(file);
519 fclose(file);
Chris Wilsona3a78632010-12-01 21:51:59 +0000520
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700521 if (filename != path)
522 free(filename);
523
524 return 0;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000525}
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700526
527/* vim: set ts=8 sw=8 tw=0 noet :*/