]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/i915/i915_irq.c
Merge tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel...
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / i915 / i915_irq.c
index b6c886ac901bd78cfa7beb1a3aaaf706821a6d2b..7b7f55a28eec2038bcb94cb25353d8f0eaed386f 100644 (file)
@@ -180,7 +180,7 @@ i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
        WARN_ON(bits & ~mask);
 
        val = I915_READ(PORT_HOTPLUG_EN);
@@ -222,7 +222,7 @@ void ilk_update_display_irq(struct drm_i915_private *dev_priv,
 {
        uint32_t new_val;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
@@ -250,7 +250,7 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
                              uint32_t interrupt_mask,
                              uint32_t enabled_irq_mask)
 {
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
@@ -302,7 +302,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        new_val = dev_priv->pm_imr;
        new_val &= ~interrupt_mask;
@@ -340,7 +340,7 @@ void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask)
 {
        i915_reg_t reg = gen6_pm_iir(dev_priv);
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        I915_WRITE(reg, reset_mask);
        I915_WRITE(reg, reset_mask);
@@ -349,7 +349,7 @@ void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask)
 
 void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask)
 {
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        dev_priv->pm_ier |= enable_mask;
        I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier);
@@ -359,7 +359,7 @@ void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask)
 
 void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask)
 {
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        dev_priv->pm_ier &= ~disable_mask;
        __gen6_mask_pm_irq(dev_priv, disable_mask);
@@ -389,11 +389,6 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv)
        spin_unlock_irq(&dev_priv->irq_lock);
 }
 
-u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask)
-{
-       return (mask & ~dev_priv->rps.pm_intr_keep);
-}
-
 void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
 {
        if (!READ_ONCE(dev_priv->rps.interrupts_enabled))
@@ -463,7 +458,7 @@ static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
        uint32_t new_val;
        uint32_t old_val;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
@@ -496,7 +491,7 @@ void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
 {
        uint32_t new_val;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
@@ -530,7 +525,7 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
@@ -546,7 +541,7 @@ __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
        i915_reg_t reg = PIPESTAT(pipe);
        u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
        WARN_ON(!intel_irqs_enabled(dev_priv));
 
        if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
@@ -573,7 +568,7 @@ __i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
        i915_reg_t reg = PIPESTAT(pipe);
        u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
        WARN_ON(!intel_irqs_enabled(dev_priv));
 
        if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
@@ -725,9 +720,8 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
        struct drm_i915_private *dev_priv = to_i915(dev);
        i915_reg_t high_frame, low_frame;
        u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
-       struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
-                                                               pipe);
-       const struct drm_display_mode *mode = &intel_crtc->base.hwmode;
+       const struct drm_display_mode *mode = &dev->vblank[pipe].hwmode;
+       unsigned long irqflags;
 
        htotal = mode->crtc_htotal;
        hsync_start = mode->crtc_hsync_start;
@@ -744,17 +738,21 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
        high_frame = PIPEFRAME(pipe);
        low_frame = PIPEFRAMEPIXEL(pipe);
 
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
        /*
         * High & low register fields aren't synchronized, so make sure
         * we get a low value that's stable across two reads of the high
         * register.
         */
        do {
-               high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
-               low   = I915_READ(low_frame);
-               high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
+               high1 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK;
+               low   = I915_READ_FW(low_frame);
+               high2 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK;
        } while (high1 != high2);
 
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
        high1 >>= PIPE_FRAME_HIGH_SHIFT;
        pixel = low & PIPE_PIXEL_MASK;
        low >>= PIPE_FRAME_LOW_SHIFT;
@@ -779,10 +777,17 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       const struct drm_display_mode *mode = &crtc->base.hwmode;
+       const struct drm_display_mode *mode;
+       struct drm_vblank_crtc *vblank;
        enum pipe pipe = crtc->pipe;
        int position, vtotal;
 
+       if (!crtc->active)
+               return -1;
+
+       vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)];
+       mode = &vblank->hwmode;
+
        vtotal = mode->crtc_vtotal;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                vtotal /= 2;
@@ -809,8 +814,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
 
                for (i = 0; i < 100; i++) {
                        udelay(1);
-                       temp = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) &
-                               DSL_LINEMASK_GEN3;
+                       temp = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
                        if (temp != position) {
                                position = temp;
                                break;
@@ -825,10 +829,10 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
        return (position + crtc->scanline_offset) % vtotal;
 }
 
-static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
-                                   unsigned int flags, int *vpos, int *hpos,
-                                   ktime_t *stime, ktime_t *etime,
-                                   const struct drm_display_mode *mode)
+static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
+                                    bool in_vblank_irq, int *vpos, int *hpos,
+                                    ktime_t *stime, ktime_t *etime,
+                                    const struct drm_display_mode *mode)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
@@ -836,13 +840,12 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
        int position;
        int vbl_start, vbl_end, hsync_start, htotal, vtotal;
        bool in_vbl = true;
-       int ret = 0;
        unsigned long irqflags;
 
        if (WARN_ON(!mode->crtc_clock)) {
                DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
                                 "pipe %c\n", pipe_name(pipe));
-               return 0;
+               return false;
        }
 
        htotal = mode->crtc_htotal;
@@ -857,8 +860,6 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
                vtotal /= 2;
        }
 
-       ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
-
        /*
         * Lock uncore.lock, as we will do multiple timing critical raw
         * register reads, potentially with preemption disabled, so the
@@ -942,11 +943,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
                *hpos = position - (*vpos * htotal);
        }
 
-       /* In vblank? */
-       if (in_vbl)
-               ret |= DRM_SCANOUTPOS_IN_VBLANK;
-
-       return ret;
+       return true;
 }
 
 int intel_get_crtc_scanline(struct intel_crtc *crtc)
@@ -962,37 +959,6 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc)
        return position;
 }
 
-static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
-                             int *max_error,
-                             struct timeval *vblank_time,
-                             unsigned flags)
-{
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *crtc;
-
-       if (pipe >= INTEL_INFO(dev_priv)->num_pipes) {
-               DRM_ERROR("Invalid crtc %u\n", pipe);
-               return -EINVAL;
-       }
-
-       /* Get drm_crtc to timestamp: */
-       crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
-       if (crtc == NULL) {
-               DRM_ERROR("Invalid crtc %u\n", pipe);
-               return -EINVAL;
-       }
-
-       if (!crtc->base.hwmode.crtc_clock) {
-               DRM_DEBUG_KMS("crtc %u is disabled\n", pipe);
-               return -EBUSY;
-       }
-
-       /* Helper routine in DRM core does all the work: */
-       return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
-                                                    vblank_time, flags,
-                                                    &crtc->base.hwmode);
-}
-
 static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
 {
        u32 busy_up, busy_down, max_avg, min_avg;
@@ -1033,15 +999,50 @@ static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
 
 static void notify_ring(struct intel_engine_cs *engine)
 {
-       smp_store_mb(engine->breadcrumbs.irq_posted, true);
-       if (intel_engine_wakeup(engine))
-               trace_i915_gem_request_notify(engine);
+       struct drm_i915_gem_request *rq = NULL;
+       struct intel_wait *wait;
+
+       atomic_inc(&engine->irq_count);
+       set_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
+
+       spin_lock(&engine->breadcrumbs.irq_lock);
+       wait = engine->breadcrumbs.irq_wait;
+       if (wait) {
+               /* We use a callback from the dma-fence to submit
+                * requests after waiting on our own requests. To
+                * ensure minimum delay in queuing the next request to
+                * hardware, signal the fence now rather than wait for
+                * the signaler to be woken up. We still wake up the
+                * waiter in order to handle the irq-seqno coherency
+                * issues (we may receive the interrupt before the
+                * seqno is written, see __i915_request_irq_complete())
+                * and to handle coalescing of multiple seqno updates
+                * and many waiters.
+                */
+               if (i915_seqno_passed(intel_engine_get_seqno(engine),
+                                     wait->seqno) &&
+                   !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+                             &wait->request->fence.flags))
+                       rq = i915_gem_request_get(wait->request);
+
+               wake_up_process(wait->tsk);
+       } else {
+               __intel_engine_disarm_breadcrumbs(engine);
+       }
+       spin_unlock(&engine->breadcrumbs.irq_lock);
+
+       if (rq) {
+               dma_fence_signal(&rq->fence);
+               i915_gem_request_put(rq);
+       }
+
+       trace_intel_engine_notify(engine, wait);
 }
 
 static void vlv_c0_read(struct drm_i915_private *dev_priv,
                        struct intel_rps_ei *ei)
 {
-       ei->cz_clock = vlv_punit_read(dev_priv, PUNIT_REG_CZ_TIMESTAMP);
+       ei->ktime = ktime_get_raw();
        ei->render_c0 = I915_READ(VLV_RENDER_C0_COUNT);
        ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
 }
@@ -1061,18 +1062,13 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
                return 0;
 
        vlv_c0_read(dev_priv, &now);
-       if (now.cz_clock == 0)
-               return 0;
 
-       if (prev->cz_clock) {
+       if (prev->ktime) {
                u64 time, c0;
-               unsigned int mul;
+               u32 render, media;
 
-               mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
-               if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
-                       mul <<= 8;
+               time = ktime_us_delta(now.ktime, prev->ktime);
 
-               time = now.cz_clock - prev->cz_clock;
                time *= dev_priv->czclk_freq;
 
                /* Workload can be split between render + media,
@@ -1080,9 +1076,10 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
                 * mesa. To account for this we need to combine both engines
                 * into our activity counter.
                 */
-               c0 = now.render_c0 - prev->render_c0;
-               c0 += now.media_c0 - prev->media_c0;
-               c0 *= mul;
+               render = now.render_c0 - prev->render_c0;
+               media = now.media_c0 - prev->media_c0;
+               c0 = max(render, media);
+               c0 *= 1000 * 100 << 8; /* to usecs and scale to threshold% */
 
                if (c0 > time * dev_priv->rps.up_threshold)
                        events = GEN6_PM_RP_UP_THRESHOLD;
@@ -1110,30 +1107,21 @@ static void gen6_pm_rps_work(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv =
                container_of(work, struct drm_i915_private, rps.work);
-       bool client_boost;
+       bool client_boost = false;
        int new_delay, adj, min, max;
-       u32 pm_iir;
+       u32 pm_iir = 0;
 
        spin_lock_irq(&dev_priv->irq_lock);
-       /* Speed up work cancelation during disabling rps interrupts. */
-       if (!dev_priv->rps.interrupts_enabled) {
-               spin_unlock_irq(&dev_priv->irq_lock);
-               return;
+       if (dev_priv->rps.interrupts_enabled) {
+               pm_iir = fetch_and_zero(&dev_priv->rps.pm_iir);
+               client_boost = fetch_and_zero(&dev_priv->rps.client_boost);
        }
-
-       pm_iir = dev_priv->rps.pm_iir;
-       dev_priv->rps.pm_iir = 0;
-       /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
-       gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events);
-       client_boost = dev_priv->rps.client_boost;
-       dev_priv->rps.client_boost = false;
        spin_unlock_irq(&dev_priv->irq_lock);
 
        /* Make sure we didn't queue anything we're not going to process. */
        WARN_ON(pm_iir & ~dev_priv->pm_rps_events);
-
        if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost)
-               return;
+               goto out;
 
        mutex_lock(&dev_priv->rps.hw_lock);
 
@@ -1156,20 +1144,12 @@ static void gen6_pm_rps_work(struct work_struct *work)
 
                if (new_delay >= dev_priv->rps.max_freq_softlimit)
                        adj = 0;
-               /*
-                * For better performance, jump directly
-                * to RPe if we're below it.
-                */
-               if (new_delay < dev_priv->rps.efficient_freq - adj) {
-                       new_delay = dev_priv->rps.efficient_freq;
-                       adj = 0;
-               }
        } else if (client_boost || any_waiters(dev_priv)) {
                adj = 0;
        } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) {
                if (dev_priv->rps.cur_freq > dev_priv->rps.efficient_freq)
                        new_delay = dev_priv->rps.efficient_freq;
-               else
+               else if (dev_priv->rps.cur_freq > dev_priv->rps.min_freq_softlimit)
                        new_delay = dev_priv->rps.min_freq_softlimit;
                adj = 0;
        } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
@@ -1192,9 +1172,19 @@ static void gen6_pm_rps_work(struct work_struct *work)
        new_delay += adj;
        new_delay = clamp_t(int, new_delay, min, max);
 
-       intel_set_rps(dev_priv, new_delay);
+       if (intel_set_rps(dev_priv, new_delay)) {
+               DRM_DEBUG_DRIVER("Failed to set new GPU frequency\n");
+               dev_priv->rps.last_adj = 0;
+       }
 
        mutex_unlock(&dev_priv->rps.hw_lock);
+
+out:
+       /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
+       spin_lock_irq(&dev_priv->irq_lock);
+       if (dev_priv->rps.interrupts_enabled)
+               gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events);
+       spin_unlock_irq(&dev_priv->irq_lock);
 }
 
 
@@ -1210,7 +1200,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 static void ivybridge_parity_work(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv =
-               container_of(work, struct drm_i915_private, l3_parity.error_work);
+               container_of(work, typeof(*dev_priv), l3_parity.error_work);
        u32 error_status, row, bank, subbank;
        char *parity_event[6];
        uint32_t misccpctl;
@@ -1327,13 +1317,25 @@ static void snb_gt_irq_handler(struct drm_i915_private *dev_priv,
                ivybridge_parity_error_irq_handler(dev_priv, gt_iir);
 }
 
-static __always_inline void
+static void
 gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
 {
-       if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
+       bool tasklet = false;
+
+       if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) {
+               if (port_count(&engine->execlist_port[0])) {
+                       __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
+                       tasklet = true;
+               }
+       }
+
+       if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) {
                notify_ring(engine);
-       if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
-               tasklet_schedule(&engine->irq_tasklet);
+               tasklet |= i915.enable_guc_submission;
+       }
+
+       if (tasklet)
+               tasklet_hi_schedule(&engine->irq_tasklet);
 }
 
 static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv,
@@ -1706,8 +1708,8 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
                        I915_WRITE(SOFT_SCRATCH(15), msg & ~flush);
 
                        /* Handle flush interrupt in bottom half */
-                       queue_work(dev_priv->guc.log.flush_wq,
-                                  &dev_priv->guc.log.flush_work);
+                       queue_work(dev_priv->guc.log.runtime.flush_wq,
+                                  &dev_priv->guc.log.runtime.flush_work);
 
                        dev_priv->guc.log.flush_interrupt_count++;
                } else {
@@ -2596,22 +2598,6 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        return ret;
 }
 
-static void i915_error_wake_up(struct drm_i915_private *dev_priv)
-{
-       /*
-        * Notify all waiters for GPU completion events that reset state has
-        * been changed, and that they need to restart their wait after
-        * checking for potential errors (and bail out to drop locks if there is
-        * a gpu reset pending so that i915_error_work_func can acquire them).
-        */
-
-       /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */
-       wake_up_all(&dev_priv->gpu_error.wait_queue);
-
-       /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */
-       wake_up_all(&dev_priv->pending_flip_queue);
-}
-
 /**
  * i915_reset_and_wakeup - do process context error handling work
  * @dev_priv: i915 device private
@@ -2631,16 +2617,11 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
        DRM_DEBUG_DRIVER("resetting chip\n");
        kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event);
 
-       /*
-        * In most cases it's guaranteed that we get here with an RPM
-        * reference held, for example because there is a pending GPU
-        * request that won't finish until the reset is done. This
-        * isn't the case at least when we get here by doing a
-        * simulated reset via debugs, so get an RPM reference.
-        */
-       intel_runtime_pm_get(dev_priv);
        intel_prepare_reset(dev_priv);
 
+       set_bit(I915_RESET_HANDOFF, &dev_priv->gpu_error.flags);
+       wake_up_all(&dev_priv->gpu_error.wait_queue);
+
        do {
                /*
                 * All state reset _must_ be completed before we update the
@@ -2655,12 +2636,11 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
 
                /* We need to wait for anyone holding the lock to wakeup */
        } while (wait_on_bit_timeout(&dev_priv->gpu_error.flags,
-                                    I915_RESET_IN_PROGRESS,
+                                    I915_RESET_HANDOFF,
                                     TASK_UNINTERRUPTIBLE,
                                     HZ));
 
        intel_finish_reset(dev_priv);
-       intel_runtime_pm_put(dev_priv);
 
        if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
                kobject_uevent_env(kobj,
@@ -2670,6 +2650,7 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
         * Note: The wake_up also serves as a memory barrier so that
         * waiters see the updated value of the dev_priv->gpu_error.
         */
+       clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags);
        wake_up_all(&dev_priv->gpu_error.reset_queue);
 }
 
@@ -2747,31 +2728,29 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
        vscnprintf(error_msg, sizeof(error_msg), fmt, args);
        va_end(args);
 
+       /*
+        * In most cases it's guaranteed that we get here with an RPM
+        * reference held, for example because there is a pending GPU
+        * request that won't finish until the reset is done. This
+        * isn't the case at least when we get here by doing a
+        * simulated reset via debugfs, so get an RPM reference.
+        */
+       intel_runtime_pm_get(dev_priv);
+
        i915_capture_error_state(dev_priv, engine_mask, error_msg);
        i915_clear_error_registers(dev_priv);
 
        if (!engine_mask)
-               return;
+               goto out;
 
-       if (test_and_set_bit(I915_RESET_IN_PROGRESS,
+       if (test_and_set_bit(I915_RESET_BACKOFF,
                             &dev_priv->gpu_error.flags))
-               return;
-
-       /*
-        * Wakeup waiting processes so that the reset function
-        * i915_reset_and_wakeup doesn't deadlock trying to grab
-        * various locks. By bumping the reset counter first, the woken
-        * processes will see a reset in progress and back off,
-        * releasing their locks and then wait for the reset completion.
-        * We must do this for _all_ gpu waiters that might hold locks
-        * that the reset work needs to acquire.
-        *
-        * Note: The wake_up also provides a memory barrier to ensure that the
-        * waiters see the updated value of the reset flags.
-        */
-       i915_error_wake_up(dev_priv);
+               goto out;
 
        i915_reset_and_wakeup(dev_priv);
+
+out:
+       intel_runtime_pm_put(dev_priv);
 }
 
 /* Called from drm generic code, passed 'crtc' which
@@ -2940,7 +2919,6 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
        u32 pipestat_mask;
        u32 enable_mask;
        enum pipe pipe;
-       u32 val;
 
        pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
                        PIPE_CRC_DONE_INTERRUPT_STATUS;
@@ -2951,18 +2929,16 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
 
        enable_mask = I915_DISPLAY_PORT_INTERRUPT |
                I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+               I915_LPE_PIPE_A_INTERRUPT |
+               I915_LPE_PIPE_B_INTERRUPT;
+
        if (IS_CHERRYVIEW(dev_priv))
-               enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
+               enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
+                       I915_LPE_PIPE_C_INTERRUPT;
 
        WARN_ON(dev_priv->irq_mask != ~0);
 
-       val = (I915_LPE_PIPE_A_INTERRUPT |
-               I915_LPE_PIPE_B_INTERRUPT |
-               I915_LPE_PIPE_C_INTERRUPT);
-
-       enable_mask |= val;
-
        dev_priv->irq_mask = ~enable_mask;
 
        GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);
@@ -3089,19 +3065,9 @@ static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
        return enabled_irqs;
 }
 
-static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
+static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
 {
-       u32 hotplug_irqs, hotplug, enabled_irqs;
-
-       if (HAS_PCH_IBX(dev_priv)) {
-               hotplug_irqs = SDE_HOTPLUG_MASK;
-               enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ibx);
-       } else {
-               hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
-               enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_cpt);
-       }
-
-       ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+       u32 hotplug;
 
        /*
         * Enable digital hotplug on the PCH, and configure the DP short pulse
@@ -3109,10 +3075,12 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
         * The pulse duration bits are reserved on LPT+.
         */
        hotplug = I915_READ(PCH_PORT_HOTPLUG);
-       hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
-       hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
-       hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
+       hotplug &= ~(PORTB_PULSE_DURATION_MASK |
+                    PORTC_PULSE_DURATION_MASK |
+                    PORTD_PULSE_DURATION_MASK);
        hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
+       hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
+       hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
        /*
         * When CPU and PCH are on the same package, port A
         * HPD must be enabled in both north and south.
@@ -3122,6 +3090,23 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
        I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
 }
 
+static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+       u32 hotplug_irqs, enabled_irqs;
+
+       if (HAS_PCH_IBX(dev_priv)) {
+               hotplug_irqs = SDE_HOTPLUG_MASK;
+               enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ibx);
+       } else {
+               hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
+               enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_cpt);
+       }
+
+       ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+       ibx_hpd_detection_setup(dev_priv);
+}
+
 static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
 {
        u32 hotplug;
@@ -3151,9 +3136,25 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
        spt_hpd_detection_setup(dev_priv);
 }
 
+static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+       u32 hotplug;
+
+       /*
+        * Enable digital hotplug on the CPU, and configure the DP short pulse
+        * duration to 2ms (which is the minimum in the Display Port spec)
+        * The pulse duration bits are reserved on HSW+.
+        */
+       hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
+       hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK;
+       hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE |
+                  DIGITAL_PORTA_PULSE_DURATION_2ms;
+       I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug);
+}
+
 static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
 {
-       u32 hotplug_irqs, hotplug, enabled_irqs;
+       u32 hotplug_irqs, enabled_irqs;
 
        if (INTEL_GEN(dev_priv) >= 8) {
                hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG;
@@ -3172,15 +3173,7 @@ static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
                ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
        }
 
-       /*
-        * Enable digital hotplug on the CPU, and configure the DP short pulse
-        * duration to 2ms (which is the minimum in the Display Port spec)
-        * The pulse duration bits are reserved on HSW+.
-        */
-       hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL);
-       hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK;
-       hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_2ms;
-       I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug);
+       ilk_hpd_detection_setup(dev_priv);
 
        ibx_hpd_irq_setup(dev_priv);
 }
@@ -3251,7 +3244,7 @@ static void ibx_irq_postinstall(struct drm_device *dev)
 
        if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
            HAS_PCH_LPT(dev_priv))
-               ; /* TODO: Enable HPD detection on older PCH platforms too */
+               ibx_hpd_detection_setup(dev_priv);
        else
                spt_hpd_detection_setup(dev_priv);
 }
@@ -3328,6 +3321,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 
        gen5_gt_irq_postinstall(dev);
 
+       ilk_hpd_detection_setup(dev_priv);
+
        ibx_irq_postinstall(dev);
 
        if (IS_IRONLAKE_M(dev_priv)) {
@@ -3346,7 +3341,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 
 void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
 {
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        if (dev_priv->display_irqs_enabled)
                return;
@@ -3361,7 +3356,7 @@ void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
 
 void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
 {
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        if (!dev_priv->display_irqs_enabled)
                return;
@@ -3468,6 +3463,8 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 
        if (IS_GEN9_LP(dev_priv))
                bxt_hpd_detection_setup(dev_priv);
+       else if (IS_BROADWELL(dev_priv))
+               ilk_hpd_detection_setup(dev_priv);
 }
 
 static int gen8_irq_postinstall(struct drm_device *dev)
@@ -4035,7 +4032,7 @@ static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
 {
        u32 hotplug_en;
 
-       assert_spin_locked(&dev_priv->irq_lock);
+       lockdep_assert_held(&dev_priv->irq_lock);
 
        /* Note HDMI and DP share hotplug bits */
        /* enable bits are the same for all generations */
@@ -4199,11 +4196,15 @@ static void i965_irq_uninstall(struct drm_device * dev)
 void intel_irq_init(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = &dev_priv->drm;
+       int i;
 
        intel_hpd_init_work(dev_priv);
 
        INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
+
        INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
+       for (i = 0; i < MAX_L3_SLICES; ++i)
+               dev_priv->l3_parity.remap_info[i] = NULL;
 
        if (HAS_GUC_SCHED(dev_priv))
                dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT;
@@ -4215,24 +4216,23 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        else
                dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
-       dev_priv->rps.pm_intr_keep = 0;
+       dev_priv->rps.pm_intrmsk_mbz = 0;
 
        /*
-        * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer
+        * SNB,IVB,HSW can while VLV,CHV may hard hang on looping batchbuffer
         * if GEN6_PM_UP_EI_EXPIRED is masked.
         *
         * TODO: verify if this can be reproduced on VLV,CHV.
         */
-       if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv))
-               dev_priv->rps.pm_intr_keep |= GEN6_PM_RP_UP_EI_EXPIRED;
+       if (INTEL_INFO(dev_priv)->gen <= 7)
+               dev_priv->rps.pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED;
 
        if (INTEL_INFO(dev_priv)->gen >= 8)
-               dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_GUC;
+               dev_priv->rps.pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC;
 
        if (IS_GEN2(dev_priv)) {
                /* Gen2 doesn't have a hardware frame counter */
                dev->max_vblank_count = 0;
-               dev->driver->get_vblank_counter = drm_vblank_no_hw_counter;
        } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
                dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
                dev->driver->get_vblank_counter = g4x_get_vblank_counter;
@@ -4259,7 +4259,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                dev_priv->display_irqs_enabled = false;
 
-       dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
+       dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD;
+
+       dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
        dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
 
        if (IS_CHERRYVIEW(dev_priv)) {
@@ -4327,6 +4329,20 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        }
 }
 
+/**
+ * intel_irq_fini - deinitializes IRQ support
+ * @i915: i915 device instance
+ *
+ * This function deinitializes all the IRQ support.
+ */
+void intel_irq_fini(struct drm_i915_private *i915)
+{
+       int i;
+
+       for (i = 0; i < MAX_L3_SLICES; ++i)
+               kfree(i915->l3_parity.remap_info[i]);
+}
+
 /**
  * intel_irq_install - enables the hardware interrupt
  * @dev_priv: i915 device instance