blob: ca03c8353c2cb4620746f6fccf1418e8dcf46dbf [file] [log] [blame]
Chris Wilson9eb4de12010-02-12 13:28:40 +00001/* -*- c-basic-offset: 4 -*- */
2/*
3 * Copyright © 2007 Intel Corporation
4 * Copyright © 2009 Intel Corporation
5 * Copyright © 2010 Intel Corporation
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 *
26 * Authors:
27 * Eric Anholt <eric@anholt.net>
28 * Carl Worth <cworth@cworth.org>
29 * Chris Wilson <chris@chris-wilson.co.uk>
30 *
31 */
32
33/** @file intel_decode.c
34 * This file contains code to print out batchbuffer contents in a
35 * human-readable format.
36 *
37 * The current version only supports i915 packets, and only pretty-prints a
38 * subset of them. The intention is for it to make just a best attempt to
39 * decode, but never crash in the process.
40 */
41
42#define _GNU_SOURCE
43#include <stdio.h>
44#include <stdlib.h>
45#include <stdarg.h>
46#include <string.h>
Chris Wilsona3a78632010-12-01 21:51:59 +000047#include <unistd.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000048#include <inttypes.h>
49#include <errno.h>
50#include <sys/stat.h>
51#include <err.h>
Imre Deak5efd3d32012-10-10 16:04:39 +030052#include <assert.h>
Daniel Vetter7ee9f162012-01-09 23:38:17 +010053#include <intel_bufmgr.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000054
Chris Wilson9eb4de12010-02-12 13:28:40 +000055#include "intel_chipset.h"
56#include "intel_gpu_tools.h"
57#include "instdone.h"
58
59static void
Chris Wilson95374222010-04-08 11:56:57 +010060print_instdone (uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000061{
62 int i;
Chris Wilson95374222010-04-08 11:56:57 +010063 static int once;
64
65 if (!once) {
66 init_instdone_definitions(devid);
67 once = 1;
68 }
Chris Wilson9eb4de12010-02-12 13:28:40 +000069
70 for (i = 0; i < num_instdone_bits; i++) {
71 int busy = 0;
72
73 if (instdone_bits[i].reg == INST_DONE_1) {
74 if (!(instdone1 & instdone_bits[i].bit))
75 busy = 1;
76 } else {
77 if (!(instdone & instdone_bits[i].bit))
78 busy = 1;
79 }
80
81 if (busy)
82 printf(" busy: %s\n", instdone_bits[i].name);
83 }
84}
85
86static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +000087print_i830_pgtbl_err(unsigned int reg)
88{
89 const char *str;
90
91 switch((reg >> 3) & 0xf) {
92 case 0x1: str = "Overlay TLB"; break;
93 case 0x2: str = "Display A TLB"; break;
94 case 0x3: str = "Host TLB"; break;
95 case 0x4: str = "Render TLB"; break;
96 case 0x5: str = "Display C TLB"; break;
97 case 0x6: str = "Mapping TLB"; break;
98 case 0x7: str = "Command Stream TLB"; break;
99 case 0x8: str = "Vertex Buffer TLB"; break;
100 case 0x9: str = "Display B TLB"; break;
101 case 0xa: str = "Reserved System Memory"; break;
102 case 0xb: str = "Compressor TLB"; break;
103 case 0xc: str = "Binner TLB"; break;
104 default: str = "unknown"; break;
105 }
106
107 if (str)
108 printf (" source = %s\n", str);
109
110 switch(reg & 0x7) {
111 case 0x0: str = "Invalid GTT"; break;
112 case 0x1: str = "Invalid GTT PTE"; break;
113 case 0x2: str = "Invalid Memory"; break;
114 case 0x3: str = "Invalid TLB miss"; break;
115 case 0x4: str = "Invalid PTE data"; break;
116 case 0x5: str = "Invalid LocalMemory not present"; break;
117 case 0x6: str = "Invalid Tiling"; break;
118 case 0x7: str = "Host to CAM"; break;
119 }
120 printf (" error = %s\n", str);
121}
122
123static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100124print_i915_pgtbl_err(unsigned int reg)
125{
126 if (reg & (1 << 29))
127 printf (" Cursor A: Invalid GTT PTE\n");
128 if (reg & (1 << 28))
129 printf (" Cursor B: Invalid GTT PTE\n");
130 if (reg & (1 << 27))
131 printf (" MT: Invalid tiling\n");
132 if (reg & (1 << 26))
133 printf (" MT: Invalid GTT PTE\n");
134 if (reg & (1 << 25))
135 printf (" LC: Invalid tiling\n");
136 if (reg & (1 << 24))
137 printf (" LC: Invalid GTT PTE\n");
138 if (reg & (1 << 23))
139 printf (" BIN VertexData: Invalid GTT PTE\n");
140 if (reg & (1 << 22))
141 printf (" BIN Instruction: Invalid GTT PTE\n");
142 if (reg & (1 << 21))
143 printf (" CS VertexData: Invalid GTT PTE\n");
144 if (reg & (1 << 20))
145 printf (" CS Instruction: Invalid GTT PTE\n");
146 if (reg & (1 << 19))
147 printf (" CS: Invalid GTT\n");
148 if (reg & (1 << 18))
149 printf (" Overlay: Invalid tiling\n");
150 if (reg & (1 << 16))
151 printf (" Overlay: Invalid GTT PTE\n");
152 if (reg & (1 << 14))
153 printf (" Display C: Invalid tiling\n");
154 if (reg & (1 << 12))
155 printf (" Display C: Invalid GTT PTE\n");
156 if (reg & (1 << 10))
157 printf (" Display B: Invalid tiling\n");
158 if (reg & (1 << 8))
159 printf (" Display B: Invalid GTT PTE\n");
160 if (reg & (1 << 6))
161 printf (" Display A: Invalid tiling\n");
162 if (reg & (1 << 4))
163 printf (" Display A: Invalid GTT PTE\n");
164 if (reg & (1 << 1))
165 printf (" Host Invalid PTE data\n");
166 if (reg & (1 << 0))
167 printf (" Host Invalid GTT PTE\n");
168}
169
170static void
Chris Wilson89343952010-10-22 11:33:08 +0100171print_i965_pgtbl_err(unsigned int reg)
172{
173 if (reg & (1 << 26))
174 printf (" Invalid Sampler Cache GTT entry\n");
175 if (reg & (1 << 24))
176 printf (" Invalid Render Cache GTT entry\n");
177 if (reg & (1 << 23))
178 printf (" Invalid Instruction/State Cache GTT entry\n");
179 if (reg & (1 << 22))
180 printf (" There is no ROC, this cannot occur!\n");
181 if (reg & (1 << 21))
182 printf (" Invalid GTT entry during Vertex Fetch\n");
183 if (reg & (1 << 20))
184 printf (" Invalid GTT entry during Command Fetch\n");
185 if (reg & (1 << 19))
186 printf (" Invalid GTT entry during CS\n");
187 if (reg & (1 << 18))
188 printf (" Invalid GTT entry during Cursor Fetch\n");
189 if (reg & (1 << 17))
190 printf (" Invalid GTT entry during Overlay Fetch\n");
191 if (reg & (1 << 8))
192 printf (" Invalid GTT entry during Display B Fetch\n");
193 if (reg & (1 << 4))
194 printf (" Invalid GTT entry during Display A Fetch\n");
195 if (reg & (1 << 1))
196 printf (" Valid PTE references illegal memory\n");
197 if (reg & (1 << 0))
198 printf (" Invalid GTT entry during fetch for host\n");
199}
200
201static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000202print_pgtbl_err(unsigned int reg, unsigned int devid)
203{
204 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100205 return print_i965_pgtbl_err(reg);
Chris Wilson41570d92011-02-14 15:56:14 +0000206 } else if (IS_GEN3(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100207 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000208 } else {
209 return print_i830_pgtbl_err(reg);
210 }
211}
212
213static void
Daniel Vetterd5109532011-10-21 19:06:08 +0200214print_snb_fence(unsigned int devid, uint64_t fence)
215{
216 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
217 fence & 1 ? "" : "in",
218 fence & (1<<1) ? 'y' : 'x',
219 (int)(((fence>>32)&0xfff)+1)*128,
220 (uint32_t)fence & 0xfffff000,
221 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
222}
223
224static void
225print_i965_fence(unsigned int devid, uint64_t fence)
226{
227 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
228 fence & 1 ? "" : "in",
229 fence & (1<<1) ? 'y' : 'x',
230 (int)(((fence>>2)&0x1ff)+1)*128,
231 (uint32_t)fence & 0xfffff000,
232 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
233}
234
235static void
Daniel Vettercf5db112011-03-14 11:20:17 +0100236print_i915_fence(unsigned int devid, uint64_t fence)
237{
238 unsigned tile_width;
239 if ((fence & 12) && !IS_915(devid))
240 tile_width = 128;
241 else
242 tile_width = 512;
243
244 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
245 fence & 1 ? "" : "in",
246 fence & 12 ? 'y' : 'x',
247 (1<<((fence>>4)&0xf))*tile_width,
Chris Wilsonbf6c4802012-03-19 14:24:22 +0000248 (uint32_t)fence & 0xff00000,
Daniel Vettercf5db112011-03-14 11:20:17 +0100249 1<<(20 + ((fence>>8)&0xf)));
250}
251
252static void
253print_i830_fence(unsigned int devid, uint64_t fence)
254{
255 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
256 fence & 1 ? "" : "in",
257 fence & 12 ? 'y' : 'x',
258 (1<<((fence>>4)&0xf))*128,
259 (uint32_t)fence & 0x7f80000,
260 1<<(19 + ((fence>>8)&0xf)));
261}
262
263static void
264print_fence(unsigned int devid, uint64_t fence)
265{
Daniel Vetterd5109532011-10-21 19:06:08 +0200266 if (IS_GEN6(devid) || IS_GEN7(devid)) {
267 return print_snb_fence(devid, fence);
268 } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
269 return print_i965_fence(devid, fence);
Daniel Vettercf5db112011-03-14 11:20:17 +0100270 } else if (IS_GEN3(devid)) {
271 return print_i915_fence(devid, fence);
272 } else {
273 return print_i830_fence(devid, fence);
274 }
275}
276
277static void
Chris Wilsona3a78632010-12-01 21:51:59 +0000278read_data_file (FILE *file)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000279{
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100280 struct drm_intel_decode *decode_ctx = NULL;
281 uint32_t devid = PCI_CHIP_I855_GM;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000282 uint32_t *data = NULL;
Daniel Vettercf5db112011-03-14 11:20:17 +0100283 long long unsigned fence;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000284 int data_size = 0, count = 0, line_number = 0, matched;
285 char *line = NULL;
286 size_t line_size;
287 uint32_t offset, value;
288 uint32_t gtt_offset = 0, new_gtt_offset;
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100289 const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
Daniel Vetter73c21042011-10-11 13:14:02 +0200290 char *ring_name = NULL;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000291 int is_batch = 1;
292
Chris Wilson9eb4de12010-02-12 13:28:40 +0000293 while (getline (&line, &line_size, file) > 0) {
Chris Wilson98eb5a52011-01-09 13:26:50 +0000294 char *dashes;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000295 line_number++;
296
Chris Wilson98eb5a52011-01-09 13:26:50 +0000297 dashes = strstr(line, "---");
298 if (dashes) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200299 char *new_ring_name = malloc(dashes - line);
300 strncpy(new_ring_name, line, dashes - line);
301 new_ring_name[dashes - line - 1] = '\0';
302
Chris Wilson98eb5a52011-01-09 13:26:50 +0000303 matched = sscanf (dashes, "--- gtt_offset = 0x%08x\n",
304 &new_gtt_offset);
305 if (matched == 1) {
306 if (count) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200307 printf("%s (%s) at 0x%08x:\n",
308 buffer_type[is_batch],
309 ring_name,
310 gtt_offset);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100311 drm_intel_decode_set_batch_pointer(decode_ctx,
312 data, gtt_offset,
313 count);
314 drm_intel_decode(decode_ctx);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000315 count = 0;
316 }
317 gtt_offset = new_gtt_offset;
318 is_batch = 1;
Daniel Vetter73c21042011-10-11 13:14:02 +0200319 free(ring_name);
320 ring_name = new_ring_name;
Chris Wilson98eb5a52011-01-09 13:26:50 +0000321 continue;
322 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000323
Chris Wilson98eb5a52011-01-09 13:26:50 +0000324 matched = sscanf (dashes, "--- ringbuffer = 0x%08x\n",
325 &new_gtt_offset);
326 if (matched == 1) {
327 if (count) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200328 printf("%s (%s) at 0x%08x:\n",
329 buffer_type[is_batch],
330 ring_name,
331 gtt_offset);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100332 drm_intel_decode_set_batch_pointer(decode_ctx,
333 data, gtt_offset,
334 count);
335 drm_intel_decode(decode_ctx);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000336 count = 0;
337 }
338 gtt_offset = new_gtt_offset;
339 is_batch = 0;
Daniel Vetter73c21042011-10-11 13:14:02 +0200340 free(ring_name);
341 ring_name = new_ring_name;
Chris Wilson98eb5a52011-01-09 13:26:50 +0000342 continue;
343 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000344 }
345
346 matched = sscanf (line, "%08x : %08x", &offset, &value);
347 if (matched != 2) {
348 unsigned int reg;
349
Daniel Vetter92b1f2c2011-10-18 15:54:31 +0200350 /* display reg section is after the ringbuffers, don't mix them */
351 if (count) {
352 printf("%s (%s) at 0x%08x:\n",
353 buffer_type[is_batch],
354 ring_name,
355 gtt_offset);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100356 drm_intel_decode_set_batch_pointer(decode_ctx,
357 data, gtt_offset,
358 count);
359 drm_intel_decode(decode_ctx);
Daniel Vetter92b1f2c2011-10-18 15:54:31 +0200360 count = 0;
361 }
362
Chris Wilson9eb4de12010-02-12 13:28:40 +0000363 printf("%s", line);
364
365 matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
Chris Wilson412e7b32012-05-09 13:50:53 +0100366 if (matched == 0)
367 matched = sscanf (line, " PCI ID: 0x%04x\n", &reg);
Chris Wilson4f208442010-12-23 19:44:14 +0000368 if (matched == 1) {
Chris Wilson9eb4de12010-02-12 13:28:40 +0000369 devid = reg;
Daniel Vetter5801e6b2011-10-18 16:30:56 +0200370 printf("Detected GEN%i chipset\n",
371 intel_gen(devid));
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100372
373 decode_ctx = drm_intel_decode_context_alloc(devid);
Chris Wilson4f208442010-12-23 19:44:14 +0000374 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000375
376 matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100377 if (matched == 1)
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100378 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000379
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000380 matched = sscanf (line, " PGTBL_ER: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100381 if (matched == 1 && reg)
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000382 print_pgtbl_err(reg, devid);
383
Chris Wilson9eb4de12010-02-12 13:28:40 +0000384 matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100385 if (matched == 1)
Chris Wilson95374222010-04-08 11:56:57 +0100386 print_instdone (devid, reg, -1);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000387
388 matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100389 if (matched == 1)
Chris Wilson95374222010-04-08 11:56:57 +0100390 print_instdone (devid, -1, reg);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000391
Daniel Vetterd5109532011-10-21 19:06:08 +0200392 matched = sscanf (line, " fence[%i] = %Lx\n", &reg, &fence);
Daniel Vettercf5db112011-03-14 11:20:17 +0100393 if (matched == 2)
394 print_fence (devid, fence);
395
Chris Wilson9eb4de12010-02-12 13:28:40 +0000396 continue;
397 }
398
399 count++;
400
401 if (count > data_size) {
402 data_size = data_size ? data_size * 2 : 1024;
403 data = realloc (data, data_size * sizeof (uint32_t));
404 if (data == NULL) {
405 fprintf (stderr, "Out of memory.\n");
406 exit (1);
407 }
408 }
409
410 data[count-1] = value;
411 }
412
413 if (count) {
Daniel Vetter6ed89f42011-10-18 15:49:41 +0200414 printf("%s (%s) at 0x%08x:\n",
415 buffer_type[is_batch],
416 ring_name,
417 gtt_offset);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100418 drm_intel_decode_set_batch_pointer(decode_ctx,
419 data, gtt_offset,
420 count);
421 drm_intel_decode(decode_ctx);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000422 }
423
424 free (data);
425 free (line);
Daniel Vetter73c21042011-10-11 13:14:02 +0200426 free (ring_name);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000427}
428
429int
430main (int argc, char *argv[])
431{
Chris Wilsona3a78632010-12-01 21:51:59 +0000432 FILE *file;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000433 const char *path;
Daniel Vetterca10c722012-01-24 21:41:17 +0100434 char *filename = NULL;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000435 struct stat st;
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100436 int error;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000437
438 if (argc > 2) {
439 fprintf (stderr,
440 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
441 "Usage:\n"
442 "\t%s [<file>]\n"
443 "\n"
444 "With no arguments, debugfs-dri-directory is probed for in "
445 "/debug and \n"
446 "/sys/kernel/debug. Otherwise, it may be "
447 "specified. If a file is given,\n"
448 "it is parsed as an GPU dump in the format of "
449 "/debug/dri/0/i915_error_state.\n",
450 argv[0]);
451 return 1;
452 }
453
Chris Wilson9eb4de12010-02-12 13:28:40 +0000454 if (argc == 1) {
Chris Wilson292ae452010-12-10 15:31:59 +0000455 if (isatty(0)) {
Chris Wilson68a95f02011-01-25 16:34:08 +0000456 path = "/debug/dri";
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100457 error = stat (path, &st);
458 if (error != 0) {
Chris Wilson68a95f02011-01-25 16:34:08 +0000459 path = "/sys/kernel/debug/dri";
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100460 error = stat (path, &st);
461 if (error != 0) {
Chris Wilsona3a78632010-12-01 21:51:59 +0000462 errx(1,
463 "Couldn't find i915 debugfs directory.\n\n"
464 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
465 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
466 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000467 }
Chris Wilsona3a78632010-12-01 21:51:59 +0000468 } else {
469 read_data_file(stdin);
470 exit(0);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000471 }
472 } else {
473 path = argv[1];
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100474 error = stat (path, &st);
475 if (error != 0) {
Chris Wilson9eb4de12010-02-12 13:28:40 +0000476 fprintf (stderr, "Error opening %s: %s\n",
477 path, strerror (errno));
478 exit (1);
479 }
480 }
481
Chris Wilson68a95f02011-01-25 16:34:08 +0000482 if (S_ISDIR (st.st_mode)) {
Imre Deak5efd3d32012-10-10 16:04:39 +0300483 int ret;
484
485 ret = asprintf (&filename, "%s/i915_error_state", path);
486 assert(ret > 0);
Chris Wilson68a95f02011-01-25 16:34:08 +0000487 file = fopen(filename, "r");
488 if (!file) {
489 int minor;
490 for (minor = 0; minor < 64; minor++) {
491 free(filename);
Imre Deak5efd3d32012-10-10 16:04:39 +0300492 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
493 assert(ret > 0);
494
Chris Wilson68a95f02011-01-25 16:34:08 +0000495 file = fopen(filename, "r");
496 if (file)
497 break;
498 }
499 }
500 if (!file) {
501 fprintf (stderr, "Failed to find i915_error_state beneath %s\n",
502 path);
503 exit (1);
504 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000505 } else {
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100506 file = fopen(path, "r");
Chris Wilson68a95f02011-01-25 16:34:08 +0000507 if (!file) {
508 fprintf (stderr, "Failed to open %s: %s\n",
Daniel Vetter391e6aa2012-01-09 23:06:41 +0100509 path, strerror (errno));
Chris Wilson68a95f02011-01-25 16:34:08 +0000510 exit (1);
511 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000512 }
513
Chris Wilson68a95f02011-01-25 16:34:08 +0000514 read_data_file (file);
515 fclose (file);
516
Chris Wilsona3a78632010-12-01 21:51:59 +0000517 if (filename != path)
518 free (filename);
519
Chris Wilson9eb4de12010-02-12 13:28:40 +0000520 return 0;
521}