Commit 2148f18f authored by Rob Clark's avatar Rob Clark Committed by Dave Airlie

drm: fix fb-helper vs MST dangling connector ptrs (v2)

VT switch back/forth from console to xserver (for example) has potential
to go horribly wrong if a dynamic DP MST connector ends up in the saved
modeset that is restored when switching back to fbcon.

When removing a dynamic connector, don't forget to clean up the saved
state.

v1: original
v2: null out set->fb if no more connectors to avoid making i915 cranky

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1184968
Cc: stable@vger.kernel.org #v3.17+
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 1c999c47
...@@ -145,6 +145,31 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ ...@@ -145,6 +145,31 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
} }
EXPORT_SYMBOL(drm_fb_helper_add_one_connector); EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
static void remove_from_modeset(struct drm_mode_set *set,
struct drm_connector *connector)
{
int i, j;
for (i = 0; i < set->num_connectors; i++) {
if (set->connectors[i] == connector)
break;
}
if (i == set->num_connectors)
return;
for (j = i + 1; j < set->num_connectors; j++) {
set->connectors[j - 1] = set->connectors[j];
}
set->num_connectors--;
/* because i915 is pissy about this..
* TODO maybe need to makes sure we set it back to !=NULL somewhere?
*/
if (set->num_connectors == 0)
set->fb = NULL;
}
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector) struct drm_connector *connector)
{ {
...@@ -167,6 +192,11 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, ...@@ -167,6 +192,11 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
} }
fb_helper->connector_count--; fb_helper->connector_count--;
kfree(fb_helper_connector); kfree(fb_helper_connector);
/* also cleanup dangling references to the connector: */
for (i = 0; i < fb_helper->crtc_count; i++)
remove_from_modeset(&fb_helper->crtc_info[i].mode_set, connector);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment