Commit e63fea163319d9784abc0c82aeaef451cc80116e
Committed by
Greg Kroah-Hartman
1 parent
f1d5aa4663
drm: fix fb-helper vs MST dangling connector ptrs (v2)
commit 2148f18fdb45f31ca269a7787fbc24053cd42e70 upstream. 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 Signed-off-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 30 additions and 0 deletions Side-by-side Diff
drivers/gpu/drm/drm_fb_helper.c
... | ... | @@ -145,6 +145,31 @@ |
145 | 145 | } |
146 | 146 | EXPORT_SYMBOL(drm_fb_helper_add_one_connector); |
147 | 147 | |
148 | +static void remove_from_modeset(struct drm_mode_set *set, | |
149 | + struct drm_connector *connector) | |
150 | +{ | |
151 | + int i, j; | |
152 | + | |
153 | + for (i = 0; i < set->num_connectors; i++) { | |
154 | + if (set->connectors[i] == connector) | |
155 | + break; | |
156 | + } | |
157 | + | |
158 | + if (i == set->num_connectors) | |
159 | + return; | |
160 | + | |
161 | + for (j = i + 1; j < set->num_connectors; j++) { | |
162 | + set->connectors[j - 1] = set->connectors[j]; | |
163 | + } | |
164 | + set->num_connectors--; | |
165 | + | |
166 | + /* because i915 is pissy about this.. | |
167 | + * TODO maybe need to makes sure we set it back to !=NULL somewhere? | |
168 | + */ | |
169 | + if (set->num_connectors == 0) | |
170 | + set->fb = NULL; | |
171 | +} | |
172 | + | |
148 | 173 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, |
149 | 174 | struct drm_connector *connector) |
150 | 175 | { |
... | ... | @@ -167,6 +192,11 @@ |
167 | 192 | } |
168 | 193 | fb_helper->connector_count--; |
169 | 194 | kfree(fb_helper_connector); |
195 | + | |
196 | + /* also cleanup dangling references to the connector: */ | |
197 | + for (i = 0; i < fb_helper->crtc_count; i++) | |
198 | + remove_from_modeset(&fb_helper->crtc_info[i].mode_set, connector); | |
199 | + | |
170 | 200 | return 0; |
171 | 201 | } |
172 | 202 | EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); |