History

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

Rob Clark committed 11 years ago

Commit 2148f181 parent 1c999c41 file · +30 −0Browse files

Unified · Split

drivers/gpu/drm/drm_fb_helper.c+30−0
@@ -145,6 +145,31 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ · 144 unmodified lines
145145 }
146146 EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
147147
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+
148173 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
149174 struct drm_connector *connector)
150175 {
@@ -167,6 +192,11 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, · 16 unmodified lines
167192 }
168193 fb_helper->connector_count--;
169194 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+
170200 return 0;
171201 }
172202 EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);