summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordom.constant@free.fr <dom.constant@free.fr>2018-02-06 19:57:05 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2018-03-02 15:17:35 +0000
commitaa36399cca1250d878a4608528a535faeb0e931a (patch)
treeb38ab4f73f9ad857e9fa1149ccaf30025845c675
parent9b4f400190064f9b60f9f3ce3517586124f157ba (diff)
sna: CustomEDID fix
For my HTPC setup, I'm using the option "CustomEDID". With this option, output attaching and destroying events leads to crashes. The following sequence leads to a crash: - In xorg.conf: Option "CustomEDID" "HDMI2:/etc/my_edid.bin" - Starting Xorg - Connect HDMI2 - Disconnect HDMI2 - Reconnect HDMI2 -> Crash The crash happens in xf86OutputSetEDID (xorg/xserver/hw/xfree86/modes/xf86Crtc.c) at "free(output->MonInfo)". MonInfo is assigned with sna_output->fake_edid_mon which is allocated by intel driver in sna_output_load_fake_edid (src/sna/sna_display.c). Sequence details: - Starting Xorg -> fake_edid_mon is initialized - Connect HDMI2 -> xf86OutputSetEDID is called: - MonInfo is NULL - MonInfo is assigned with fake_edid_mon pointer - MonInfo is read by Xorg - Disconnect HDMI2 - Reconnect HDMI2 -> xf86OutputSetEDID is called: - MonInfo is freed thus also fake_edid_mon - MonInfo is assigned with fake_edid_mon - MonInfo is read but it was freed -> CRASH The fix consists of a new instance of xf86MonPtr for each calls of xf86OutputSetEDID. is initialized with fake_edid_raw which render fake_edid_mon useless. With this proposal, the behaviour of an EDID override is similar to a "real" EDID. Signed-off-by: Dominique Constant <dom.constant@free.fr> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_display.c28
1 files changed, 12 insertions, 16 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 091932f7..e7bf6cab 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -267,7 +267,6 @@ struct sna_output {
uint32_t edid_blob_id;
uint32_t edid_len;
void *edid_raw;
- xf86MonPtr fake_edid_mon;
void *fake_edid_raw;
bool has_panel_limits;
@@ -4189,13 +4188,21 @@ static DisplayModePtr
sna_output_override_edid(xf86OutputPtr output)
{
struct sna_output *sna_output = output->driver_private;
+ xf86MonPtr mon = NULL;
+
+ if (sna_output->fake_edid_raw == NULL)
+ return NULL;
- if (sna_output->fake_edid_mon == NULL)
+ mon = xf86InterpretEDID(output->scrn->scrnIndex, sna_output->fake_edid_raw);
+ if (mon == NULL) {
return NULL;
+ }
+
+ mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
+
+ xf86OutputSetEDID(output, mon);
- xf86OutputSetEDID(output, sna_output->fake_edid_mon);
- return xf86DDCGetModes(output->scrn->scrnIndex,
- sna_output->fake_edid_mon);
+ return xf86DDCGetModes(output->scrn->scrnIndex, mon);
}
static DisplayModePtr
@@ -4983,7 +4990,6 @@ sna_output_load_fake_edid(xf86OutputPtr output)
FILE *file;
void *raw;
int size;
- xf86MonPtr mon;
filename = fake_edid_name(output);
if (filename == NULL)
@@ -5015,16 +5021,6 @@ sna_output_load_fake_edid(xf86OutputPtr output)
}
fclose(file);
- mon = xf86InterpretEDID(output->scrn->scrnIndex, raw);
- if (mon == NULL) {
- free(raw);
- goto err;
- }
-
- if (mon && size > 128)
- mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
-
- sna_output->fake_edid_mon = mon;
sna_output->fake_edid_raw = raw;
xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,