[Intel-gfx] [PATCH 4/9] drm/i915: Reduce duplicated forcewake logic
Chris Wilson
chris at chris-wilson.co.uk
Tue Dec 16 08:35:59 PST 2014
On Tue, Dec 16, 2014 at 05:20:55PM +0200, Mika Kuoppala wrote:
> +void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
> {
> - if (FORCEWAKE_RENDER & fw_engine) {
> - WARN_ON(dev_priv->uncore.fw_rendercount == 0);
> - if (--dev_priv->uncore.fw_rendercount == 0)
> - dev_priv->uncore.funcs.force_wake_put(dev_priv,
> - FORCEWAKE_RENDER);
> - }
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + unsigned long irqflags, fw = 0;
> + struct intel_uncore_forcewake_domain *domain;
> + int id, active_domains, retry_count = 100;
>
> - if (FORCEWAKE_MEDIA & fw_engine) {
> - WARN_ON(dev_priv->uncore.fw_mediacount == 0);
> - if (--dev_priv->uncore.fw_mediacount == 0)
> - dev_priv->uncore.funcs.force_wake_put(dev_priv,
> - FORCEWAKE_MEDIA);
> - }
> + /* Hold uncore.lock across reset to prevent any register access
> + * with forcewake not set correctly. Wait until all pending
> + * timers are run before holding.
> + */
> + while (1) {
> + active_domains = 0;
>
> - if (FORCEWAKE_BLITTER & fw_engine) {
> - WARN_ON(dev_priv->uncore.fw_blittercount == 0);
> - if (--dev_priv->uncore.fw_blittercount == 0)
> - dev_priv->uncore.funcs.force_wake_put(dev_priv,
> - FORCEWAKE_BLITTER);
> - }
> -}
> + for_each_fw_domain(domain, dev_priv, id)
> + del_timer_sync(&domain->timer);
>
> -static void gen6_force_wake_timer(unsigned long arg)
> -{
> - struct drm_i915_private *dev_priv = (void *)arg;
> - unsigned long irqflags;
> + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
>
> - assert_device_not_suspended(dev_priv);
> + for_each_fw_domain(domain, dev_priv, id) {
> + if (timer_pending(&domain->timer))
> + active_domains |= (1 << id);
> + }
>
> - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> - WARN_ON(!dev_priv->uncore.forcewake_count);
> + if (active_domains == 0 || --retry_count == 0)
> + break;
>
> - if (--dev_priv->uncore.forcewake_count == 0)
> - dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
> - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> + }
One minor thing that occurs to me is that we should put a cond_resched()
here to encourage the timers to clear.
Also:
if (active_domains == 0)
break;
if (--retry_count == 0) {
DRM_ERROR("Timed out waiting for forcewake timers to finish\n");
break;
}
would be prudent in case we hit the race condition and do go ahead in
the confused state.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
More information about the Intel-gfx
mailing list