From patchwork Thu Aug 9 14:46:01 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 1301051 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 4C67E3FD8C for ; Thu, 9 Aug 2012 14:29:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 31F90A0E04 for ; Thu, 9 Aug 2012 07:29:26 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-we0-f177.google.com (mail-we0-f177.google.com [74.125.82.177]) by gabe.freedesktop.org (Postfix) with ESMTP id E62D49E936 for ; Thu, 9 Aug 2012 07:29:11 -0700 (PDT) Received: by weyr3 with SMTP id r3so355136wey.36 for ; Thu, 09 Aug 2012 07:29:11 -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=FY7uuo0gElc2AJ2hSdaPdZiP2aPDDBru366ABF1LsdE=; b=TKMCn4V/EnRjclQACZVgbB1/8AKlVs0sm2K4vfwOiqWjVEWh3sXGY61Uu1kjjvV8++ 9hypxBR59qDIUGBQq89ocVnzcx6iQQHQX4nmy0gJArOTbOMKbqSYVlthMyj2oUnLR5Bf VyRo+0ZxBrvljuyeOPO2nrCCXec7sLEK+WihI= 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=FY7uuo0gElc2AJ2hSdaPdZiP2aPDDBru366ABF1LsdE=; b=YXT0czqwGeA4Ux+F52BGMH2oCDXdk6ykIni83L3g7xBploakPnkbUP5DlPIGZQ9Tje 69ru3yX4PAg7z6t202X+039fpL8S41ozPOAz5VM1BoxnDSHhHwCdynhuKPrSqBL+n5/W uMFDcELHaxoAMoZZ1IwPuM3IJKTV/5TBAOK8DFbXk4lMeSBrgeeTs3UnrrnvASi+HNmK erWdFxXCR0Z6TubEFGO9QUtekOtBlRW1TUGVxPfPYPVJI7LBe0owzPgt+4VKdUG3i2s+ yKCCG7xSrkPiRy1zzsT1UfcfEqJyVO1dWR38coRp0miiFgavwKsqeQyGgwelcJoA+Ugj g8lQ== Received: by 10.180.82.164 with SMTP id j4mr3347457wiy.18.1344522551090; Thu, 09 Aug 2012 07:29:11 -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 bc2sm3032412wib.0.2012.08.09.07.29.09 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 09 Aug 2012 07:29:10 -0700 (PDT) From: Daniel Vetter To: Intel Graphics Development Date: Thu, 9 Aug 2012 16:46:01 +0200 Message-Id: <1344523561-32759-1-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1344461740-1231-7-git-send-email-daniel.vetter@ffwll.ch> References: <1344461740-1231-7-git-send-email-daniel.vetter@ffwll.ch> X-Gm-Message-State: ALoCoQk9PAM+JQe6bGIPAxtlyC1mxgGMmbXIjjpnBJaWkFttoNcJGLwXKgfV9h5Z6A6jLISXHlDX Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH] 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 ... v3: Resolve rebase conflict. 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 212b28e..6d68a05 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; } @@ -3186,18 +3197,18 @@ void intel_gpu_ips_init(struct drm_i915_private *dev_priv) { /* We only register the i915 ips part with intel-ips once everything is * set up, to avoid intel-ips sneaking in and reading bogus values. */ - 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) {