diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 09:52:16 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-08 09:52:16 -0700 |
| commit | e9f37d3a8d126e73f5737ef548cdf6f618e295e4 (patch) | |
| tree | 831eb4952637828a7bbafa361185e0ca57aa86ed /drivers/gpu/drm/msm/msm_gpu.c | |
| parent | 5fb6b953bb7aa86a9c8ea760934982cedc45c52b (diff) | |
| parent | c39b06951f1dc2e384650288676c5b7dcc0ec92c (diff) | |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"Highlights:
- drm:
Generic display port aux features, primary plane support, drm
master management fixes, logging cleanups, enforced locking checks
(instead of docs), documentation improvements, minor number
handling cleanup, pseudofs for shared inodes.
- ttm:
add ability to allocate from both ends
- i915:
broadwell features, power domain and runtime pm, per-process
address space infrastructure (not enabled)
- msm:
power management, hdmi audio support
- nouveau:
ongoing GPU fault recovery, initial maxwell support, random fixes
- exynos:
refactored driver to clean up a lot of abstraction, DP support
moved into drm, LVDS bridge support added, parallel panel support
- gma500:
SGX MMU support, SGX irq handling, asle irq work fixes
- radeon:
video engine bringup, ring handling fixes, use dp aux helpers
- vmwgfx:
add rendernode support"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (849 commits)
DRM: armada: fix corruption while loading cursors
drm/dp_helper: don't return EPROTO for defers (v2)
drm/bridge: export ptn3460_init function
drm/exynos: remove MODULE_DEVICE_TABLE definitions
ARM: dts: exynos4412-trats2: enable exynos/fimd node
ARM: dts: exynos4210-trats: enable exynos/fimd node
ARM: dts: exynos4412-trats2: add panel node
ARM: dts: exynos4210-trats: add panel node
ARM: dts: exynos4: add MIPI DSI Master node
drm/panel: add S6E8AA0 driver
ARM: dts: exynos4210-universal_c210: add proper panel node
drm/panel: add ld9040 driver
panel/ld9040: add DT bindings
panel/s6e8aa0: add DT bindings
drm/exynos: add DSIM driver
exynos/dsim: add DT bindings
drm/exynos: disallow fbdev initialization if no device is connected
drm/mipi_dsi: create dsi devices only for nodes with reg property
drm/mipi_dsi: add flags to DSI messages
Skip intel_crt_init for Dell XPS 8700
...
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gpu.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 0cfe3f426ee4..3e667ca1f2b9 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -154,9 +154,18 @@ static int disable_axi(struct msm_gpu *gpu) int msm_gpu_pm_resume(struct msm_gpu *gpu) { + struct drm_device *dev = gpu->dev; int ret; - DBG("%s", gpu->name); + DBG("%s: active_cnt=%d", gpu->name, gpu->active_cnt); + + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + + if (gpu->active_cnt++ > 0) + return 0; + + if (WARN_ON(gpu->active_cnt <= 0)) + return -EINVAL; ret = enable_pwrrail(gpu); if (ret) @@ -175,9 +184,18 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu) int msm_gpu_pm_suspend(struct msm_gpu *gpu) { + struct drm_device *dev = gpu->dev; int ret; - DBG("%s", gpu->name); + DBG("%s: active_cnt=%d", gpu->name, gpu->active_cnt); + + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + + if (--gpu->active_cnt > 0) + return 0; + + if (WARN_ON(gpu->active_cnt < 0)) + return -EINVAL; ret = disable_axi(gpu); if (ret) @@ -195,6 +213,55 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu) } /* + * Inactivity detection (for suspend): + */ + +static void inactive_worker(struct work_struct *work) +{ + struct msm_gpu *gpu = container_of(work, struct msm_gpu, inactive_work); + struct drm_device *dev = gpu->dev; + + if (gpu->inactive) + return; + + DBG("%s: inactive!\n", gpu->name); + mutex_lock(&dev->struct_mutex); + if (!(msm_gpu_active(gpu) || gpu->inactive)) { + disable_axi(gpu); + disable_clk(gpu); + gpu->inactive = true; + } + mutex_unlock(&dev->struct_mutex); +} + +static void inactive_handler(unsigned long data) +{ + struct msm_gpu *gpu = (struct msm_gpu *)data; + struct msm_drm_private *priv = gpu->dev->dev_private; + + queue_work(priv->wq, &gpu->inactive_work); +} + +/* cancel inactive timer and make sure we are awake: */ +static void inactive_cancel(struct msm_gpu *gpu) +{ + DBG("%s", gpu->name); + del_timer(&gpu->inactive_timer); + if (gpu->inactive) { + enable_clk(gpu); + enable_axi(gpu); + gpu->inactive = false; + } +} + +static void inactive_start(struct msm_gpu *gpu) +{ + DBG("%s", gpu->name); + mod_timer(&gpu->inactive_timer, + round_jiffies_up(jiffies + DRM_MSM_INACTIVE_JIFFIES)); +} + +/* * Hangcheck detection for locked gpu: */ @@ -206,7 +273,10 @@ static void recover_worker(struct work_struct *work) dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name); mutex_lock(&dev->struct_mutex); - gpu->funcs->recover(gpu); + if (msm_gpu_active(gpu)) { + inactive_cancel(gpu); + gpu->funcs->recover(gpu); + } mutex_unlock(&dev->struct_mutex); msm_gpu_retire(gpu); @@ -281,6 +351,9 @@ static void retire_worker(struct work_struct *work) } mutex_unlock(&dev->struct_mutex); + + if (!msm_gpu_active(gpu)) + inactive_start(gpu); } /* call from irq handler to schedule work to retire bo's */ @@ -302,6 +375,8 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, gpu->submitted_fence = submit->fence; + inactive_cancel(gpu); + ret = gpu->funcs->submit(gpu, submit, ctx); priv->lastctx = ctx; @@ -357,11 +432,15 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->dev = drm; gpu->funcs = funcs; gpu->name = name; + gpu->inactive = true; INIT_LIST_HEAD(&gpu->active_list); INIT_WORK(&gpu->retire_work, retire_worker); + INIT_WORK(&gpu->inactive_work, inactive_worker); INIT_WORK(&gpu->recover_work, recover_worker); + setup_timer(&gpu->inactive_timer, inactive_handler, + (unsigned long)gpu); setup_timer(&gpu->hangcheck_timer, hangcheck_handler, (unsigned long)gpu); |
