summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-12-15 16:46:47 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2015-12-15 17:05:30 +0000
commitf458e8c41112cf56a132ac42cc9e6a4be893ff2c (patch)
tree65d52590d9386c5e9f1ffa895d476bad098c1d67
parent6c4ffba39acb114cbbbfa3359a8c1ba7dfcc7df6 (diff)
sna: Dump kernel debug messages for KMS failures
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_display.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index cc1c2583..3de232bf 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1235,6 +1235,81 @@ bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation)
rotation_reduce(&to_sna_crtc(crtc)->sprite, rotation));
}
+#if HAS_DEBUG_FULL
+struct kmsg {
+ int fd;
+ int saved_loglevel;
+};
+
+static int kmsg_get_debug(void)
+{
+ FILE *file;
+ int v = -1;
+
+ file = fopen("/sys/module/drm/parameters/debug", "r");
+ if (file) {
+ fscanf(file, "%d", &v);
+ fclose(file);
+ }
+
+ return v;
+}
+
+static void kmsg_set_debug(int v)
+{
+ FILE *file;
+
+ file = fopen("/sys/module/drm/parameters/debug", "w");
+ if (file) {
+ fprintf(file, "%d\n", v);
+ fclose(file);
+ }
+}
+
+static void kmsg_open(struct kmsg *k)
+{
+ k->saved_loglevel = kmsg_get_debug();
+ if (k->saved_loglevel != -1)
+ kmsg_set_debug(0xff);
+
+ k->fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
+ if (k->fd != -1)
+ lseek(k->fd, 0, SEEK_END);
+}
+
+static void kmsg_close(struct kmsg *k, int dump)
+{
+ FILE *file;
+
+ file = NULL;
+ if (k->fd != -1 && dump)
+ file = fdopen(k->fd, "r");
+ if (file) {
+ size_t len = 0;
+ char *line = NULL;
+
+ while (getline(&line, &len, file) != -1) {
+ char *start = strchr(line, ';');
+ if (start)
+ LogF("KMSG: %s", start + 1);
+ }
+
+ free(line);
+ fclose(file);
+ }
+
+ if (k->fd != -1)
+ close(k->fd);
+
+ if (k->saved_loglevel != -1)
+ kmsg_set_debug(k->saved_loglevel);
+}
+#else
+struct kmsg { int unused; };
+static void kmsg_open(struct kmsg *k);
+static void kmsg_close(struct kmsg *k, int dump);
+#endif
+
static bool
sna_crtc_apply(xf86CrtcPtr crtc)
{
@@ -1245,6 +1320,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
uint32_t output_ids[32];
int output_count = 0;
int sigio, i;
+ struct kmsg kmsg;
bool ret = false;
DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__,
@@ -1257,6 +1333,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
}
sigio = sigio_block();
+ kmsg_open(&kmsg);
assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
sna_crtc_disable_cursor(sna, sna_crtc);
@@ -1348,6 +1425,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
sna_crtc_force_outputs_on(crtc);
}
unblock:
+ kmsg_close(&kmsg, !ret);
sigio_unblock(sigio);
return ret;
}