aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-12-17 06:13:23 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-20 16:17:17 -0500
commit20c60c35de3285222b3476c3445c66bedf0c449c (patch)
tree96993a1477448059651019185c34460d6ea7a245
parent5d7a951537927555fa1286a338e1b91c3b8b7445 (diff)
drm/fb_helper: check whether fbcon is bound
We need to make sure that the fbcon is still bound when touching the hw, since otherwise we might corrupt the modeset state of kms clients. X mostly works around that with VT switching and setting the VT into raw mode, which disables most fbcon events. Raw kms test programs though don't do that dance, and in the future we might want to aim to abolish CONFIG_VT anyway. So improve preventive measures a bit. To do so, extract the existing logic for handling hotplug events (which X can't block with the current set of tricks) and reuse it for the fbdev blanking helper. Long-term we really need to either scrap this all and only have a OOPS console, or come up with a saner model for device ownership sharing between fbdev/fbcon and kms userspace. Reviewed-by: Rob Clark <rob@ti.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index be0f2d65db3a..0c6e25e979dd 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -305,6 +305,24 @@ void drm_fb_helper_restore(void)
305} 305}
306EXPORT_SYMBOL(drm_fb_helper_restore); 306EXPORT_SYMBOL(drm_fb_helper_restore);
307 307
308static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
309{
310 struct drm_device *dev = fb_helper->dev;
311 struct drm_crtc *crtc;
312 int bound = 0, crtcs_bound = 0;
313
314 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
315 if (crtc->fb)
316 crtcs_bound++;
317 if (crtc->fb == fb_helper->fb)
318 bound++;
319 }
320
321 if (bound < crtcs_bound)
322 return false;
323 return true;
324}
325
308#ifdef CONFIG_MAGIC_SYSRQ 326#ifdef CONFIG_MAGIC_SYSRQ
309static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) 327static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
310{ 328{
@@ -338,6 +356,11 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
338 * For each CRTC in this fb, turn the connectors on/off. 356 * For each CRTC in this fb, turn the connectors on/off.
339 */ 357 */
340 drm_modeset_lock_all(dev); 358 drm_modeset_lock_all(dev);
359 if (!drm_fb_helper_is_bound(fb_helper)) {
360 drm_modeset_unlock_all(dev);
361 return;
362 }
363
341 for (i = 0; i < fb_helper->crtc_count; i++) { 364 for (i = 0; i < fb_helper->crtc_count; i++) {
342 crtc = fb_helper->crtc_info[i].mode_set.crtc; 365 crtc = fb_helper->crtc_info[i].mode_set.crtc;
343 366
@@ -702,6 +725,11 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
702 int i; 725 int i;
703 726
704 drm_modeset_lock_all(dev); 727 drm_modeset_lock_all(dev);
728 if (!drm_fb_helper_is_bound(fb_helper)) {
729 drm_modeset_unlock_all(dev);
730 return -EBUSY;
731 }
732
705 for (i = 0; i < fb_helper->crtc_count; i++) { 733 for (i = 0; i < fb_helper->crtc_count; i++) {
706 crtc = fb_helper->crtc_info[i].mode_set.crtc; 734 crtc = fb_helper->crtc_info[i].mode_set.crtc;
707 735
@@ -1369,21 +1397,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1369 struct drm_device *dev = fb_helper->dev; 1397 struct drm_device *dev = fb_helper->dev;
1370 int count = 0; 1398 int count = 0;
1371 u32 max_width, max_height, bpp_sel; 1399 u32 max_width, max_height, bpp_sel;
1372 int bound = 0, crtcs_bound = 0;
1373 struct drm_crtc *crtc;
1374 1400
1375 if (!fb_helper->fb) 1401 if (!fb_helper->fb)
1376 return 0; 1402 return 0;
1377 1403
1378 drm_modeset_lock_all(dev); 1404 drm_modeset_lock_all(dev);
1379 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1405 if (!drm_fb_helper_is_bound(fb_helper)) {
1380 if (crtc->fb)
1381 crtcs_bound++;
1382 if (crtc->fb == fb_helper->fb)
1383 bound++;
1384 }
1385
1386 if (bound < crtcs_bound) {
1387 fb_helper->delayed_hotplug = true; 1406 fb_helper->delayed_hotplug = true;
1388 drm_modeset_unlock_all(dev); 1407 drm_modeset_unlock_all(dev);
1389 return 0; 1408 return 0;