xf86-video-intel: 4 commits - src/compat-api.h src/sna/sna_display.c src/sna/sna_driver.c src/sna/sna.h

Chris Wilson ickle at kemper.freedesktop.org
Fri May 2 09:16:44 PDT 2014


 src/compat-api.h      |    1 
 src/sna/sna.h         |    3 
 src/sna/sna_display.c |  309 +++++++++++++++++++++++++++++++++++++-------------
 src/sna/sna_driver.c  |   33 +++--
 4 files changed, 254 insertions(+), 92 deletions(-)

New commits:
commit 828bd9e250b7d9dd1dc4185c0179237e9b21d8bf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 2 17:13:29 2014 +0100

    sna: Reorder cursor initialisation
    
    It helps to initialise the cursors after we setup one of the values we
    depend on.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 47a36d8..70fbc8d 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3802,6 +3802,9 @@ sna_cursor_pre_init(struct sna *sna)
 		uint64_t value;
 	} cap;
 
+	if (sna->mode.num_real_crtc == 0)
+		return;
+
 #define LOCAL_IOCTL_GET_CAP	DRM_IOWR(0x0c, struct local_get_cap)
 #define DRM_CAP_CURSOR_WIDTH	8
 #define DRM_CAP_CURSOR_HEIGHT	9
@@ -4392,8 +4395,6 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
 		assert(res->count_crtcs);
 		assert(res->count_connectors);
 
-		sna_cursor_pre_init(sna);
-
 		xf86CrtcConfigInit(scrn, &sna_mode_funcs);
 
 		xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -4417,6 +4418,8 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
 		sna->mode.max_crtc_height = res->max_height;
 
 		drmModeFreeResources(res);
+
+		sna_cursor_pre_init(sna);
 	} else {
 		if (num_fake == 0)
 			num_fake = 1;
commit 38f82655e0bc8f26250f56e9a25aedd30b46360c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 2 12:30:43 2014 +0100

    sna: Remove incorrect cursor assertion
    
    Ideally, we want to assert that we have sufficient stashed cursors to
    allocate for the unused CRTCS, so something like
    assert(num_stash + num_active_cursors >= 0);
    
    Reported-by: Zdenek Kabelac <zkabelac at redhat.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index a66ca09..47a36d8 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3765,10 +3765,8 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
 	       cursor->bits->width, cursor->bits->height));
 
 	/* cursors are invariant */
-	if (cursor == sna->cursor.ref) {
-		assert(sna->cursor.num_stash >= 0);
+	if (cursor == sna->cursor.ref)
 		return TRUE;
-	}
 
 	if (sna->cursor.ref) {
 		FreeCursor(sna->cursor.ref, None);
commit 430152da82f496ac47f33ce1eca65d154af38752
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 2 16:57:27 2014 +0100

    compat: Add missing wrapper for RegionSubtract
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/compat-api.h b/src/compat-api.h
index 244a486..c7b0aae 100644
--- a/src/compat-api.h
+++ b/src/compat-api.h
@@ -121,6 +121,7 @@
 #define RegionCopy(res, r) REGION_COPY(NULL, res, r)
 #define RegionIntersect(res, r1, r2) REGION_INTERSECT(NULL, res, r1, r2)
 #define RegionUnion(res, r1, r2) REGION_UNION(NULL, res, r1, r2)
+#define RegionSubtract(res, r1, r2) REGION_SUBTRACT(NULL, res, r1, r2)
 #define RegionTranslate(r, x, y) REGION_TRANSLATE(NULL, r, x, y)
 #define RegionUninit(r) REGION_UNINIT(NULL, r)
 #define region_from_bitmap BITMAP_TO_REGION
commit add84cd8a8dc6d285912d0ea3a3a3e7faa9e0942
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 2 13:21:02 2014 +0100

    sna: Perform dynamic connector discovery
    
    One of the side-effects of MST is that we need to support dynamic
    attachment and removal of displays as the branch hierachy changes.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index cf9a4d5..cc086d7 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -242,6 +242,7 @@ struct sna {
 #define SNA_IS_HOSTED		0x80
 #define SNA_PERFORMANCE		0x100
 #define SNA_POWERSAVE		0x200
+#define SNA_REDISCOVER		0x40000000
 #define SNA_REPROBE		0x80000000
 
 	unsigned cpu_features;
@@ -281,6 +282,7 @@ struct sna {
 		unsigned num_real_crtc;
 		unsigned num_real_output;
 		unsigned num_fake;
+		unsigned serial;
 	} mode;
 
 	struct {
@@ -378,6 +380,7 @@ struct sna {
 bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
 bool sna_mode_fake_init(struct sna *sna, int num_fake);
 void sna_mode_adjust_frame(struct sna *sna, int x, int y);
+extern void sna_mode_discover(struct sna *sna);
 extern void sna_mode_update(struct sna *sna);
 extern void sna_mode_reset(struct sna *sna);
 extern void sna_mode_wakeup(struct sna *sna);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index ae07252..a66ca09 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -47,6 +47,7 @@
 #include "backlight.h"
 
 #include <xf86Crtc.h>
+#include <xf86RandR12.h>
 #include <cursorstr.h>
 
 #if XF86_CRTC_VERSION >= 3
@@ -128,7 +129,8 @@ struct sna_property {
 
 struct sna_output {
 	int id;
-	int encoder_idx;
+	int encoder_id, encoder_idx;
+	int serial;
 
 	unsigned int is_panel : 1;
 
@@ -743,14 +745,15 @@ sna_crtc_apply(xf86CrtcPtr crtc)
 		if (output->crtc != crtc)
 			continue;
 
-		assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
-		       xf86IsEntityShared(crtc->scrn->entityList[0]));
-
 		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
 		     __FUNCTION__, output->name, i, to_connector_id(output),
 		     sna_crtc->id, sna_crtc->pipe,
 		     (uint32_t)output->possible_crtcs,
 		     (uint32_t)output->possible_clones));
+
+		assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
+		       xf86IsEntityShared(crtc->scrn->entityList[0]));
+
 		output_ids[output_count] = to_connector_id(output);
 		if (++output_count == ARRAY_SIZE(output_ids))
 			return false;
@@ -1799,7 +1802,7 @@ sna_crtc_init__cursor(struct sna *sna, struct sna_crtc *crtc)
 }
 
 static bool
-sna_crtc_init(ScrnInfoPtr scrn, int id)
+sna_crtc_add(ScrnInfoPtr scrn, int id)
 {
 	struct sna *sna = to_sna(scrn);
 	xf86CrtcPtr crtc;
@@ -2634,24 +2637,98 @@ output_ignored(ScrnInfoPtr scrn, const char *name)
 	return xf86CheckBoolOption(conf->mon_option_lst, "Ignore", 0);
 }
 
-static bool
-sna_output_init(ScrnInfoPtr scrn, int id, drmModeResPtr res)
+/* We need to map from kms encoder based possible_clones mask to X output based
+ * possible clones masking. Note that for SDVO and on Haswell with DP/HDMI we
+ * can have more than one output hanging off the same encoder.
+ */
+static void
+sna_mode_compute_possible_outputs(struct sna *sna, drmModeResPtr res)
 {
-	struct sna *sna = to_sna(scrn);
-	xf86OutputPtr output;
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i, j;
+
+	assert(sna->mode.num_real_output < 32);
+	assert(sna->mode.num_real_crtc < 32);
+
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		struct sna_output *sna_output = to_sna_output(output);
+		struct drm_mode_get_encoder enc;
+
+		assert(to_sna_output(output));
+
+		sna_output->encoder_idx = -1;
+		output->possible_clones = 0;
+
+		VG_CLEAR(enc);
+		enc.encoder_id = sna_output->encoder_id;
+
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
+			DBG(("%s: GETENCODER failed, ret=%d\n", __FUNCTION__, errno));
+			continue;
+		}
+
+		for (j = 0; j < res->count_encoders; j++) {
+			if (enc.encoder_id == res->encoders[j]) {
+				sna_output->encoder_idx = j;
+				break;
+			}
+		}
+		assert(sna_output->encoder_idx != -1);
+
+		output->possible_clones = enc.possible_clones;
+	}
+
+	/* Convert from encoder numbering to output numbering */
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		unsigned mask = output->possible_clones;
+		unsigned clones = 0;
+
+		assert(to_sna_output(output));
+		if (output->possible_clones == 0)
+			continue;
+
+		for (j = 0; j < sna->mode.num_real_output; j++) {
+			struct sna_output *sna_output = to_sna_output(config->output[j]);
+
+			if (i == j)
+				continue;
+
+			if (sna_output->encoder_idx == -1)
+				continue;
+
+			if (mask & (1 << sna_output->encoder_idx))
+				clones |= 1 << j;
+		}
+
+		output->possible_clones = clones;
+
+		DBG(("%s: updated output '%s' %d [%d] (possible crtc:%x, possible clones:%x)\n",
+		     __FUNCTION__, output->name, i, to_connector_id(output),
+		     (uint32_t)output->possible_crtcs,
+		     (uint32_t)output->possible_clones));
+	}
+}
+
+static int
+sna_output_add(struct sna *sna, int id, drmModeResPtr res, int serial)
+{
+	ScrnInfoPtr scrn = sna->scrn;
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
 	union compat_mode_get_connector compat_conn;
 	struct drm_mode_get_encoder enc;
 	struct drm_mode_modeinfo dummy;
 	struct sna_output *sna_output;
+	xf86OutputPtr *outputs, output;
 	const char *output_name;
 	char name[32];
-	bool ret = false;
-	int i;
-
-	COMPILE_TIME_ASSERT(sizeof(struct drm_mode_get_connector) <= sizeof(compat_conn.pad));
+	int len, i, ret = -1;
 
 	DBG(("%s(%d)\n", __FUNCTION__, id));
 
+	COMPILE_TIME_ASSERT(sizeof(struct drm_mode_get_connector) <= sizeof(compat_conn.pad));
+
 	VG_CLEAR(compat_conn);
 	VG_CLEAR(enc);
 
@@ -2664,23 +2741,23 @@ sna_output_init(ScrnInfoPtr scrn, int id, drmModeResPtr res)
 
 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &compat_conn.conn)) {
 		DBG(("%s: GETCONNECTOR failed, ret=%d\n", __FUNCTION__, errno));
-		return false;
+		return -1;
 	}
 
 	if (compat_conn.conn.count_encoders != 1) {
 		DBG(("%s: unexpected number [%d] of encoders attached\n",
 		     __FUNCTION__, compat_conn.conn.count_encoders));
-		return false;
+		return 0;
 	}
 
 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
 		DBG(("%s: GETENCODER failed, ret=%d\n", __FUNCTION__, errno));
-		return false;
+		return 0;
 	}
 
 	sna_output = calloc(sizeof(struct sna_output), 1);
 	if (!sna_output)
-		return false;
+		return -1;
 
 	sna_output->num_props = compat_conn.conn.count_props;
 	sna_output->prop_ids = malloc(sizeof(uint32_t)*compat_conn.conn.count_props);
@@ -2710,7 +2787,9 @@ sna_output_init(ScrnInfoPtr scrn, int id, drmModeResPtr res)
 		output_name = output_names[compat_conn.conn.connector_type];
 	else
 		output_name = "UNKNOWN";
-	snprintf(name, 32, "%s%d", output_name, compat_conn.conn.connector_type_id);
+	len = snprintf(name, 32, "%s%d", output_name, compat_conn.conn.connector_type_id);
+	if (output_ignored(scrn, name))
+		return 0;
 
 	if (xf86IsEntityShared(scrn->entityList[0])) {
 		const char *str;
@@ -2718,7 +2797,7 @@ sna_output_init(ScrnInfoPtr scrn, int id, drmModeResPtr res)
 		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
 		if (str && !sna_zaphod_match(str, name)) {
 			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
-			ret = true;
+			ret = 0;
 			goto cleanup;
 		}
 
@@ -2732,22 +2811,39 @@ sna_output_init(ScrnInfoPtr scrn, int id, drmModeResPtr res)
 		}
 
 		enc.possible_crtcs = 1;
-		enc.possible_clones = 0;
 	}
 
-	output = xf86OutputCreate(scrn, &sna_output_funcs, name);
-	if (!output) {
-		/* xf86OutputCreate does not differentiate between
-		 * a failure to allocate the output, and a user request
-		 * to ignore the output. So reconstruct whether the user
-		 * explicitly ignored the output.
-		 */
-		ret = output_ignored(scrn, name);
-		DBG(("%s: create failed, ignored? %d\n", __FUNCTION__, ret));
+	output = calloc(1, sizeof(*output) + len + 1);
+	if (!output)
 		goto cleanup;
+
+	outputs = realloc(config->output, (config->num_output + 1) * sizeof(output));
+	if (outputs == NULL) {
+		free(output);
+		goto cleanup;
+	}
+
+	for (i = config->num_output; i > sna->mode.num_real_output; i--) {
+		outputs[i] = outputs[i-1];
+		assert(outputs[i]->driver_private == NULL);
+		outputs[i]->possible_clones <<= 1;
 	}
+	outputs[i] = output;
+	sna->mode.num_real_output++;
+	config->num_output++;
+	config->output = outputs;
+
+	output->scrn = scrn;
+	output->funcs = &sna_output_funcs;
+	output->name = (char *)(output + 1);
+	memcpy(output->name, name, len + 1);
+
+	output->use_screen_monitor = config->num_output;
+	xf86OutputUseScreenMonitor(output, !config->num_output);
 
 	sna_output->id = compat_conn.conn.connector_id;
+	sna_output->encoder_id = enc.encoder_id;
+	sna_output->encoder_idx = -1;
 	sna_output->is_panel = is_panel(compat_conn.conn.connector_type);
 	sna_output->edid_idx = find_property(sna, sna_output, "EDID");
 	sna_output->dpms_id = find_property_id(sna, sna_output, "DPMS");
@@ -2760,33 +2856,34 @@ sna_output_init(ScrnInfoPtr scrn, int id, drmModeResPtr res)
 	output->subpixel_order = subpixel_conv_table[compat_conn.conn.subpixel];
 	output->driver_private = sna_output;
 
-	for (i = 0; i < res->count_encoders; i++) {
-		if (enc.encoder_id == res->encoders[i]) {
-			sna_output->encoder_idx = i;
-			break;
-		}
-	}
-
 	if (sna_output->is_panel)
 		sna_output_backlight_init(output);
 
-	output->possible_crtcs = enc.possible_crtcs;
-	output->possible_clones = enc.possible_clones;
+	output->possible_crtcs = enc.possible_crtcs & ((1 << sna->mode.num_real_crtc) - 1);
 	output->interlaceAllowed = TRUE;
 
-	/* stash the active CRTC id for our probe function */
-	output->crtc = NULL;
-	if (compat_conn.conn.connection != DRM_MODE_DISCONNECTED)
-		output->crtc = (void *)(uintptr_t)enc.crtc_id;
+	if (serial) {
+		output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), name, len, output);
+		if (output->randr_output == NULL)
+			goto cleanup;
+
+		sna_output_create_resources(output);
+		RRPostPendingProperties(output->randr_output);
+
+		sna_output->serial = serial;
+	} else {
+		/* stash the active CRTC id for our probe function */
+		if (compat_conn.conn.connection != DRM_MODE_DISCONNECTED)
+			output->crtc = (void *)(uintptr_t)enc.crtc_id;
+	}
 
-	DBG(("%s: created output '%s' %d (possible crtc:%x, possible clones:%x), edid=%d, dpms=%d, crtc=%lu\n",
+	DBG(("%s: created output '%s' %d (possible crtc:%x), serial=%d, edid=%d, dpms=%d, crtc=%lu\n",
 	     __FUNCTION__, name, id,
 	     (uint32_t)output->possible_crtcs,
-	     (uint32_t)output->possible_clones,
-	     sna_output->edid_idx, sna_output->dpms_id,
+	     serial, sna_output->edid_idx, sna_output->dpms_id,
 	     (unsigned long)(uintptr_t)output->crtc));
 
-	return true;
+	return 1;
 
 cleanup:
 	free(sna_output->prop_ids);
@@ -2795,41 +2892,92 @@ cleanup:
 	return ret;
 }
 
-/* We need to map from kms encoder based possible_clones mask to X output based
- * possible clones masking. Note that for SDVO and on Haswell with DP/HDMI we
- * can have more than one output hanging off the same encoder.
- */
-static void
-sna_mode_compute_possible_outputs(ScrnInfoPtr scrn)
+static void sna_output_del(xf86OutputPtr output)
 {
+	ScrnInfoPtr scrn = output->scrn;
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
-	unsigned crtc_mask;
-	int i, j;
+	int i;
 
-	assert(config->num_output < 32);
-	assert(config->num_crtc < 32);
+	assert(to_sna_output(output));
 
-	crtc_mask = (1 << config->num_crtc) - 1;
+	RROutputDestroy(output->randr_output);
+	sna_output_destroy(output);
 
-	/* Convert from encoder numbering to output numbering */
+	while (output->probed_modes)
+		xf86DeleteMode(&output->probed_modes, output->probed_modes);
+
+	free(output);
+
+	for (i = 0; i < config->num_output; i++)
+		if (config->output[i] == output)
+			break;
+	assert(i < to_sna(scrn)->mode.num_real_output);
+
+	for (; i < config->num_output; i++) {
+		config->output[i] = config->output[i+1];
+		config->output[i]->possible_clones >>= 1;
+	}
+	config->num_output--;
+	to_sna(scrn)->mode.num_real_output--;
+}
+
+static void sort_randr_outputs(struct sna *sna, ScreenPtr screen)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	rrScrPriv(screen);
+	int i;
+
+	assert(pScrPriv->numOutputs = config->num_output);
 	for (i = 0; i < config->num_output; i++) {
-		xf86OutputPtr output = config->output[i];
-		unsigned mask = output->possible_clones;
-		unsigned clones = 0;
+		assert(config->output[i]->randr_output);
+		pScrPriv->outputs[i] = config->output[i]->randr_output;
+	}
+}
 
-		for (j = 0; j < config->num_output; j++) {
-			if (mask & (1 << to_sna_output(config->output[j])->encoder_idx))
-				clones |= 1 << j;
+void sna_mode_discover(struct sna *sna)
+{
+	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	drmModeResPtr res;
+	int i, j, serial = ++sna->mode.serial;
+	bool changed = false;
+
+	res = drmModeGetResources(sna->kgem.fd);
+	if (res == NULL)
+		return;
+
+	assert(res->count_crtcs == sna->mode.num_real_crtc);
+	assert(sna->mode.max_crtc_width  == res->max_width);
+	assert(sna->mode.max_crtc_height == res->max_height);
+
+	for (i = 0; i < res->count_connectors; i++) {
+		for (j = 0; j < sna->mode.num_real_output; j++) {
+			if (to_sna_output(config->output[j])->id == res->connectors[i]) {
+				to_sna_output(config->output[j])->serial = serial;
+				break;
+			}
 		}
+		if (j == sna->mode.num_real_output)
+			changed |= sna_output_add(sna, res->connectors[i], res, serial) > 0;
+	}
 
-		output->possible_clones = clones;
-		output->possible_crtcs &= crtc_mask;
+	for (i = 0; i < sna->mode.num_real_output; i++) {
+		xf86OutputPtr output = config->output[i];
+		if (to_sna_output(output)->serial != serial) {
+			sna_output_del(output);
+			changed = true;
+		}
+	}
 
-		DBG(("%s: updated output '%s' %d [%d] (possible crtc:%x, possible clones:%x)\n",
-		     __FUNCTION__, output->name, i, to_connector_id(output),
-		     (uint32_t)output->possible_crtcs,
-		     (uint32_t)output->possible_clones));
+	if (changed) {
+		sna_mode_compute_possible_outputs(sna, res);
+
+		/* Reorder user visible listing */
+		sort_randr_outputs(sna, screen);
+		xf86RandR12TellChanged(screen);
 	}
+
+	drmModeFreeResources(res);
 }
 
 static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
@@ -4254,18 +4402,18 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
 		xf86_config->xf86_crtc_notify = sna_crtc_config_notify;
 
 		for (i = 0; i < res->count_crtcs; i++)
-			if (!sna_crtc_init(scrn, res->crtcs[i]))
+			if (!sna_crtc_add(scrn, res->crtcs[i]))
 				return false;
 
+		sna->mode.num_real_crtc = xf86_config->num_crtc;
+
 		for (i = 0; i < res->count_connectors; i++)
-			if (!sna_output_init(scrn, res->connectors[i], res))
+			if (sna_output_add(sna, res->connectors[i], res, 0) < 0)
 				return false;
 
-		sna->mode.num_real_crtc   = xf86_config->num_crtc;
 		sna->mode.num_real_output = xf86_config->num_output;
 
-		if (!xf86IsEntityShared(scrn->entityList[0]))
-			sna_mode_compute_possible_outputs(scrn);
+		sna_mode_compute_possible_outputs(sna, res);
 
 		sna->mode.max_crtc_width  = res->max_width;
 		sna->mode.max_crtc_height = res->max_height;
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 673e2a5..80ff33b 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -689,7 +689,7 @@ sna_handle_uevents(int fd, void *closure)
 	ScrnInfoPtr scrn = closure;
 	struct sna *sna = to_sna(scrn);
 	struct udev_device *dev;
-	const char *hotplug;
+	const char *str;
 	struct stat s;
 	dev_t udev_devnum;
 
@@ -700,21 +700,13 @@ sna_handle_uevents(int fd, void *closure)
 		return;
 
 	udev_devnum = udev_device_get_devnum(dev);
-	if (fstat(sna->kgem.fd, &s)) {
+	if (fstat(sna->kgem.fd, &s) || memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t))) {
 		udev_device_unref(dev);
 		return;
 	}
 
-	/*
-	 * Check to make sure this event is directed at our
-	 * device (by comparing dev_t values), then make
-	 * sure it's a hotplug event (HOTPLUG=1)
-	 */
-
-	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
-
-	if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
-	    hotplug && atoi(hotplug) == 1) {
+	str = udev_device_get_property_value(dev, "HOTPLUG");
+	if (str && atoi(str) == 1) {
 		DBG(("%s: hotplug event (vtSema?=%d)\n",
 		     __FUNCTION__, sna->scrn->vtSema));
 		if (sna->scrn->vtSema) {
@@ -724,6 +716,16 @@ sna_handle_uevents(int fd, void *closure)
 			sna->flags |= SNA_REPROBE;
 	}
 
+	str = udev_device_get_property_value(dev, "DISCOVER");
+	if (str && atoi(str) == 1) {
+		DBG(("%s: discover event (vtSema?=%d)\n",
+		     __FUNCTION__, sna->scrn->vtSema));
+		if (sna->scrn->vtSema)
+			sna_mode_discover(sna);
+		else
+			sna->flags |= SNA_REDISCOVER;
+	}
+
 	udev_device_unref(dev);
 }
 
@@ -1094,6 +1096,13 @@ static Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
 	if (!sna_set_desired_mode(sna))
 		return FALSE;
 
+	if (sna->flags & SNA_REDISCOVER) {
+		DBG(("%s: reporting deferred discover event\n",
+		     __FUNCTION__));
+		sna_mode_discover(sna);
+		sna->flags &= ~SNA_REDISCOVER;
+	}
+
 	if (sna->flags & SNA_REPROBE) {
 		DBG(("%s: reporting deferred hotplug event\n",
 		     __FUNCTION__));


More information about the xorg-commit mailing list