drm/i915: Protect DSPARB registers with a spinlock
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 5 Dec 2016 14:13:28 +0000 (16:13 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 7 Dec 2016 15:50:21 +0000 (17:50 +0200)
Each DSPARB register can house bits for two separate pipes, hence
we must protect the registers during reprogramming so that parallel
FIFO reconfigurations happening simultaneosly on multiple pipes won't
corrupt each others values.

We'll use a new spinlock for this instead of the wm_mutex since we'll
have to move the DSPARB programming to happen from the vblank evade
critical section, and we can't use mutexes in there.

v2: Document why we use a spinlock instead of a mutex (Maarten)

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1480947208-18468-1-git-send-email-ville.syrjala@linux.intel.com
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_pm.c

index 1a7ac2eefe97def1efc361f6911b7145afdf3fec..5fe27e42d81be1184a41d1af612eb123f13d4bd2 100644 (file)
@@ -801,6 +801,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        spin_lock_init(&dev_priv->mmio_flip_lock);
+       spin_lock_init(&dev_priv->wm.dsparb_lock);
        mutex_init(&dev_priv->sb_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
        mutex_init(&dev_priv->av_mutex);
index 8daa4fb13b52bcabf026aba28788c11ac0d7050f..33758ac5ec9a70bcc78f9608530c3d8d776b0d6f 100644 (file)
@@ -2191,6 +2191,9 @@ struct drm_i915_private {
        } sagv_status;
 
        struct {
+               /* protects DSPARB registers on pre-g4x/vlv/chv */
+               spinlock_t dsparb_lock;
+
                /*
                 * Raw watermark latency values:
                 * in 0.1us units for WM0,
index c6fe59944a0bd47849f4accf2159a7726d6ebc62..3ea7cf275be09f72f3bd225c2404896d3b2199b4 100644 (file)
@@ -1223,6 +1223,8 @@ static void vlv_pipe_set_fifo_size(struct intel_crtc *crtc)
                      pipe_name(crtc->pipe), sprite0_start,
                      sprite1_start, fifo_size);
 
+       spin_lock(&dev_priv->wm.dsparb_lock);
+
        switch (crtc->pipe) {
                uint32_t dsparb, dsparb2, dsparb3;
        case PIPE_A:
@@ -1279,6 +1281,10 @@ static void vlv_pipe_set_fifo_size(struct intel_crtc *crtc)
        default:
                break;
        }
+
+       POSTING_READ(DSPARB);
+
+       spin_unlock(&dev_priv->wm.dsparb_lock);
 }
 
 #undef VLV_FIFO