aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-08-09 10:46:01 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-08-09 15:53:52 -0400
commit9270388e184fddb83e3b69c6b7f5b523c070e53d (patch)
tree10286bc3872461b729bd817c995190970aafcdb4 /drivers/gpu/drm/i915
parent73edd18f610b6dd900cc3a180919dc643fff8513 (diff)
drm/i915: fix up ilk drps/ips locking
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. Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c12
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c83
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 3e203da61c69..d15ea50f5854 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)
296 drm_helper_hpd_irq_event(dev); 296 drm_helper_hpd_irq_event(dev);
297} 297}
298 298
299/* defined intel_pm.c */
300extern spinlock_t mchdev_lock;
301
299static void ironlake_handle_rps_change(struct drm_device *dev) 302static void ironlake_handle_rps_change(struct drm_device *dev)
300{ 303{
301 drm_i915_private_t *dev_priv = dev->dev_private; 304 drm_i915_private_t *dev_priv = dev->dev_private;
302 u32 busy_up, busy_down, max_avg, min_avg; 305 u32 busy_up, busy_down, max_avg, min_avg;
303 u8 new_delay = dev_priv->cur_delay; 306 u8 new_delay;
307 unsigned long flags;
308
309 spin_lock_irqsave(&mchdev_lock, flags);
304 310
305 I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); 311 I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
306 312
313 new_delay = dev_priv->cur_delay;
314
307 I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG); 315 I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
308 busy_up = I915_READ(RCPREVBSYTUPAVG); 316 busy_up = I915_READ(RCPREVBSYTUPAVG);
309 busy_down = I915_READ(RCPREVBSYTDNAVG); 317 busy_down = I915_READ(RCPREVBSYTDNAVG);
@@ -326,6 +334,8 @@ static void ironlake_handle_rps_change(struct drm_device *dev)
326 if (ironlake_set_drps(dev, new_delay)) 334 if (ironlake_set_drps(dev, new_delay))
327 dev_priv->cur_delay = new_delay; 335 dev_priv->cur_delay = new_delay;
328 336
337 spin_unlock_irqrestore(&mchdev_lock, flags);
338
329 return; 339 return;
330} 340}
331 341
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 212b28e1b050..6d68a0599686 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2160,11 +2160,28 @@ err_unref:
2160 return NULL; 2160 return NULL;
2161} 2161}
2162 2162
2163/**
2164 * Lock protecting IPS related data structures
2165 * - i915_mch_dev
2166 * - dev_priv->max_delay
2167 * - dev_priv->min_delay
2168 * - dev_priv->fmax
2169 * - dev_priv->gpu_busy
2170 * - dev_priv->gfx_power
2171 */
2172DEFINE_SPINLOCK(mchdev_lock);
2173
2174/* Global for IPS driver to get at the current i915 device. Protected by
2175 * mchdev_lock. */
2176static struct drm_i915_private *i915_mch_dev;
2177
2163bool ironlake_set_drps(struct drm_device *dev, u8 val) 2178bool ironlake_set_drps(struct drm_device *dev, u8 val)
2164{ 2179{
2165 struct drm_i915_private *dev_priv = dev->dev_private; 2180 struct drm_i915_private *dev_priv = dev->dev_private;
2166 u16 rgvswctl; 2181 u16 rgvswctl;
2167 2182
2183 assert_spin_locked(&mchdev_lock);
2184
2168 rgvswctl = I915_READ16(MEMSWCTL); 2185 rgvswctl = I915_READ16(MEMSWCTL);
2169 if (rgvswctl & MEMCTL_CMD_STS) { 2186 if (rgvswctl & MEMCTL_CMD_STS) {
2170 DRM_DEBUG("gpu busy, RCS change rejected\n"); 2187 DRM_DEBUG("gpu busy, RCS change rejected\n");
@@ -2188,6 +2205,8 @@ static void ironlake_enable_drps(struct drm_device *dev)
2188 u32 rgvmodectl = I915_READ(MEMMODECTL); 2205 u32 rgvmodectl = I915_READ(MEMMODECTL);
2189 u8 fmax, fmin, fstart, vstart; 2206 u8 fmax, fmin, fstart, vstart;
2190 2207
2208 spin_lock_irq(&mchdev_lock);
2209
2191 /* Enable temp reporting */ 2210 /* Enable temp reporting */
2192 I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN); 2211 I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
2193 I915_WRITE16(TSC1, I915_READ(TSC1) | TSE); 2212 I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
@@ -2233,9 +2252,9 @@ static void ironlake_enable_drps(struct drm_device *dev)
2233 rgvmodectl |= MEMMODE_SWMODE_EN; 2252 rgvmodectl |= MEMMODE_SWMODE_EN;
2234 I915_WRITE(MEMMODECTL, rgvmodectl); 2253 I915_WRITE(MEMMODECTL, rgvmodectl);
2235 2254
2236 if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) 2255 if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
2237 DRM_ERROR("stuck trying to change perf mode\n"); 2256 DRM_ERROR("stuck trying to change perf mode\n");
2238 msleep(1); 2257 mdelay(1);
2239 2258
2240 ironlake_set_drps(dev, fstart); 2259 ironlake_set_drps(dev, fstart);
2241 2260
@@ -2244,12 +2263,18 @@ static void ironlake_enable_drps(struct drm_device *dev)
2244 dev_priv->last_time1 = jiffies_to_msecs(jiffies); 2263 dev_priv->last_time1 = jiffies_to_msecs(jiffies);
2245 dev_priv->last_count2 = I915_READ(0x112f4); 2264 dev_priv->last_count2 = I915_READ(0x112f4);
2246 getrawmonotonic(&dev_priv->last_time2); 2265 getrawmonotonic(&dev_priv->last_time2);
2266
2267 spin_unlock_irq(&mchdev_lock);
2247} 2268}
2248 2269
2249static void ironlake_disable_drps(struct drm_device *dev) 2270static void ironlake_disable_drps(struct drm_device *dev)
2250{ 2271{
2251 struct drm_i915_private *dev_priv = dev->dev_private; 2272 struct drm_i915_private *dev_priv = dev->dev_private;
2252 u16 rgvswctl = I915_READ16(MEMSWCTL); 2273 u16 rgvswctl;
2274
2275 spin_lock_irq(&mchdev_lock);
2276
2277 rgvswctl = I915_READ16(MEMSWCTL);
2253 2278
2254 /* Ack interrupts, disable EFC interrupt */ 2279 /* Ack interrupts, disable EFC interrupt */
2255 I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); 2280 I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -2260,11 +2285,12 @@ static void ironlake_disable_drps(struct drm_device *dev)
2260 2285
2261 /* Go back to the starting frequency */ 2286 /* Go back to the starting frequency */
2262 ironlake_set_drps(dev, dev_priv->fstart); 2287 ironlake_set_drps(dev, dev_priv->fstart);
2263 msleep(1); 2288 mdelay(1);
2264 rgvswctl |= MEMCTL_CMD_STS; 2289 rgvswctl |= MEMCTL_CMD_STS;
2265 I915_WRITE(MEMSWCTL, rgvswctl); 2290 I915_WRITE(MEMSWCTL, rgvswctl);
2266 msleep(1); 2291 mdelay(1);
2267 2292
2293 spin_unlock_irq(&mchdev_lock);
2268} 2294}
2269 2295
2270/* There's a funny hw issue where the hw returns all 0 when reading from 2296/* There's a funny hw issue where the hw returns all 0 when reading from
@@ -2713,21 +2739,6 @@ static const struct cparams {
2713 { 0, 800, 231, 23784 }, 2739 { 0, 800, 231, 23784 },
2714}; 2740};
2715 2741
2716/**
2717 * Lock protecting IPS related data structures
2718 * - i915_mch_dev
2719 * - dev_priv->max_delay
2720 * - dev_priv->min_delay
2721 * - dev_priv->fmax
2722 * - dev_priv->gpu_busy
2723 * - dev_priv->gfx_power
2724 */
2725static DEFINE_SPINLOCK(mchdev_lock);
2726
2727/* Global for IPS driver to get at the current i915 device. Protected by
2728 * mchdev_lock. */
2729static struct drm_i915_private *i915_mch_dev;
2730
2731unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) 2742unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
2732{ 2743{
2733 u64 total_count, diff, ret; 2744 u64 total_count, diff, ret;
@@ -2978,11 +2989,11 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv)
2978 if (dev_priv->info->gen != 5) 2989 if (dev_priv->info->gen != 5)
2979 return; 2990 return;
2980 2991
2981 spin_lock(&mchdev_lock); 2992 spin_lock_irq(&mchdev_lock);
2982 2993
2983 __i915_update_gfx_val(dev_priv); 2994 __i915_update_gfx_val(dev_priv);
2984 2995
2985 spin_unlock(&mchdev_lock); 2996 spin_unlock_irq(&mchdev_lock);
2986} 2997}
2987 2998
2988unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) 2999unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
@@ -3033,7 +3044,7 @@ unsigned long i915_read_mch_val(void)
3033 struct drm_i915_private *dev_priv; 3044 struct drm_i915_private *dev_priv;
3034 unsigned long chipset_val, graphics_val, ret = 0; 3045 unsigned long chipset_val, graphics_val, ret = 0;
3035 3046
3036 spin_lock(&mchdev_lock); 3047 spin_lock_irq(&mchdev_lock);
3037 if (!i915_mch_dev) 3048 if (!i915_mch_dev)
3038 goto out_unlock; 3049 goto out_unlock;
3039 dev_priv = i915_mch_dev; 3050 dev_priv = i915_mch_dev;
@@ -3044,7 +3055,7 @@ unsigned long i915_read_mch_val(void)
3044 ret = chipset_val + graphics_val; 3055 ret = chipset_val + graphics_val;
3045 3056
3046out_unlock: 3057out_unlock:
3047 spin_unlock(&mchdev_lock); 3058 spin_unlock_irq(&mchdev_lock);
3048 3059
3049 return ret; 3060 return ret;
3050} 3061}
@@ -3060,7 +3071,7 @@ bool i915_gpu_raise(void)
3060 struct drm_i915_private *dev_priv; 3071 struct drm_i915_private *dev_priv;
3061 bool ret = true; 3072 bool ret = true;
3062 3073
3063 spin_lock(&mchdev_lock); 3074 spin_lock_irq(&mchdev_lock);
3064 if (!i915_mch_dev) { 3075 if (!i915_mch_dev) {
3065 ret = false; 3076 ret = false;
3066 goto out_unlock; 3077 goto out_unlock;
@@ -3071,7 +3082,7 @@ bool i915_gpu_raise(void)
3071 dev_priv->max_delay--; 3082 dev_priv->max_delay--;
3072 3083
3073out_unlock: 3084out_unlock:
3074 spin_unlock(&mchdev_lock); 3085 spin_unlock_irq(&mchdev_lock);
3075 3086
3076 return ret; 3087 return ret;
3077} 3088}
@@ -3088,7 +3099,7 @@ bool i915_gpu_lower(void)
3088 struct drm_i915_private *dev_priv; 3099 struct drm_i915_private *dev_priv;
3089 bool ret = true; 3100 bool ret = true;
3090 3101
3091 spin_lock(&mchdev_lock); 3102 spin_lock_irq(&mchdev_lock);
3092 if (!i915_mch_dev) { 3103 if (!i915_mch_dev) {
3093 ret = false; 3104 ret = false;
3094 goto out_unlock; 3105 goto out_unlock;
@@ -3099,7 +3110,7 @@ bool i915_gpu_lower(void)
3099 dev_priv->max_delay++; 3110 dev_priv->max_delay++;
3100 3111
3101out_unlock: 3112out_unlock:
3102 spin_unlock(&mchdev_lock); 3113 spin_unlock_irq(&mchdev_lock);
3103 3114
3104 return ret; 3115 return ret;
3105} 3116}
@@ -3117,7 +3128,7 @@ bool i915_gpu_busy(void)
3117 bool ret = false; 3128 bool ret = false;
3118 int i; 3129 int i;
3119 3130
3120 spin_lock(&mchdev_lock); 3131 spin_lock_irq(&mchdev_lock);
3121 if (!i915_mch_dev) 3132 if (!i915_mch_dev)
3122 goto out_unlock; 3133 goto out_unlock;
3123 dev_priv = i915_mch_dev; 3134 dev_priv = i915_mch_dev;
@@ -3126,7 +3137,7 @@ bool i915_gpu_busy(void)
3126 ret |= !list_empty(&ring->request_list); 3137 ret |= !list_empty(&ring->request_list);
3127 3138
3128out_unlock: 3139out_unlock:
3129 spin_unlock(&mchdev_lock); 3140 spin_unlock_irq(&mchdev_lock);
3130 3141
3131 return ret; 3142 return ret;
3132} 3143}
@@ -3143,7 +3154,7 @@ bool i915_gpu_turbo_disable(void)
3143 struct drm_i915_private *dev_priv; 3154 struct drm_i915_private *dev_priv;
3144 bool ret = true; 3155 bool ret = true;
3145 3156
3146 spin_lock(&mchdev_lock); 3157 spin_lock_irq(&mchdev_lock);
3147 if (!i915_mch_dev) { 3158 if (!i915_mch_dev) {
3148 ret = false; 3159 ret = false;
3149 goto out_unlock; 3160 goto out_unlock;
@@ -3156,7 +3167,7 @@ bool i915_gpu_turbo_disable(void)
3156 ret = false; 3167 ret = false;
3157 3168
3158out_unlock: 3169out_unlock:
3159 spin_unlock(&mchdev_lock); 3170 spin_unlock_irq(&mchdev_lock);
3160 3171
3161 return ret; 3172 return ret;
3162} 3173}
@@ -3186,18 +3197,18 @@ void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
3186{ 3197{
3187 /* We only register the i915 ips part with intel-ips once everything is 3198 /* We only register the i915 ips part with intel-ips once everything is
3188 * set up, to avoid intel-ips sneaking in and reading bogus values. */ 3199 * set up, to avoid intel-ips sneaking in and reading bogus values. */
3189 spin_lock(&mchdev_lock); 3200 spin_lock_irq(&mchdev_lock);
3190 i915_mch_dev = dev_priv; 3201 i915_mch_dev = dev_priv;
3191 spin_unlock(&mchdev_lock); 3202 spin_unlock_irq(&mchdev_lock);
3192 3203
3193 ips_ping_for_i915_load(); 3204 ips_ping_for_i915_load();
3194} 3205}
3195 3206
3196void intel_gpu_ips_teardown(void) 3207void intel_gpu_ips_teardown(void)
3197{ 3208{
3198 spin_lock(&mchdev_lock); 3209 spin_lock_irq(&mchdev_lock);
3199 i915_mch_dev = NULL; 3210 i915_mch_dev = NULL;
3200 spin_unlock(&mchdev_lock); 3211 spin_unlock_irq(&mchdev_lock);
3201} 3212}
3202static void intel_init_emon(struct drm_device *dev) 3213static void intel_init_emon(struct drm_device *dev)
3203{ 3214{