[PATCH] drm/i915: Convert the forcewake worker into a timer func

Chris Wilson
2014-02-28T09:02:44Z

We don't want to suffer scheduling delay when turning off the GPU after
waking it up to touch registers. Ideally, we only want to keep the GPU
awake for the register access sequence, with a single forcewake dance on
the first access and release immediately after the last. We set a timer
on the first access so that we only dance once and on the next scheduler
tick, we drop the forcewake again.

This moves the cleanup routine from the common i915 workqueue to a timer
func so that we don't anger powertop, and drop the forcewake again
quicker.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ben Widawsky <ben@bwidawsk.net>
---
drivers/gpu/drm/i915/i915_drv.h | 2 +-
drivers/gpu/drm/i915/intel_uncore.c | 15 ++++++---------
2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eb31c45..9416b03 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -508,7 +508,7 @@ struct intel_uncore {
unsigned fw_rendercount;
unsigned fw_mediacount;

- struct delayed_work force_wake_work;
+ struct timer_list force_wake_timer;
};

#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index c628414..140a9f0 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -289,10 +289,8 @@ void vlv_force_wake_put(struct drm_i915_private *dev_priv,
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}

-static void gen6_force_wake_work(struct work_struct *work)
+static void gen6_force_wake_timer(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv =
- container_of(work, typeof(*dev_priv), uncore.force_wake_work.work);
unsigned long irqflags;

spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
@@ -405,9 +403,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (--dev_priv->uncore.forcewake_count == 0) {
dev_priv->uncore.forcewake_count++;
- mod_delayed_work(dev_priv->wq,
- &dev_priv->uncore.force_wake_work,
- 1);
+ mod_timer_pinned(&dev_priv->uncore.force_wake_timer,
+ jiffies + 1);
}
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);

@@ -681,8 +678,8 @@ void intel_uncore_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;

- INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work,
- gen6_force_wake_work);
+ setup_timer(&dev_priv->uncore.force_wake_timer,
+ gen6_force_wake_timer, (unsigned long)dev_priv);

if (IS_VALLEYVIEW(dev)) {
dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
@@ -794,7 +791,7 @@ void intel_uncore_fini(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;

- flush_delayed_work(&dev_priv->uncore.force_wake_work);
+ del_timer_sync(&dev_priv->uncore.force_wake_timer);

/* Paranoia: make sure we have disabled everything before we exit. */
intel_uncore_sanitize(dev);
--
1.7.9.5