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
Unified · Split
| @@ -145,6 +145,31 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ · 144 unmodified lines | ||
| 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 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, · 16 unmodified lines | ||
| 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); |