On Fri, Jan 26, 2018 at 10:39:39AM +0200, Paul Irofti wrote:
> Hi,
>
> I have a T460 Lenovo model that, when connected to an external monitor
> via a docking station, freezes the machine and produces the "snowflake"
> effect on the monitor. Last time I saw this was in 2010 when working on
> suspend-resume :)
>
> After a month of fighting to fix the issue I came up with this drm
> update. The code bellow includes commits taken directly from the Linux
> kernel, no local modifications.
>
> Notable changes are:
> - improved DP link training by renegotiating with different rates and
> lane values
> - caching of source, sink and common rates
> - max link rate limiting and related calculation changes
> - switch to long and short pulse interrupts
>
> I have been running succesfully with this on both the affected model and
> on the x250 that I used with a dozen monitors, projectors and the like
> at uni. No problems so far, but would appreciate test repaorts on a
> wider range of hardware.
>
> Comments? Mistakes? How should we proceed to get this in the tree?
For the archives, here is a diff that fixes a locking warning with the
earlier patch. So you have to apply it after the former one.
diff --git sys/dev/pci/drm/drm_probe_helper.c sys/dev/pci/drm/drm_probe_helper.c
index 936c0c1d3a7..84a0e585d32 100644
--- sys/dev/pci/drm/drm_probe_helper.c
+++ sys/dev/pci/drm/drm_probe_helper.c
@@ -136,15 +136,27 @@ static int
drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
struct drm_display_mode *mode;
const struct drm_connector_helper_funcs *connector_funcs =
connector->helper_private;
- int count = 0;
+ int count = 0, ret;
int mode_flags = 0;
bool verbose_prune = true;
enum drm_connector_status old_status;
+ struct drm_modeset_acquire_ctx ctx;
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
connector->name);
+
+ drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ } else
+ WARN_ON(ret < 0);
+
/* set all modes to the unverified state */
list_for_each_entry(mode, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
@@ -248,6 +260,9 @@ static int
drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
prune:
drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+
if (list_empty(&connector->modes))
return 0;