monitor-manager-kms: Don't try to wait for EDID on hot plug
The mitigation to avoid missing EDID blob was incorrect; the reason it sometimes failed to read was a race between different applications all trying to read the EDID at the same time. E.g. gnome-shell as GDM would at the same time as the session gnome-shell try to read the EDID of the same connector at the same time, triggering a race in the kernel, making the blob reading ioctl occationally fail with ENOENT. Remove this mitigation, as it didn't really mitigate anything; the race could just as well happen when doing the actual read later. https://bugzilla.gnome.org/show_bug.cgi?id=779837
This commit is contained in:
parent
db14e6099e
commit
eb3ff3f44a
@ -52,10 +52,6 @@
|
||||
#define ALL_TRANSFORMS_MASK ((1 << ALL_TRANSFORMS) - 1)
|
||||
#define SYNC_TOLERANCE 0.01 /* 1 percent */
|
||||
|
||||
/* Try each 50 milleseconds up to half a second to get a proper EDID read */
|
||||
#define EDID_RETRY_TIMEOUT_MS 50
|
||||
#define EDID_MAX_NUM_RETRIES 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drmModeConnector *connector;
|
||||
@ -117,9 +113,6 @@ struct _MetaMonitorManagerKms
|
||||
GSettings *desktop_settings;
|
||||
|
||||
gboolean page_flips_not_supported;
|
||||
|
||||
guint handle_hotplug_timeout;
|
||||
int read_edid_tries;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerKmsClass
|
||||
@ -1595,76 +1588,6 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_pending_edid_blob (MetaMonitorManagerKms *manager_kms)
|
||||
{
|
||||
drmModeRes *resources;
|
||||
int n_connectors;
|
||||
int i, j;
|
||||
gboolean edid_blob_pending;
|
||||
|
||||
resources = drmModeGetResources (manager_kms->fd);
|
||||
n_connectors = resources->count_connectors;
|
||||
|
||||
edid_blob_pending = FALSE;
|
||||
for (i = 0; i < n_connectors; i++)
|
||||
{
|
||||
drmModeConnector *drm_connector;
|
||||
uint32_t edid_blob_id;
|
||||
|
||||
drm_connector = drmModeGetConnector (manager_kms->fd,
|
||||
resources->connectors[i]);
|
||||
|
||||
edid_blob_id = 0;
|
||||
for (j = 0; j < drm_connector->count_props; j++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = drmModeGetProperty (manager_kms->fd, drm_connector->props[j]);
|
||||
|
||||
if (prop->flags & DRM_MODE_PROP_BLOB &&
|
||||
g_str_equal (prop->name, "EDID"))
|
||||
edid_blob_id = drm_connector->prop_values[j];
|
||||
|
||||
drmModeFreeProperty (prop);
|
||||
|
||||
if (edid_blob_id)
|
||||
break;
|
||||
}
|
||||
|
||||
drmModeFreeConnector (drm_connector);
|
||||
|
||||
if (edid_blob_id)
|
||||
{
|
||||
GError *error = NULL;
|
||||
drmModePropertyBlobPtr edid_blob;
|
||||
|
||||
edid_blob = read_edid_blob (manager_kms, edid_blob_id, &error);
|
||||
if (!edid_blob &&
|
||||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
edid_blob_pending = TRUE;
|
||||
g_error_free (error);
|
||||
}
|
||||
else if (!edid_blob)
|
||||
{
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
drmModeFreePropertyBlob (edid_blob);
|
||||
}
|
||||
}
|
||||
|
||||
if (edid_blob_pending)
|
||||
break;
|
||||
}
|
||||
|
||||
drmModeFreeResources (resources);
|
||||
|
||||
return edid_blob_pending;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_hotplug_event (MetaMonitorManager *manager)
|
||||
{
|
||||
@ -1672,37 +1595,6 @@ handle_hotplug_event (MetaMonitorManager *manager)
|
||||
meta_monitor_manager_on_hotplug (manager);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_hotplug_event_timeout (gpointer user_data)
|
||||
{
|
||||
MetaMonitorManager *manager = user_data;
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data);
|
||||
|
||||
if (!has_pending_edid_blob (manager_kms))
|
||||
{
|
||||
handle_hotplug_event (manager);
|
||||
|
||||
manager_kms->handle_hotplug_timeout = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
manager_kms->read_edid_tries++;
|
||||
|
||||
if (manager_kms->read_edid_tries > EDID_MAX_NUM_RETRIES)
|
||||
{
|
||||
g_warning ("Tried to read the EDID %d times, "
|
||||
"but one or more are still missing, continuing without",
|
||||
manager_kms->read_edid_tries);
|
||||
|
||||
handle_hotplug_event (manager);
|
||||
|
||||
manager_kms->handle_hotplug_timeout = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_uevent (GUdevClient *client,
|
||||
const char *action,
|
||||
@ -1715,28 +1607,6 @@ on_uevent (GUdevClient *client,
|
||||
if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG"))
|
||||
return;
|
||||
|
||||
if (manager_kms->handle_hotplug_timeout)
|
||||
{
|
||||
g_source_remove (manager_kms->handle_hotplug_timeout);
|
||||
manager_kms->handle_hotplug_timeout = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On a hot-plug event, the EDID of one or more connectors might not yet be
|
||||
* ready at this point, resulting in invalid configuration potentially being
|
||||
* applied. Avoid this by first checking whether the EDID is ready at this
|
||||
* point, or otherwise wait a bit and try again.
|
||||
*/
|
||||
manager_kms->read_edid_tries = 0;
|
||||
if (has_pending_edid_blob (manager_kms))
|
||||
{
|
||||
manager_kms->handle_hotplug_timeout =
|
||||
g_timeout_add (EDID_RETRY_TIMEOUT_MS,
|
||||
handle_hotplug_event_timeout,
|
||||
manager);
|
||||
return;
|
||||
}
|
||||
|
||||
handle_hotplug_event (manager);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user