[PATCH xserver] modesetting: re-set the crtc's mode when link-status goes BAD
Martin Peres
martin.peres at linux.intel.com
Mon Apr 10 13:48:21 UTC 2017
Despite all the careful planing of the kernel, a link may become
insufficient to handle the currently-set mode. At this point, the
kernel should mark this particular configuration as being broken
and potentially prune the mode before setting the offending connector's
link-status to BAD and send the userspace a hotplug event. This may
happen right after a modeset or later on.
Upon receiving a hot-plug event, we iterate through the connectors to
re-apply the currently-set mode on all the connectors that have a
link-status property set to BAD. This modeset may fail immediatly if
the kernel has already pruned the mode we are trying to set but it
does not matter as -modesetting has no business picking another
mode if the modeset did fail. To make users aware of this problem
a warning is outputed in the logs to warn about having a
potentially-black display.
This patch does not modify the current behaviour of always propagating
the events to the randr clients. This allows desktop environments to
re-probe the connectors and select a new resolution based on the new
(currated) mode list if a mode disapeared. This behaviour is expected in
order to pass the Display Port compliance tests.
Signed-off-by: Martin Peres <martin.peres at linux.intel.com>
---
hw/xfree86/drivers/modesetting/drmmode_display.c | 51 ++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index c1e489e48a..516eb76915 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -2253,6 +2253,10 @@ drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
}
#ifdef CONFIG_UDEV_KMS
+
+#define DRM_MODE_LINK_STATUS_GOOD 0
+#define DRM_MODE_LINK_STATUS_BAD 1
+
static void
drmmode_handle_uevents(int fd, void *closure)
{
@@ -2272,6 +2276,49 @@ drmmode_handle_uevents(int fd, void *closure)
if (!found)
return;
+ /* Try to re-set the mode on all the connectors with a BAD link-state:
+ * This may happen if a link degrades and a new modeset is necessary, using
+ * different link-training parameters. If the kernel found that the current
+ * mode is not achievable anymore, it should have pruned the mode before
+ * sending the hotplug event. Try to re-set the currently-set mode to keep
+ * the display alive, this will fail if the mode has been pruned.
+ * In any case, we will send randr events for the Desktop Environment to
+ * deal with it, if it wants to.
+ */
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ uint32_t con_id = drmmode_output->mode_output->connector_id;
+ drmModeConnectorPtr koutput;
+
+ /* Get an updated view of the properties for the current connector and
+ * look for the link-status property
+ */
+ koutput = drmModeGetConnectorCurrent(drmmode->fd, con_id);
+ for (j = 0; koutput && j < koutput->count_props; j++) {
+ drmModePropertyPtr props;
+ props = drmModeGetProperty(drmmode->fd, koutput->props[j]);
+ if (props && props->flags & DRM_MODE_PROP_ENUM &&
+ !strcmp(props->name, "link-status") &&
+ koutput->prop_values[j] == DRM_MODE_LINK_STATUS_BAD) {
+ xf86CrtcPtr crtc = output->crtc;
+ if (!crtc)
+ continue;
+
+ /* the connector got a link failure, re-set the current mode */
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
+
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "hotplug event: connector %u's link-state is BAD, "
+ "tried resetting the current mode. You may be left"
+ "with a black screen if this fails...\n", con_id);
+ }
+ drmModeFreeProperty(props);
+ }
+ drmModeFreeConnector(koutput);
+ }
+
mode_res = drmModeGetResources(drmmode->fd);
if (!mode_res)
goto out;
@@ -2336,6 +2383,10 @@ out_free_res:
out:
RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
}
+
+#undef DRM_MODE_LINK_STATUS_BAD
+#undef DRM_MODE_LINK_STATUS_GOOD
+
#endif
void
--
2.12.1
More information about the xorg-devel
mailing list