From patchwork Wed Aug 8 21:35:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 1297701 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 084C1DF223 for ; Wed, 8 Aug 2012 21:23:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id ECF9EA0B00 for ; Wed, 8 Aug 2012 14:23:36 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-wg0-f43.google.com (mail-wg0-f43.google.com [74.125.82.43]) by gabe.freedesktop.org (Postfix) with ESMTP id B130F9EF85 for ; Wed, 8 Aug 2012 14:19:15 -0700 (PDT) Received: by wgbdr1 with SMTP id dr1so888933wgb.12 for ; Wed, 08 Aug 2012 14:19:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=UvMTb8r+EpO53105kdaAuJl7cS73ih8v3TCP68ZTl1o=; b=DHSrqVzEDnu3Ms0ppG85YubYALiRGqvvXLTE0EetfbmopxBl1jGGhipjh0uaZbQANa D0aKAbBBqm+OCHh4JQM79fyVwr9U9KRT3YLLu4jfA4Fk4Yfh3jWl8uOJUJmRFW5XdaYT UbZ0zAjnskZ+CcjDDWnRd/wZHR5eVuUzS08xc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=UvMTb8r+EpO53105kdaAuJl7cS73ih8v3TCP68ZTl1o=; b=gm/y7IxabrZ8HtTuJbBMz07X+WsgWxGd3icagfbw/Quvv9Nrog/4yIfxjOTpt8Embr 12KtuehCLsmfIxEm+C3w+BHtvZc0vDTMEHUbIoyzx2aa4Y0Ab5lElHxk1oUuDm96XQ47 ttFcy2FT5VAcGB5RX2E2W4oTliuxJupNa1+lAEPekiTKliNKtMDqlREi7raHXQZhUd27 F9L2n81zLrfROyrPo9/+k57FuRaLsfVbZxwlx/C9yjNUAJWjrNcVGKXyZh0O05xU3Ilb Eyn5lFwCQcVujq9DmQhYYLh4HIRF8g6Rpk2AyFN9DJneCw2Vse074OyTS4zZ/HbrSJHm Y5WQ== Received: by 10.180.14.9 with SMTP id l9mr826597wic.21.1344460754840; Wed, 08 Aug 2012 14:19:14 -0700 (PDT) Received: from hummel.ffwll.local (178-83-130-250.dynamic.hispeed.ch. [178.83.130.250]) by mx.google.com with ESMTPS id o2sm10646321wiz.11.2012.08.08.14.19.13 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 08 Aug 2012 14:19:14 -0700 (PDT) From: Daniel Vetter To: Intel Graphics Development Date: Wed, 8 Aug 2012 23:35:38 +0200 Message-Id: <1344461740-1231-7-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1344461740-1231-1-git-send-email-daniel.vetter@ffwll.ch> References: <1344461740-1231-1-git-send-email-daniel.vetter@ffwll.ch> X-Gm-Message-State: ALoCoQnbIx1EAdFIu/mDLJC6yxET1TrcGGVYTkqRy2ZNvjQfWU9bMUWOdx0XZWjVJHcJfXXZZx23 Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH 6/8] drm/i915: fix up ilk drps/ips locking X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org We change the drps/ips sw/hw state from different callers: Our own irq handler, the external intel-ips module and from process context. Most of these callers don't take any lock at all. Protect everything by making the mchdev_lock irqsave and grabbing it in all relevant callsites. Note that we have to convert a few sleeps in the drps enable/disable code to delays, but alas, I'm not volunteering to restructure the code around a few work items. For paranoia add a spin_locked assert to ironlake_set_drps, too. v2: Move one access inside the lock protection. Caught by the dev_priv->ips mass-rename ... Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 12 +++++- drivers/gpu/drm/i915/intel_pm.c | 83 ++++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3e203da..d15ea50 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -296,14 +296,22 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_helper_hpd_irq_event(dev); } +/* defined intel_pm.c */ +extern spinlock_t mchdev_lock; + static void ironlake_handle_rps_change(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; u32 busy_up, busy_down, max_avg, min_avg; - u8 new_delay = dev_priv->cur_delay; + u8 new_delay; + unsigned long flags; + + spin_lock_irqsave(&mchdev_lock, flags); I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); + new_delay = dev_priv->cur_delay; + I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG); busy_up = I915_READ(RCPREVBSYTUPAVG); busy_down = I915_READ(RCPREVBSYTDNAVG); @@ -326,6 +334,8 @@ static void ironlake_handle_rps_change(struct drm_device *dev) if (ironlake_set_drps(dev, new_delay)) dev_priv->cur_delay = new_delay; + spin_unlock_irqrestore(&mchdev_lock, flags); + return; } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 44d58e7..5f9f93e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2160,11 +2160,28 @@ err_unref: return NULL; } +/** + * Lock protecting IPS related data structures + * - i915_mch_dev + * - dev_priv->max_delay + * - dev_priv->min_delay + * - dev_priv->fmax + * - dev_priv->gpu_busy + * - dev_priv->gfx_power + */ +DEFINE_SPINLOCK(mchdev_lock); + +/* Global for IPS driver to get at the current i915 device. Protected by + * mchdev_lock. */ +static struct drm_i915_private *i915_mch_dev; + bool ironlake_set_drps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; u16 rgvswctl; + assert_spin_locked(&mchdev_lock); + rgvswctl = I915_READ16(MEMSWCTL); if (rgvswctl & MEMCTL_CMD_STS) { DRM_DEBUG("gpu busy, RCS change rejected\n"); @@ -2188,6 +2205,8 @@ static void ironlake_enable_drps(struct drm_device *dev) u32 rgvmodectl = I915_READ(MEMMODECTL); u8 fmax, fmin, fstart, vstart; + spin_lock_irq(&mchdev_lock); + /* Enable temp reporting */ I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN); I915_WRITE16(TSC1, I915_READ(TSC1) | TSE); @@ -2233,9 +2252,9 @@ static void ironlake_enable_drps(struct drm_device *dev) rgvmodectl |= MEMMODE_SWMODE_EN; I915_WRITE(MEMMODECTL, rgvmodectl); - if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) + if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) DRM_ERROR("stuck trying to change perf mode\n"); - msleep(1); + mdelay(1); ironlake_set_drps(dev, fstart); @@ -2244,12 +2263,18 @@ static void ironlake_enable_drps(struct drm_device *dev) dev_priv->last_time1 = jiffies_to_msecs(jiffies); dev_priv->last_count2 = I915_READ(0x112f4); getrawmonotonic(&dev_priv->last_time2); + + spin_unlock_irq(&mchdev_lock); } static void ironlake_disable_drps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u16 rgvswctl = I915_READ16(MEMSWCTL); + u16 rgvswctl; + + spin_lock_irq(&mchdev_lock); + + rgvswctl = I915_READ16(MEMSWCTL); /* Ack interrupts, disable EFC interrupt */ I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); @@ -2260,11 +2285,12 @@ static void ironlake_disable_drps(struct drm_device *dev) /* Go back to the starting frequency */ ironlake_set_drps(dev, dev_priv->fstart); - msleep(1); + mdelay(1); rgvswctl |= MEMCTL_CMD_STS; I915_WRITE(MEMSWCTL, rgvswctl); - msleep(1); + mdelay(1); + spin_unlock_irq(&mchdev_lock); } /* There's a funny hw issue where the hw returns all 0 when reading from @@ -2713,21 +2739,6 @@ static const struct cparams { { 0, 800, 231, 23784 }, }; -/** - * Lock protecting IPS related data structures - * - i915_mch_dev - * - dev_priv->max_delay - * - dev_priv->min_delay - * - dev_priv->fmax - * - dev_priv->gpu_busy - * - dev_priv->gfx_power - */ -static DEFINE_SPINLOCK(mchdev_lock); - -/* Global for IPS driver to get at the current i915 device. Protected by - * mchdev_lock. */ -static struct drm_i915_private *i915_mch_dev; - unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) { u64 total_count, diff, ret; @@ -2978,11 +2989,11 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv) if (dev_priv->info->gen != 5) return; - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); __i915_update_gfx_val(dev_priv); - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); } unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) @@ -3033,7 +3044,7 @@ unsigned long i915_read_mch_val(void) struct drm_i915_private *dev_priv; unsigned long chipset_val, graphics_val, ret = 0; - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); if (!i915_mch_dev) goto out_unlock; dev_priv = i915_mch_dev; @@ -3044,7 +3055,7 @@ unsigned long i915_read_mch_val(void) ret = chipset_val + graphics_val; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); return ret; } @@ -3060,7 +3071,7 @@ bool i915_gpu_raise(void) struct drm_i915_private *dev_priv; bool ret = true; - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); if (!i915_mch_dev) { ret = false; goto out_unlock; @@ -3071,7 +3082,7 @@ bool i915_gpu_raise(void) dev_priv->max_delay--; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); return ret; } @@ -3088,7 +3099,7 @@ bool i915_gpu_lower(void) struct drm_i915_private *dev_priv; bool ret = true; - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); if (!i915_mch_dev) { ret = false; goto out_unlock; @@ -3099,7 +3110,7 @@ bool i915_gpu_lower(void) dev_priv->max_delay++; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); return ret; } @@ -3117,7 +3128,7 @@ bool i915_gpu_busy(void) bool ret = false; int i; - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); if (!i915_mch_dev) goto out_unlock; dev_priv = i915_mch_dev; @@ -3126,7 +3137,7 @@ bool i915_gpu_busy(void) ret |= !list_empty(&ring->request_list); out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); return ret; } @@ -3143,7 +3154,7 @@ bool i915_gpu_turbo_disable(void) struct drm_i915_private *dev_priv; bool ret = true; - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); if (!i915_mch_dev) { ret = false; goto out_unlock; @@ -3156,7 +3167,7 @@ bool i915_gpu_turbo_disable(void) ret = false; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); return ret; } @@ -3184,18 +3195,18 @@ ips_ping_for_i915_load(void) void intel_gpu_ips_init(struct drm_i915_private *dev_priv) { - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); i915_mch_dev = dev_priv; - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); ips_ping_for_i915_load(); } void intel_gpu_ips_teardown(void) { - spin_lock(&mchdev_lock); + spin_lock_irq(&mchdev_lock); i915_mch_dev = NULL; - spin_unlock(&mchdev_lock); + spin_unlock_irq(&mchdev_lock); } static void intel_init_emon(struct drm_device *dev) {