diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 7 |
3 files changed, 34 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e67080729746..530cf90d13b0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1329,6 +1329,8 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
1329 | 1329 | ||
1330 | intel_modeset_gem_init(dev); | 1330 | intel_modeset_gem_init(dev); |
1331 | 1331 | ||
1332 | INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); | ||
1333 | |||
1332 | ret = drm_irq_install(dev); | 1334 | ret = drm_irq_install(dev); |
1333 | if (ret) | 1335 | if (ret) |
1334 | goto cleanup_gem; | 1336 | goto cleanup_gem; |
@@ -1723,6 +1725,7 @@ int i915_driver_unload(struct drm_device *dev) | |||
1723 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1725 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
1724 | intel_fbdev_fini(dev); | 1726 | intel_fbdev_fini(dev); |
1725 | intel_modeset_cleanup(dev); | 1727 | intel_modeset_cleanup(dev); |
1728 | cancel_work_sync(&dev_priv->console_resume_work); | ||
1726 | 1729 | ||
1727 | /* | 1730 | /* |
1728 | * free the memory space allocated for the child device | 1731 | * free the memory space allocated for the child device |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a08e9cafb7f2..cfd8920537c5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -523,6 +523,18 @@ int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
526 | void intel_console_resume(struct work_struct *work) | ||
527 | { | ||
528 | struct drm_i915_private *dev_priv = | ||
529 | container_of(work, struct drm_i915_private, | ||
530 | console_resume_work); | ||
531 | struct drm_device *dev = dev_priv->dev; | ||
532 | |||
533 | console_lock(); | ||
534 | intel_fbdev_set_suspend(dev, 0); | ||
535 | console_unlock(); | ||
536 | } | ||
537 | |||
526 | static int i915_drm_thaw(struct drm_device *dev) | 538 | static int i915_drm_thaw(struct drm_device *dev) |
527 | { | 539 | { |
528 | struct drm_i915_private *dev_priv = dev->dev_private; | 540 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -559,9 +571,18 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
559 | 571 | ||
560 | dev_priv->modeset_on_lid = 0; | 572 | dev_priv->modeset_on_lid = 0; |
561 | 573 | ||
562 | console_lock(); | 574 | /* |
563 | intel_fbdev_set_suspend(dev, 0); | 575 | * The console lock can be pretty contented on resume due |
564 | console_unlock(); | 576 | * to all the printk activity. Try to keep it out of the hot |
577 | * path of resume if possible. | ||
578 | */ | ||
579 | if (console_trylock()) { | ||
580 | intel_fbdev_set_suspend(dev, 0); | ||
581 | console_unlock(); | ||
582 | } else { | ||
583 | schedule_work(&dev_priv->console_resume_work); | ||
584 | } | ||
585 | |||
565 | return error; | 586 | return error; |
566 | } | 587 | } |
567 | 588 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 135b9db55279..f8fa63deb92c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -887,6 +887,12 @@ typedef struct drm_i915_private { | |||
887 | /* list of fbdev register on this device */ | 887 | /* list of fbdev register on this device */ |
888 | struct intel_fbdev *fbdev; | 888 | struct intel_fbdev *fbdev; |
889 | 889 | ||
890 | /* | ||
891 | * The console may be contended at resume, but we don't | ||
892 | * want it to block on it. | ||
893 | */ | ||
894 | struct work_struct console_resume_work; | ||
895 | |||
890 | struct backlight_device *backlight; | 896 | struct backlight_device *backlight; |
891 | 897 | ||
892 | struct drm_property *broadcast_rgb_property; | 898 | struct drm_property *broadcast_rgb_property; |
@@ -1273,6 +1279,7 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); | |||
1273 | extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); | 1279 | extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); |
1274 | extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); | 1280 | extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); |
1275 | 1281 | ||
1282 | extern void intel_console_resume(struct work_struct *work); | ||
1276 | 1283 | ||
1277 | /* i915_irq.c */ | 1284 | /* i915_irq.c */ |
1278 | void i915_hangcheck_elapsed(unsigned long data); | 1285 | void i915_hangcheck_elapsed(unsigned long data); |