Since the suspend_work is entirely internal to intel_fbdev.c, move it from the top level drm_i915_private and into struct intel_fbdev. This requires splitting the internal interface for the suspend worker from the external interface used by the higher layers to initiate suspend. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_drv.h | 5 +- drivers/gpu/drm/i915/intel_fbdev.c | 117 ++++++++++++++++++++----------------- 4 files changed, 68 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 020a31c5e2bb..100d0d92b1e6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -634,7 +634,7 @@ static int i915_drm_suspend(struct drm_device *dev) intel_uncore_forcewake_reset(dev, false); intel_opregion_fini(dev); - intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true); + intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED); dev_priv->suspend_count++; @@ -784,7 +784,7 @@ static int i915_drm_resume(struct drm_device *dev) intel_opregion_init(dev); - intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false); + intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING); mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_DONE; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 820c91f551ba..973a602c5077 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1880,7 +1880,6 @@ struct drm_i915_private { #ifdef CONFIG_DRM_FBDEV_EMULATION /* list of fbdev register on this device */ struct intel_fbdev *fbdev; - struct work_struct fbdev_suspend_work; #endif struct drm_property *broadcast_rgb_property; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6ac46d921cde..00b6c60c1cb8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -158,6 +158,7 @@ struct intel_framebuffer { struct intel_fbdev { struct drm_fb_helper helper; struct intel_framebuffer *fb; + struct work_struct suspend_work; int preferred_bpp; }; @@ -1335,7 +1336,7 @@ void intel_dvo_init(struct drm_device *dev); extern int intel_fbdev_init(struct drm_device *dev); extern void intel_fbdev_initial_config_async(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev); -extern void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous); +extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); extern void intel_fbdev_output_poll_changed(struct drm_device *dev); extern void intel_fbdev_restore_mode(struct drm_device *dev); #else @@ -1352,7 +1353,7 @@ static inline void intel_fbdev_fini(struct drm_device *dev) { } -static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) +static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state) { } diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 5d4be71bdf22..66bb79613660 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -534,8 +534,7 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { .fb_probe = intelfb_create, }; -static void intel_fbdev_destroy(struct drm_device *dev, - struct intel_fbdev *ifbdev) +static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) { /* We rely on the object-free to release the VMA pinning for * the info->screen_base mmaping. Leaking the VMA is simpler than @@ -681,13 +680,56 @@ out: return false; } +static void __intel_fbdev_set_suspend(struct intel_fbdev *ifbdev, + int state, bool synchronous) +{ + if (synchronous) { + /* Flush any pending work to turn the console on, and then + * wait to turn it off. It must be synchronous as we are + * about to suspend or unload the driver. + * + * Note that from within the work-handler, we cannot flush + * ourselves, so only flush outstanding work upon suspend! + */ + if (state != FBINFO_STATE_RUNNING) + flush_work(&ifbdev->suspend_work); + console_lock(); + } else { + /* + * The console lock can be pretty contented on resume due + * to all the printk activity. Try to keep it out of the hot + * path of resume if possible. + */ + WARN_ON(state != FBINFO_STATE_RUNNING); + if (!console_trylock()) { + /* Don't block our own workqueue as this can + * be run in parallel with other i915.ko tasks. + */ + schedule_work(&ifbdev->suspend_work); + return; + } + } + + /* On resume from hibernation: If the object is shmemfs backed, it has + * been restored from swap. If the object is stolen however, it will be + * full of whatever garbage was left in there. + */ + if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen) { + struct fb_info *info = ifbdev->helper.fbdev; + memset_io(info->screen_base, 0, info->screen_size); + } + + drm_fb_helper_set_suspend(&ifbdev->helper, state); + console_unlock(); +} + static void intel_fbdev_suspend_worker(struct work_struct *work) { - intel_fbdev_set_suspend(container_of(work, - struct drm_i915_private, - fbdev_suspend_work)->dev, - FBINFO_STATE_RUNNING, - true); + __intel_fbdev_set_suspend(container_of(work, + struct intel_fbdev, + suspend_work), + FBINFO_STATE_RUNNING, + true); } int intel_fbdev_init(struct drm_device *dev) @@ -716,9 +758,9 @@ int intel_fbdev_init(struct drm_device *dev) } ifbdev->helper.atomic = true; + INIT_WORK(&ifbdev->suspend_work, intel_fbdev_suspend_worker); dev_priv->fbdev = ifbdev; - INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker); drm_fb_helper_single_add_all_connectors(&ifbdev->helper); @@ -743,17 +785,21 @@ void intel_fbdev_initial_config_async(struct drm_device *dev) void intel_fbdev_fini(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - if (!dev_priv->fbdev) + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_fbdev *ifbdev; + + ifbdev = dev_priv->fbdev; + if (ifbdev == NULL) return; - flush_work(&dev_priv->fbdev_suspend_work); + dev_priv->fbdev = NULL; if (!current_is_async()) async_synchronize_full(); - intel_fbdev_destroy(dev, dev_priv->fbdev); - kfree(dev_priv->fbdev); - dev_priv->fbdev = NULL; + flush_work(&ifbdev->suspend_work); + + intel_fbdev_destroy(ifbdev); + kfree(ifbdev); } static struct intel_fbdev *intel_fbdev_get(struct drm_device *dev) @@ -788,53 +834,16 @@ static struct intel_fbdev *intel_fbdev_get_if_active(struct drm_device *dev) return ifbdev; } -void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) +void intel_fbdev_set_suspend(struct drm_device *dev, int state) { - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_fbdev *ifbdev; ifbdev = intel_fbdev_get(dev); if (ifbdev == NULL) return; - if (synchronous) { - /* Flush any pending work to turn the console on, and then - * wait to turn it off. It must be synchronous as we are - * about to suspend or unload the driver. - * - * Note that from within the work-handler, we cannot flush - * ourselves, so only flush outstanding work upon suspend! - */ - if (state != FBINFO_STATE_RUNNING) - flush_work(&dev_priv->fbdev_suspend_work); - console_lock(); - } else { - /* - * The console lock can be pretty contented on resume due - * to all the printk activity. Try to keep it out of the hot - * path of resume if possible. - */ - WARN_ON(state != FBINFO_STATE_RUNNING); - if (!console_trylock()) { - /* Don't block our own workqueue as this can - * be run in parallel with other i915.ko tasks. - */ - schedule_work(&dev_priv->fbdev_suspend_work); - return; - } - } - - /* On resume from hibernation: If the object is shmemfs backed, it has - * been restored from swap. If the object is stolen however, it will be - * full of whatever garbage was left in there. - */ - if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen) { - struct fb_info *info = ifbdev->helper.fbdev; - memset_io(info->screen_base, 0, info->screen_size); - } - - drm_fb_helper_set_suspend(&ifbdev->helper, state); - console_unlock(); + __intel_fbdev_set_suspend(ifbdev, state, + state != FBINFO_STATE_RUNNING); } void intel_fbdev_output_poll_changed(struct drm_device *dev) -- 2.8.0.rc3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx