xref: /gfx-drm/usr/src/uts/intel/io/i915/i915_irq.c (revision 19482684)
147dc10d7SGordon Ross /*
247dc10d7SGordon Ross  * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
347dc10d7SGordon Ross  */
447dc10d7SGordon Ross 
547dc10d7SGordon Ross /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
647dc10d7SGordon Ross  */
747dc10d7SGordon Ross /*
847dc10d7SGordon Ross  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
947dc10d7SGordon Ross  * Copyright (c) 2009, 2012, Intel Corporation.
1047dc10d7SGordon Ross  * All Rights Reserved.
1147dc10d7SGordon Ross  *
1247dc10d7SGordon Ross  * Permission is hereby granted, free of charge, to any person obtaining a
1347dc10d7SGordon Ross  * copy of this software and associated documentation files (the
1447dc10d7SGordon Ross  * "Software"), to deal in the Software without restriction, including
1547dc10d7SGordon Ross  * without limitation the rights to use, copy, modify, merge, publish,
1647dc10d7SGordon Ross  * distribute, sub license, and/or sell copies of the Software, and to
1747dc10d7SGordon Ross  * permit persons to whom the Software is furnished to do so, subject to
1847dc10d7SGordon Ross  * the following conditions:
1947dc10d7SGordon Ross  *
2047dc10d7SGordon Ross  * The above copyright notice and this permission notice (including the
2147dc10d7SGordon Ross  * next paragraph) shall be included in all copies or substantial portions
2247dc10d7SGordon Ross  * of the Software.
2347dc10d7SGordon Ross  *
2447dc10d7SGordon Ross  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2547dc10d7SGordon Ross  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2647dc10d7SGordon Ross  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2747dc10d7SGordon Ross  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2847dc10d7SGordon Ross  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2947dc10d7SGordon Ross  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
3047dc10d7SGordon Ross  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3147dc10d7SGordon Ross  *
3247dc10d7SGordon Ross  */
3347dc10d7SGordon Ross 
3447dc10d7SGordon Ross #include "drmP.h"
3547dc10d7SGordon Ross #include "drm.h"
3647dc10d7SGordon Ross #include "i915_drm.h"
3747dc10d7SGordon Ross #include "i915_drv.h"
3847dc10d7SGordon Ross #include "intel_drv.h"
3947dc10d7SGordon Ross 
4047dc10d7SGordon Ross static const u32 hpd_ibx[] = {
4147dc10d7SGordon Ross 	[HPD_CRT] = SDE_CRT_HOTPLUG,
4247dc10d7SGordon Ross 	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
4347dc10d7SGordon Ross 	[HPD_PORT_B] = SDE_PORTB_HOTPLUG,
4447dc10d7SGordon Ross 	[HPD_PORT_C] = SDE_PORTC_HOTPLUG,
4547dc10d7SGordon Ross 	[HPD_PORT_D] = SDE_PORTD_HOTPLUG
4647dc10d7SGordon Ross };
4747dc10d7SGordon Ross 
4847dc10d7SGordon Ross static const u32 hpd_cpt[] = {
4947dc10d7SGordon Ross 	[HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
5047dc10d7SGordon Ross 	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
5147dc10d7SGordon Ross 	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
5247dc10d7SGordon Ross 	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
5347dc10d7SGordon Ross 	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
5447dc10d7SGordon Ross };
5547dc10d7SGordon Ross 
5647dc10d7SGordon Ross static const u32 hpd_mask_i915[] = {
5747dc10d7SGordon Ross 	[HPD_CRT] = CRT_HOTPLUG_INT_EN,
5847dc10d7SGordon Ross 	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
5947dc10d7SGordon Ross 	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
6047dc10d7SGordon Ross 	[HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
6147dc10d7SGordon Ross 	[HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
6247dc10d7SGordon Ross 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
6347dc10d7SGordon Ross };
6447dc10d7SGordon Ross 
6547dc10d7SGordon Ross static const u32 hpd_status_gen4[] = {
6647dc10d7SGordon Ross 	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
6747dc10d7SGordon Ross 	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
6847dc10d7SGordon Ross 	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
6947dc10d7SGordon Ross 	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
7047dc10d7SGordon Ross 	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
7147dc10d7SGordon Ross 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
7247dc10d7SGordon Ross };
7347dc10d7SGordon Ross 
7447dc10d7SGordon Ross static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
7547dc10d7SGordon Ross 	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
7647dc10d7SGordon Ross 	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
7747dc10d7SGordon Ross 	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
7847dc10d7SGordon Ross 	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
7947dc10d7SGordon Ross 	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
8047dc10d7SGordon Ross 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
8147dc10d7SGordon Ross };
8247dc10d7SGordon Ross 
8347dc10d7SGordon Ross /* For display hotplug interrupt */
8447dc10d7SGordon Ross static void
ironlake_enable_display_irq(drm_i915_private_t * dev_priv,u32 mask)8547dc10d7SGordon Ross ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
8647dc10d7SGordon Ross {
8747dc10d7SGordon Ross 	assert_spin_locked(&dev_priv->irq_lock);
8847dc10d7SGordon Ross 
8947dc10d7SGordon Ross 	if ((dev_priv->irq_mask & mask) != 0) {
9047dc10d7SGordon Ross 		dev_priv->irq_mask &= ~mask;
9147dc10d7SGordon Ross 		I915_WRITE(DEIMR, dev_priv->irq_mask);
9247dc10d7SGordon Ross 		POSTING_READ(DEIMR);
9347dc10d7SGordon Ross 	}
9447dc10d7SGordon Ross }
9547dc10d7SGordon Ross 
9647dc10d7SGordon Ross static void
ironlake_disable_display_irq(drm_i915_private_t * dev_priv,u32 mask)9747dc10d7SGordon Ross ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
9847dc10d7SGordon Ross {
9947dc10d7SGordon Ross 	assert_spin_locked(&dev_priv->irq_lock);
10047dc10d7SGordon Ross 
10147dc10d7SGordon Ross 	if ((dev_priv->irq_mask & mask) != mask) {
10247dc10d7SGordon Ross 		dev_priv->irq_mask |= mask;
10347dc10d7SGordon Ross 		I915_WRITE(DEIMR, dev_priv->irq_mask);
10447dc10d7SGordon Ross 		POSTING_READ(DEIMR);
10547dc10d7SGordon Ross 	}
10647dc10d7SGordon Ross }
10747dc10d7SGordon Ross 
ivb_can_enable_err_int(struct drm_device * dev)10847dc10d7SGordon Ross static bool ivb_can_enable_err_int(struct drm_device *dev)
10947dc10d7SGordon Ross {
11047dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
11147dc10d7SGordon Ross 	struct intel_crtc *crtc;
11247dc10d7SGordon Ross 	enum pipe pipe;
11347dc10d7SGordon Ross 
11447dc10d7SGordon Ross 	assert_spin_locked(&dev_priv->irq_lock);
11547dc10d7SGordon Ross 
11647dc10d7SGordon Ross 	for_each_pipe(pipe) {
11747dc10d7SGordon Ross 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
11847dc10d7SGordon Ross 
11947dc10d7SGordon Ross 		if (crtc->cpu_fifo_underrun_disabled)
12047dc10d7SGordon Ross 			return false;
12147dc10d7SGordon Ross 	}
12247dc10d7SGordon Ross 
12347dc10d7SGordon Ross 	return true;
12447dc10d7SGordon Ross }
12547dc10d7SGordon Ross 
cpt_can_enable_serr_int(struct drm_device * dev)12647dc10d7SGordon Ross static bool cpt_can_enable_serr_int(struct drm_device *dev)
12747dc10d7SGordon Ross {
12847dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
12947dc10d7SGordon Ross 	enum pipe pipe;
13047dc10d7SGordon Ross 	struct intel_crtc *crtc;
13147dc10d7SGordon Ross 
13247dc10d7SGordon Ross 	for_each_pipe(pipe) {
13347dc10d7SGordon Ross 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
13447dc10d7SGordon Ross 
13547dc10d7SGordon Ross 		if (crtc->pch_fifo_underrun_disabled)
13647dc10d7SGordon Ross 			return false;
13747dc10d7SGordon Ross 	}
13847dc10d7SGordon Ross 
13947dc10d7SGordon Ross 	return true;
14047dc10d7SGordon Ross }
14147dc10d7SGordon Ross 
ironlake_set_fifo_underrun_reporting(struct drm_device * dev,enum pipe pipe,bool enable)14247dc10d7SGordon Ross static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
14347dc10d7SGordon Ross 						 enum pipe pipe, bool enable)
14447dc10d7SGordon Ross {
14547dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
14647dc10d7SGordon Ross 	uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
14747dc10d7SGordon Ross 					  DE_PIPEB_FIFO_UNDERRUN;
14847dc10d7SGordon Ross 
14947dc10d7SGordon Ross 	if (enable)
15047dc10d7SGordon Ross 		ironlake_enable_display_irq(dev_priv, bit);
15147dc10d7SGordon Ross 	else
15247dc10d7SGordon Ross 		ironlake_disable_display_irq(dev_priv, bit);
15347dc10d7SGordon Ross }
15447dc10d7SGordon Ross 
ivybridge_set_fifo_underrun_reporting(struct drm_device * dev,bool enable)15547dc10d7SGordon Ross static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
15647dc10d7SGordon Ross 						  bool enable)
15747dc10d7SGordon Ross {
15847dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
15947dc10d7SGordon Ross 
16047dc10d7SGordon Ross 	if (enable) {
16147dc10d7SGordon Ross 		if (!ivb_can_enable_err_int(dev))
16247dc10d7SGordon Ross 			return;
16347dc10d7SGordon Ross 
16447dc10d7SGordon Ross 		I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN_A |
16547dc10d7SGordon Ross 					 ERR_INT_FIFO_UNDERRUN_B |
16647dc10d7SGordon Ross 					 ERR_INT_FIFO_UNDERRUN_C);
16747dc10d7SGordon Ross 
16847dc10d7SGordon Ross 		ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
16947dc10d7SGordon Ross 	} else {
17047dc10d7SGordon Ross 		ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
17147dc10d7SGordon Ross 	}
17247dc10d7SGordon Ross }
17347dc10d7SGordon Ross 
ibx_set_fifo_underrun_reporting(struct intel_crtc * crtc,bool enable)17447dc10d7SGordon Ross static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
17547dc10d7SGordon Ross 					    bool enable)
17647dc10d7SGordon Ross {
17747dc10d7SGordon Ross 	struct drm_device *dev = crtc->base.dev;
17847dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
17947dc10d7SGordon Ross 	uint32_t bit = (crtc->pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
18047dc10d7SGordon Ross 						SDE_TRANSB_FIFO_UNDER;
18147dc10d7SGordon Ross 
18247dc10d7SGordon Ross 	if (enable)
18347dc10d7SGordon Ross 		I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~bit);
18447dc10d7SGordon Ross 	else
18547dc10d7SGordon Ross 		I915_WRITE(SDEIMR, I915_READ(SDEIMR) | bit);
18647dc10d7SGordon Ross 
18747dc10d7SGordon Ross 	POSTING_READ(SDEIMR);
18847dc10d7SGordon Ross }
18947dc10d7SGordon Ross 
cpt_set_fifo_underrun_reporting(struct drm_device * dev,enum transcoder pch_transcoder,bool enable)19047dc10d7SGordon Ross static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
19147dc10d7SGordon Ross 					    enum transcoder pch_transcoder,
19247dc10d7SGordon Ross 					    bool enable)
19347dc10d7SGordon Ross {
19447dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
19547dc10d7SGordon Ross 
19647dc10d7SGordon Ross 	if (enable) {
19747dc10d7SGordon Ross 		if (!cpt_can_enable_serr_int(dev))
19847dc10d7SGordon Ross 			return;
19947dc10d7SGordon Ross 
20047dc10d7SGordon Ross 		I915_WRITE(SERR_INT, SERR_INT_TRANS_A_FIFO_UNDERRUN |
20147dc10d7SGordon Ross 				     SERR_INT_TRANS_B_FIFO_UNDERRUN |
20247dc10d7SGordon Ross 				     SERR_INT_TRANS_C_FIFO_UNDERRUN);
20347dc10d7SGordon Ross 
20447dc10d7SGordon Ross 		I915_WRITE(SDEIMR, I915_READ(SDEIMR) & ~SDE_ERROR_CPT);
20547dc10d7SGordon Ross 	} else {
20647dc10d7SGordon Ross 		I915_WRITE(SDEIMR, I915_READ(SDEIMR) | SDE_ERROR_CPT);
20747dc10d7SGordon Ross 	}
20847dc10d7SGordon Ross 
20947dc10d7SGordon Ross 	POSTING_READ(SDEIMR);
21047dc10d7SGordon Ross }
21147dc10d7SGordon Ross 
21247dc10d7SGordon Ross /**
21347dc10d7SGordon Ross  * intel_set_cpu_fifo_underrun_reporting - enable/disable FIFO underrun messages
21447dc10d7SGordon Ross  * @dev: drm device
21547dc10d7SGordon Ross  * @pipe: pipe
21647dc10d7SGordon Ross  * @enable: true if we want to report FIFO underrun errors, false otherwise
21747dc10d7SGordon Ross  *
21847dc10d7SGordon Ross  * This function makes us disable or enable CPU fifo underruns for a specific
21947dc10d7SGordon Ross  * pipe. Notice that on some Gens (e.g. IVB, HSW), disabling FIFO underrun
22047dc10d7SGordon Ross  * reporting for one pipe may also disable all the other CPU error interruts for
22147dc10d7SGordon Ross  * the other pipes, due to the fact that there's just one interrupt mask/enable
22247dc10d7SGordon Ross  * bit for all the pipes.
22347dc10d7SGordon Ross  *
22447dc10d7SGordon Ross  * Returns the previous state of underrun reporting.
22547dc10d7SGordon Ross  */
intel_set_cpu_fifo_underrun_reporting(struct drm_device * dev,enum pipe pipe,bool enable)22647dc10d7SGordon Ross bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
22747dc10d7SGordon Ross 					   enum pipe pipe, bool enable)
22847dc10d7SGordon Ross {
22947dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
23047dc10d7SGordon Ross 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
23147dc10d7SGordon Ross 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
23247dc10d7SGordon Ross 	unsigned long flags;
23347dc10d7SGordon Ross 	bool ret;
23447dc10d7SGordon Ross 
23547dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
23647dc10d7SGordon Ross 
23747dc10d7SGordon Ross 	ret = !intel_crtc->cpu_fifo_underrun_disabled;
23847dc10d7SGordon Ross 
23947dc10d7SGordon Ross 	if (enable == ret)
24047dc10d7SGordon Ross 		goto done;
24147dc10d7SGordon Ross 
24247dc10d7SGordon Ross 	intel_crtc->cpu_fifo_underrun_disabled = !enable;
24347dc10d7SGordon Ross 
24447dc10d7SGordon Ross 	if (IS_GEN5(dev) || IS_GEN6(dev))
24547dc10d7SGordon Ross 		ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
24647dc10d7SGordon Ross 	else if (IS_GEN7(dev))
24747dc10d7SGordon Ross 		ivybridge_set_fifo_underrun_reporting(dev, enable);
24847dc10d7SGordon Ross 
24947dc10d7SGordon Ross done:
25047dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
25147dc10d7SGordon Ross 	return ret;
25247dc10d7SGordon Ross }
25347dc10d7SGordon Ross 
25447dc10d7SGordon Ross /**
25547dc10d7SGordon Ross  * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
25647dc10d7SGordon Ross  * @dev: drm device
25747dc10d7SGordon Ross  * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
25847dc10d7SGordon Ross  * @enable: true if we want to report FIFO underrun errors, false otherwise
25947dc10d7SGordon Ross  *
26047dc10d7SGordon Ross  * This function makes us disable or enable PCH fifo underruns for a specific
26147dc10d7SGordon Ross  * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
26247dc10d7SGordon Ross  * underrun reporting for one transcoder may also disable all the other PCH
26347dc10d7SGordon Ross  * error interruts for the other transcoders, due to the fact that there's just
26447dc10d7SGordon Ross  * one interrupt mask/enable bit for all the transcoders.
26547dc10d7SGordon Ross  *
26647dc10d7SGordon Ross  * Returns the previous state of underrun reporting.
26747dc10d7SGordon Ross  */
intel_set_pch_fifo_underrun_reporting(struct drm_device * dev,enum transcoder pch_transcoder,bool enable)26847dc10d7SGordon Ross bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
26947dc10d7SGordon Ross 					   enum transcoder pch_transcoder,
27047dc10d7SGordon Ross 					   bool enable)
27147dc10d7SGordon Ross {
27247dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
27347dc10d7SGordon Ross 	enum pipe p;
27447dc10d7SGordon Ross 	struct drm_crtc *crtc;
27547dc10d7SGordon Ross 	struct intel_crtc *intel_crtc;
27647dc10d7SGordon Ross 	unsigned long flags;
27747dc10d7SGordon Ross 	bool ret;
27847dc10d7SGordon Ross 
27947dc10d7SGordon Ross 	if (HAS_PCH_LPT(dev)) {
28047dc10d7SGordon Ross 		crtc = NULL;
28147dc10d7SGordon Ross 		for_each_pipe(p) {
28247dc10d7SGordon Ross 			struct drm_crtc *c = dev_priv->pipe_to_crtc_mapping[p];
28347dc10d7SGordon Ross 			if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) {
28447dc10d7SGordon Ross 				crtc = c;
28547dc10d7SGordon Ross 				break;
28647dc10d7SGordon Ross 			}
28747dc10d7SGordon Ross 		}
28847dc10d7SGordon Ross 		if (!crtc) {
28947dc10d7SGordon Ross 			DRM_ERROR("PCH FIFO underrun, but no CRTC using the PCH found\n");
29047dc10d7SGordon Ross 			return false;
29147dc10d7SGordon Ross 		}
29247dc10d7SGordon Ross 	} else {
29347dc10d7SGordon Ross 		crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
29447dc10d7SGordon Ross 	}
29547dc10d7SGordon Ross 	intel_crtc = to_intel_crtc(crtc);
29647dc10d7SGordon Ross 
29747dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
29847dc10d7SGordon Ross 
29947dc10d7SGordon Ross 	ret = !intel_crtc->pch_fifo_underrun_disabled;
30047dc10d7SGordon Ross 
30147dc10d7SGordon Ross 	if (enable == ret)
30247dc10d7SGordon Ross 		goto done;
30347dc10d7SGordon Ross 
30447dc10d7SGordon Ross 	intel_crtc->pch_fifo_underrun_disabled = !enable;
30547dc10d7SGordon Ross 
30647dc10d7SGordon Ross 	if (HAS_PCH_IBX(dev))
30747dc10d7SGordon Ross 		ibx_set_fifo_underrun_reporting(intel_crtc, enable);
30847dc10d7SGordon Ross 	else
30947dc10d7SGordon Ross 		cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
31047dc10d7SGordon Ross 
31147dc10d7SGordon Ross done:
31247dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
31347dc10d7SGordon Ross 	return ret;
31447dc10d7SGordon Ross }
31547dc10d7SGordon Ross 
31647dc10d7SGordon Ross 
31747dc10d7SGordon Ross void
i915_enable_pipestat(drm_i915_private_t * dev_priv,int pipe,u32 mask)31847dc10d7SGordon Ross i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
31947dc10d7SGordon Ross {
32047dc10d7SGordon Ross 	u32 reg = PIPESTAT(pipe);
32147dc10d7SGordon Ross 	u32 pipestat = I915_READ(reg) & 0x7fff0000;
32247dc10d7SGordon Ross 
32347dc10d7SGordon Ross 	if ((pipestat & mask) == mask)
32447dc10d7SGordon Ross 		return;
32547dc10d7SGordon Ross 
32647dc10d7SGordon Ross 	/* Enable the interrupt, clear any pending status */
32747dc10d7SGordon Ross 	pipestat |= mask | (mask >> 16);
32847dc10d7SGordon Ross 	I915_WRITE(reg, pipestat);
32947dc10d7SGordon Ross 	POSTING_READ(reg);
33047dc10d7SGordon Ross }
33147dc10d7SGordon Ross 
33247dc10d7SGordon Ross void
i915_disable_pipestat(drm_i915_private_t * dev_priv,int pipe,u32 mask)33347dc10d7SGordon Ross i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
33447dc10d7SGordon Ross {
33547dc10d7SGordon Ross 	u32 reg = PIPESTAT(pipe);
33647dc10d7SGordon Ross 	u32 pipestat = I915_READ(reg) & 0x7fff0000;
33747dc10d7SGordon Ross 
33847dc10d7SGordon Ross 	if ((pipestat & mask) == 0)
33947dc10d7SGordon Ross 		return;
34047dc10d7SGordon Ross 
34147dc10d7SGordon Ross 	pipestat &= ~mask;
34247dc10d7SGordon Ross 	I915_WRITE(reg, pipestat);
34347dc10d7SGordon Ross 		POSTING_READ(reg);
34447dc10d7SGordon Ross 	}
34547dc10d7SGordon Ross 
34647dc10d7SGordon Ross /**
34747dc10d7SGordon Ross  * i915_pipe_enabled - check if a pipe is enabled
34847dc10d7SGordon Ross  * @dev: DRM device
34947dc10d7SGordon Ross  * @pipe: pipe to check
35047dc10d7SGordon Ross  *
35147dc10d7SGordon Ross  * Reading certain registers when the pipe is disabled can hang the chip.
35247dc10d7SGordon Ross  * Use this routine to make sure the PLL is running and the pipe is active
35347dc10d7SGordon Ross  * before reading such registers if unsure.
35447dc10d7SGordon Ross  */
35547dc10d7SGordon Ross static int
i915_pipe_enabled(struct drm_device * dev,int pipe)35647dc10d7SGordon Ross i915_pipe_enabled(struct drm_device *dev, int pipe)
35747dc10d7SGordon Ross {
35847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
35947dc10d7SGordon Ross 
36047dc10d7SGordon Ross 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
36147dc10d7SGordon Ross 		/* Locking is horribly broken here, but whatever. */
36247dc10d7SGordon Ross 		struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
36347dc10d7SGordon Ross 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
36447dc10d7SGordon Ross 
36547dc10d7SGordon Ross 		return intel_crtc->active;
36647dc10d7SGordon Ross 	} else {
36747dc10d7SGordon Ross 		return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE;
36847dc10d7SGordon Ross 	}
36947dc10d7SGordon Ross }
37047dc10d7SGordon Ross 
37147dc10d7SGordon Ross /* Called from drm generic code, passed a 'crtc', which
37247dc10d7SGordon Ross  * we use as a pipe index
37347dc10d7SGordon Ross  */
i915_get_vblank_counter(struct drm_device * dev,int pipe)37447dc10d7SGordon Ross static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
37547dc10d7SGordon Ross {
37647dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
37747dc10d7SGordon Ross 	unsigned long high_frame;
37847dc10d7SGordon Ross 	unsigned long low_frame;
37947dc10d7SGordon Ross 	u32 high1, high2, low;
38047dc10d7SGordon Ross 
38147dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe)) {
38247dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
38347dc10d7SGordon Ross 				"pipe %c\n", pipe_name(pipe));
38447dc10d7SGordon Ross 		return 0;
38547dc10d7SGordon Ross 	}
38647dc10d7SGordon Ross 
38747dc10d7SGordon Ross 	high_frame = PIPEFRAME(pipe);
38847dc10d7SGordon Ross 	low_frame = PIPEFRAMEPIXEL(pipe);
38947dc10d7SGordon Ross 
39047dc10d7SGordon Ross 	/*
39147dc10d7SGordon Ross 	 * High & low register fields aren't synchronized, so make sure
39247dc10d7SGordon Ross 	 * we get a low value that's stable across two reads of the high
39347dc10d7SGordon Ross 	 * register.
39447dc10d7SGordon Ross 	 */
39547dc10d7SGordon Ross 	do {
39647dc10d7SGordon Ross 		high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
39747dc10d7SGordon Ross 		low   = I915_READ(low_frame)  & PIPE_FRAME_LOW_MASK;
39847dc10d7SGordon Ross 		high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
39947dc10d7SGordon Ross 	} while (high1 != high2);
40047dc10d7SGordon Ross 
40147dc10d7SGordon Ross 	high1 >>= PIPE_FRAME_HIGH_SHIFT;
40247dc10d7SGordon Ross 	low >>= PIPE_FRAME_LOW_SHIFT;
40347dc10d7SGordon Ross 	return (high1 << 8) | low;
40447dc10d7SGordon Ross }
40547dc10d7SGordon Ross 
gm45_get_vblank_counter(struct drm_device * dev,int pipe)40647dc10d7SGordon Ross static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
40747dc10d7SGordon Ross {
40847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
40947dc10d7SGordon Ross 	int reg = PIPE_FRMCOUNT_GM45(pipe);
41047dc10d7SGordon Ross 
41147dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe)) {
41247dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
41347dc10d7SGordon Ross 				 "pipe %c\n", pipe_name(pipe));
41447dc10d7SGordon Ross 		return 0;
41547dc10d7SGordon Ross 	}
41647dc10d7SGordon Ross 
41747dc10d7SGordon Ross 	return I915_READ(reg);
41847dc10d7SGordon Ross }
41947dc10d7SGordon Ross 
i915_get_crtc_scanoutpos(struct drm_device * dev,int pipe,int * vpos,int * hpos)42047dc10d7SGordon Ross static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
42147dc10d7SGordon Ross 			     int *vpos, int *hpos)
42247dc10d7SGordon Ross {
42347dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
42447dc10d7SGordon Ross 	u32 vbl = 0, position = 0;
42547dc10d7SGordon Ross 	int vbl_start, vbl_end, htotal, vtotal;
42647dc10d7SGordon Ross 	bool in_vbl = true;
42747dc10d7SGordon Ross 	int ret = 0;
42847dc10d7SGordon Ross 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
42947dc10d7SGordon Ross 								      pipe);
43047dc10d7SGordon Ross 
43147dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe)) {
43247dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
43347dc10d7SGordon Ross 				 "pipe %c\n", pipe_name(pipe));
43447dc10d7SGordon Ross 		return 0;
43547dc10d7SGordon Ross 	}
43647dc10d7SGordon Ross 
43747dc10d7SGordon Ross 	/* Get vtotal. */
43847dc10d7SGordon Ross 	vtotal = 1 + ((I915_READ(VTOTAL(cpu_transcoder)) >> 16) & 0x1fff);
43947dc10d7SGordon Ross 
44047dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 4) {
44147dc10d7SGordon Ross 		/* No obvious pixelcount register. Only query vertical
44247dc10d7SGordon Ross 		 * scanout position from Display scan line register.
44347dc10d7SGordon Ross 		 */
44447dc10d7SGordon Ross 		position = I915_READ(PIPEDSL(pipe));
44547dc10d7SGordon Ross 
44647dc10d7SGordon Ross 		/* Decode into vertical scanout position. Don't have
44747dc10d7SGordon Ross 		 * horizontal scanout position.
44847dc10d7SGordon Ross 		 */
44947dc10d7SGordon Ross 		*vpos = position & 0x1fff;
45047dc10d7SGordon Ross 		*hpos = 0;
45147dc10d7SGordon Ross 	} else {
45247dc10d7SGordon Ross 		/* Have access to pixelcount since start of frame.
45347dc10d7SGordon Ross 		 * We can split this into vertical and horizontal
45447dc10d7SGordon Ross 		 * scanout position.
45547dc10d7SGordon Ross 		 */
45647dc10d7SGordon Ross 		position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
45747dc10d7SGordon Ross 
45847dc10d7SGordon Ross 		htotal = 1 + ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff);
45947dc10d7SGordon Ross 		*vpos = position / htotal;
46047dc10d7SGordon Ross 		*hpos = position - (*vpos * htotal);
46147dc10d7SGordon Ross 	}
46247dc10d7SGordon Ross 
46347dc10d7SGordon Ross 	/* Query vblank area. */
46447dc10d7SGordon Ross 	vbl = I915_READ(VBLANK(cpu_transcoder));
46547dc10d7SGordon Ross 
46647dc10d7SGordon Ross 	/* Test position against vblank region. */
46747dc10d7SGordon Ross 	vbl_start = vbl & 0x1fff;
46847dc10d7SGordon Ross 	vbl_end = (vbl >> 16) & 0x1fff;
46947dc10d7SGordon Ross 
47047dc10d7SGordon Ross 	if ((*vpos < vbl_start) || (*vpos > vbl_end))
47147dc10d7SGordon Ross 		in_vbl = false;
47247dc10d7SGordon Ross 
47347dc10d7SGordon Ross 	/* Inside "upper part" of vblank area? Apply corrective offset: */
47447dc10d7SGordon Ross 	if (in_vbl && (*vpos >= vbl_start))
47547dc10d7SGordon Ross 		*vpos = *vpos - vtotal;
47647dc10d7SGordon Ross 
47747dc10d7SGordon Ross 	/* Readouts valid? */
47847dc10d7SGordon Ross 	if (vbl > 0)
47947dc10d7SGordon Ross 		ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
48047dc10d7SGordon Ross 
48147dc10d7SGordon Ross 	/* In vblank? */
48247dc10d7SGordon Ross 	if (in_vbl)
48347dc10d7SGordon Ross 		ret |= DRM_SCANOUTPOS_INVBL;
48447dc10d7SGordon Ross 
48547dc10d7SGordon Ross 	return ret;
48647dc10d7SGordon Ross }
48747dc10d7SGordon Ross 
i915_get_vblank_timestamp(struct drm_device * dev,int pipe,int * max_error,struct timeval * vblank_time,unsigned flags)48847dc10d7SGordon Ross static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
48947dc10d7SGordon Ross 			      int *max_error,
49047dc10d7SGordon Ross 			      struct timeval *vblank_time,
49147dc10d7SGordon Ross 			      unsigned flags)
49247dc10d7SGordon Ross {
49347dc10d7SGordon Ross 	struct drm_crtc *crtc;
49447dc10d7SGordon Ross 
49547dc10d7SGordon Ross 	if (pipe < 0 || pipe >= INTEL_INFO(dev)->num_pipes) {
49647dc10d7SGordon Ross 		DRM_ERROR("Invalid crtc %d\n", pipe);
49747dc10d7SGordon Ross 		return -EINVAL;
49847dc10d7SGordon Ross 	}
49947dc10d7SGordon Ross 
50047dc10d7SGordon Ross 	/* Get drm_crtc to timestamp: */
50147dc10d7SGordon Ross 	crtc = intel_get_crtc_for_pipe(dev, pipe);
50247dc10d7SGordon Ross 	if (crtc == NULL) {
50347dc10d7SGordon Ross 		DRM_ERROR("Invalid crtc %d\n", pipe);
50447dc10d7SGordon Ross 		return -EINVAL;
50547dc10d7SGordon Ross 	}
50647dc10d7SGordon Ross 
50747dc10d7SGordon Ross 	if (!crtc->enabled) {
50847dc10d7SGordon Ross 		DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
50947dc10d7SGordon Ross 		return -EBUSY;
51047dc10d7SGordon Ross 	}
51147dc10d7SGordon Ross 
51247dc10d7SGordon Ross 	/* Helper routine in DRM core does all the work: */
51347dc10d7SGordon Ross 	return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
51447dc10d7SGordon Ross 						     vblank_time, flags,
51547dc10d7SGordon Ross 						     crtc);
51647dc10d7SGordon Ross }
51747dc10d7SGordon Ross 
intel_hpd_irq_event(struct drm_device * dev,struct drm_connector * connector)51847dc10d7SGordon Ross static int intel_hpd_irq_event(struct drm_device *dev, struct drm_connector *connector)
51947dc10d7SGordon Ross {
52047dc10d7SGordon Ross 	enum drm_connector_status old_status;
52147dc10d7SGordon Ross 
52247dc10d7SGordon Ross 	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
52347dc10d7SGordon Ross 	old_status = connector->status;
52447dc10d7SGordon Ross 
52547dc10d7SGordon Ross 	connector->status = connector->funcs->detect(connector, false);
52647dc10d7SGordon Ross 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
52747dc10d7SGordon Ross 		      connector->base.id,
52847dc10d7SGordon Ross 		      drm_get_connector_name(connector),
52947dc10d7SGordon Ross 		      old_status, connector->status);
53047dc10d7SGordon Ross 	return (old_status != connector->status);
53147dc10d7SGordon Ross }
53247dc10d7SGordon Ross 
53347dc10d7SGordon Ross /*
53447dc10d7SGordon Ross  * Handle hotplug events outside the interrupt handler proper.
53547dc10d7SGordon Ross  */
53647dc10d7SGordon Ross #define I915_REENABLE_HOTPLUG_DELAY (2*60*1000)
53747dc10d7SGordon Ross 
i915_hotplug_work_func(struct work_struct * work)53847dc10d7SGordon Ross static void i915_hotplug_work_func(struct work_struct *work)
53947dc10d7SGordon Ross {
54047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
54147dc10d7SGordon Ross 						    hotplug_work);
54247dc10d7SGordon Ross 	struct drm_device *dev = dev_priv->dev;
54347dc10d7SGordon Ross 	struct drm_mode_config *mode_config = &dev->mode_config;
54447dc10d7SGordon Ross 	struct intel_connector *intel_connector;
54547dc10d7SGordon Ross 	struct intel_encoder *intel_encoder;
54647dc10d7SGordon Ross 	struct drm_connector *connector;
54747dc10d7SGordon Ross 	unsigned long irqflags;
54847dc10d7SGordon Ross 	bool hpd_disabled = false;
54947dc10d7SGordon Ross 	bool changed = false;
55047dc10d7SGordon Ross 	u32 hpd_event_bits;
55147dc10d7SGordon Ross 
55247dc10d7SGordon Ross 	/* HPD irq before everything is fully set up. */
55347dc10d7SGordon Ross 	if (!dev_priv->enable_hotplug_processing)
55447dc10d7SGordon Ross 		return;
55547dc10d7SGordon Ross 
55647dc10d7SGordon Ross 	mutex_lock(&mode_config->mutex);
55747dc10d7SGordon Ross 	DRM_DEBUG_KMS("running encoder hotplug functions\n");
55847dc10d7SGordon Ross 
55947dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
56047dc10d7SGordon Ross 
56147dc10d7SGordon Ross 	hpd_event_bits = dev_priv->hpd_event_bits;
56247dc10d7SGordon Ross 	dev_priv->hpd_event_bits = 0;
56347dc10d7SGordon Ross 	list_for_each_entry(connector, struct drm_connector, &mode_config->connector_list, head) {
56447dc10d7SGordon Ross 		intel_connector = to_intel_connector(connector);
56547dc10d7SGordon Ross 		intel_encoder = intel_connector->encoder;
56647dc10d7SGordon Ross 		if (intel_encoder->hpd_pin > HPD_NONE &&
56747dc10d7SGordon Ross 		    dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
56847dc10d7SGordon Ross 		    connector->polled == DRM_CONNECTOR_POLL_HPD) {
56947dc10d7SGordon Ross 			DRM_INFO("HPD interrupt storm detected on connector %s: "
57047dc10d7SGordon Ross 				 "switching from hotplug detection to polling\n",
57147dc10d7SGordon Ross 				drm_get_connector_name(connector));
57247dc10d7SGordon Ross 			dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark = HPD_DISABLED;
57347dc10d7SGordon Ross 			connector->polled = DRM_CONNECTOR_POLL_CONNECT
57447dc10d7SGordon Ross 				| DRM_CONNECTOR_POLL_DISCONNECT;
57547dc10d7SGordon Ross 			hpd_disabled = true;
57647dc10d7SGordon Ross 		}
57747dc10d7SGordon Ross 		if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
57847dc10d7SGordon Ross 			DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n",
57947dc10d7SGordon Ross 				      drm_get_connector_name(connector), intel_encoder->hpd_pin);
58047dc10d7SGordon Ross 		}
58147dc10d7SGordon Ross 	}
58247dc10d7SGordon Ross 	 /* if there were no outputs to poll, poll was disabled,
58347dc10d7SGordon Ross 	  * therefore make sure it's enabled when disabling HPD on
58447dc10d7SGordon Ross 	  * some connectors */
58547dc10d7SGordon Ross 	if (hpd_disabled) {
58647dc10d7SGordon Ross 		drm_kms_helper_poll_enable(dev);
58747dc10d7SGordon Ross 		mod_timer(&dev_priv->hotplug_reenable_timer,
58847dc10d7SGordon Ross 			  msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
58947dc10d7SGordon Ross 	}
59047dc10d7SGordon Ross 
59147dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
59247dc10d7SGordon Ross 
59347dc10d7SGordon Ross 	list_for_each_entry(connector, struct drm_connector, &mode_config->connector_list, head) {
59447dc10d7SGordon Ross 		intel_connector = to_intel_connector(connector);
59547dc10d7SGordon Ross 		intel_encoder = intel_connector->encoder;
59647dc10d7SGordon Ross 		if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
59747dc10d7SGordon Ross 			if (intel_encoder->hot_plug)
59847dc10d7SGordon Ross 				intel_encoder->hot_plug(intel_encoder);
59947dc10d7SGordon Ross 			if (intel_hpd_irq_event(dev, connector))
60047dc10d7SGordon Ross 				changed = true;
60147dc10d7SGordon Ross 		}
60247dc10d7SGordon Ross 	}
60347dc10d7SGordon Ross 	mutex_unlock(&mode_config->mutex);
60447dc10d7SGordon Ross 
60547dc10d7SGordon Ross 	if (changed)
60647dc10d7SGordon Ross 		drm_kms_helper_hotplug_event(dev);
60747dc10d7SGordon Ross }
60847dc10d7SGordon Ross 
ironlake_handle_rps_change(struct drm_device * dev)60947dc10d7SGordon Ross static void ironlake_handle_rps_change(struct drm_device *dev)
61047dc10d7SGordon Ross {
61147dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = dev->dev_private;
61247dc10d7SGordon Ross 	u32 busy_up, busy_down, max_avg, min_avg;
61347dc10d7SGordon Ross 	u8 new_delay;
61447dc10d7SGordon Ross 	unsigned long flags;
61547dc10d7SGordon Ross 
61647dc10d7SGordon Ross 	spin_lock_irqsave(&mchdev_lock, flags);
61747dc10d7SGordon Ross 
61847dc10d7SGordon Ross 	I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
61947dc10d7SGordon Ross 
62047dc10d7SGordon Ross 	new_delay = dev_priv->ips.cur_delay;
62147dc10d7SGordon Ross 
62247dc10d7SGordon Ross 	I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
62347dc10d7SGordon Ross 	busy_up = I915_READ(RCPREVBSYTUPAVG);
62447dc10d7SGordon Ross 	busy_down = I915_READ(RCPREVBSYTDNAVG);
62547dc10d7SGordon Ross 	max_avg = I915_READ(RCBMAXAVG);
62647dc10d7SGordon Ross 	min_avg = I915_READ(RCBMINAVG);
62747dc10d7SGordon Ross 
62847dc10d7SGordon Ross 	/* Handle RCS change request from hw */
62947dc10d7SGordon Ross 	if (busy_up > max_avg) {
63047dc10d7SGordon Ross 		if (dev_priv->ips.cur_delay != dev_priv->ips.max_delay)
63147dc10d7SGordon Ross 			new_delay = dev_priv->ips.cur_delay - 1;
63247dc10d7SGordon Ross 		if (new_delay < dev_priv->ips.max_delay)
63347dc10d7SGordon Ross 			new_delay = dev_priv->ips.max_delay;
63447dc10d7SGordon Ross 	} else if (busy_down < min_avg) {
63547dc10d7SGordon Ross 		if (dev_priv->ips.cur_delay != dev_priv->ips.min_delay)
63647dc10d7SGordon Ross 			new_delay = dev_priv->ips.cur_delay + 1;
63747dc10d7SGordon Ross 		if (new_delay > dev_priv->ips.min_delay)
63847dc10d7SGordon Ross 			new_delay = dev_priv->ips.min_delay;
63947dc10d7SGordon Ross 	}
64047dc10d7SGordon Ross 
64147dc10d7SGordon Ross 	if (ironlake_set_drps(dev, new_delay))
64247dc10d7SGordon Ross 		dev_priv->ips.cur_delay = new_delay;
64347dc10d7SGordon Ross 
64447dc10d7SGordon Ross 	spin_unlock_irqrestore(&mchdev_lock, flags);
64547dc10d7SGordon Ross 
64647dc10d7SGordon Ross 	return;
64747dc10d7SGordon Ross }
64847dc10d7SGordon Ross 
notify_ring(struct drm_device * dev,struct intel_ring_buffer * ring)64947dc10d7SGordon Ross static void notify_ring(struct drm_device *dev,
65047dc10d7SGordon Ross 			struct intel_ring_buffer *ring)
65147dc10d7SGordon Ross {
65247dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
65347dc10d7SGordon Ross 
65447dc10d7SGordon Ross 	if (ring->obj == NULL)
65547dc10d7SGordon Ross 		return;
65647dc10d7SGordon Ross 
65747dc10d7SGordon Ross 	DRM_WAKEUP(&ring->irq_queue);
65847dc10d7SGordon Ross 	if (i915_enable_hangcheck && !dev_priv->gpu_hang) {
65947dc10d7SGordon Ross 		mod_timer(&dev_priv->gpu_error.hangcheck_timer,
66047dc10d7SGordon Ross 			msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
66147dc10d7SGordon Ross 	}
66247dc10d7SGordon Ross }
66347dc10d7SGordon Ross 
gen6_pm_rps_work(struct work_struct * work)66447dc10d7SGordon Ross static void gen6_pm_rps_work(struct work_struct *work)
66547dc10d7SGordon Ross {
66647dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
66747dc10d7SGordon Ross 						    rps.work);
66847dc10d7SGordon Ross 	u32 pm_iir, pm_imr;
66947dc10d7SGordon Ross 	u8 new_delay;
67047dc10d7SGordon Ross 
67147dc10d7SGordon Ross 	spin_lock_irq(&dev_priv->rps.lock);
67247dc10d7SGordon Ross 	pm_iir = dev_priv->rps.pm_iir;
67347dc10d7SGordon Ross 	dev_priv->rps.pm_iir = 0;
67447dc10d7SGordon Ross 	pm_imr = I915_READ(GEN6_PMIMR);
67547dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIMR, pm_imr & ~GEN6_PM_RPS_EVENTS);
67647dc10d7SGordon Ross 	spin_unlock_irq(&dev_priv->rps.lock);
67747dc10d7SGordon Ross 
67847dc10d7SGordon Ross 	if ((pm_iir & GEN6_PM_RPS_EVENTS) == 0)
67947dc10d7SGordon Ross 		return;
68047dc10d7SGordon Ross 
68147dc10d7SGordon Ross 	mutex_lock(&dev_priv->rps.hw_lock);
68247dc10d7SGordon Ross 
68347dc10d7SGordon Ross 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
68447dc10d7SGordon Ross 		new_delay = dev_priv->rps.cur_delay + 1;
68547dc10d7SGordon Ross 
68647dc10d7SGordon Ross 		/*
68747dc10d7SGordon Ross 		 * For better performance, jump directly
68847dc10d7SGordon Ross 		 * to RPe if we're below it.
68947dc10d7SGordon Ross 		 */
69047dc10d7SGordon Ross 		if (IS_VALLEYVIEW(dev_priv->dev) &&
69147dc10d7SGordon Ross 		    dev_priv->rps.cur_delay < dev_priv->rps.rpe_delay)
69247dc10d7SGordon Ross 			new_delay = dev_priv->rps.rpe_delay;
69347dc10d7SGordon Ross 	} else
69447dc10d7SGordon Ross 		new_delay = dev_priv->rps.cur_delay - 1;
69547dc10d7SGordon Ross 
69647dc10d7SGordon Ross 	/* sysfs frequency interfaces may have snuck in while servicing the
69747dc10d7SGordon Ross 	 * interrupt
69847dc10d7SGordon Ross 	 */
69947dc10d7SGordon Ross 	if (new_delay >= dev_priv->rps.min_delay &&
70047dc10d7SGordon Ross 	    new_delay <= dev_priv->rps.max_delay) {
70147dc10d7SGordon Ross 		if (IS_VALLEYVIEW(dev_priv->dev))
70247dc10d7SGordon Ross 			valleyview_set_rps(dev_priv->dev, new_delay);
70347dc10d7SGordon Ross 		else
70447dc10d7SGordon Ross 			gen6_set_rps(dev_priv->dev, new_delay);
70547dc10d7SGordon Ross 	}
70647dc10d7SGordon Ross 
70747dc10d7SGordon Ross 	mutex_unlock(&dev_priv->rps.hw_lock);
70847dc10d7SGordon Ross 	}
70947dc10d7SGordon Ross 
71047dc10d7SGordon Ross 
71147dc10d7SGordon Ross /**
71247dc10d7SGordon Ross  * ivybridge_parity_work - Workqueue called when a parity error interrupt
71347dc10d7SGordon Ross  * occurred.
71447dc10d7SGordon Ross  * @work: workqueue struct
71547dc10d7SGordon Ross  *
71647dc10d7SGordon Ross  * Doesn't actually do anything except notify userspace. As a consequence of
71747dc10d7SGordon Ross  * this event, userspace should try to remap the bad rows since statistically
71847dc10d7SGordon Ross  * it is likely the same row is more likely to go bad again.
71947dc10d7SGordon Ross  */
ivybridge_parity_work(struct work_struct * work)72047dc10d7SGordon Ross static void ivybridge_parity_work(struct work_struct *work)
72147dc10d7SGordon Ross {
72247dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
72347dc10d7SGordon Ross 						    l3_parity.error_work);
72447dc10d7SGordon Ross 	u32 error_status, row, bank, subbank;
72547dc10d7SGordon Ross 	uint32_t misccpctl;
72647dc10d7SGordon Ross 	unsigned long flags;
72747dc10d7SGordon Ross 
72847dc10d7SGordon Ross 	/* We must turn off DOP level clock gating to access the L3 registers.
72947dc10d7SGordon Ross 	 * In order to prevent a get/put style interface, acquire struct mutex
73047dc10d7SGordon Ross 	 * any time we access those registers.
73147dc10d7SGordon Ross 	 */
73247dc10d7SGordon Ross 	mutex_lock(&dev_priv->dev->struct_mutex);
73347dc10d7SGordon Ross 
73447dc10d7SGordon Ross 	misccpctl = I915_READ(GEN7_MISCCPCTL);
73547dc10d7SGordon Ross 	I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
73647dc10d7SGordon Ross 	POSTING_READ(GEN7_MISCCPCTL);
73747dc10d7SGordon Ross 
73847dc10d7SGordon Ross 	error_status = I915_READ(GEN7_L3CDERRST1);
73947dc10d7SGordon Ross 	row = GEN7_PARITY_ERROR_ROW(error_status);
74047dc10d7SGordon Ross 	bank = GEN7_PARITY_ERROR_BANK(error_status);
74147dc10d7SGordon Ross 	subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
74247dc10d7SGordon Ross 
74347dc10d7SGordon Ross 	I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID |
74447dc10d7SGordon Ross 				    GEN7_L3CDERRST1_ENABLE);
74547dc10d7SGordon Ross 	POSTING_READ(GEN7_L3CDERRST1);
74647dc10d7SGordon Ross 
74747dc10d7SGordon Ross 	I915_WRITE(GEN7_MISCCPCTL, misccpctl);
74847dc10d7SGordon Ross 
74947dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
75047dc10d7SGordon Ross 	dev_priv->gt_irq_mask &= ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
75147dc10d7SGordon Ross 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
75247dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
75347dc10d7SGordon Ross 
75447dc10d7SGordon Ross 	mutex_unlock(&dev_priv->dev->struct_mutex);
75547dc10d7SGordon Ross 
75647dc10d7SGordon Ross 	DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n",
75747dc10d7SGordon Ross 		  row, bank, subbank);
75847dc10d7SGordon Ross }
75947dc10d7SGordon Ross 
ivybridge_handle_parity_error(struct drm_device * dev)76047dc10d7SGordon Ross static void ivybridge_handle_parity_error(struct drm_device *dev)
76147dc10d7SGordon Ross {
76247dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
76347dc10d7SGordon Ross 	unsigned long flags;
76447dc10d7SGordon Ross 
76547dc10d7SGordon Ross 	if (!HAS_L3_GPU_CACHE(dev))
76647dc10d7SGordon Ross 		return;
76747dc10d7SGordon Ross 
76847dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
76947dc10d7SGordon Ross 	dev_priv->gt_irq_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
77047dc10d7SGordon Ross 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
77147dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
77247dc10d7SGordon Ross 
77347dc10d7SGordon Ross 	queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
77447dc10d7SGordon Ross }
77547dc10d7SGordon Ross 
snb_gt_irq_handler(struct drm_device * dev,struct drm_i915_private * dev_priv,u32 gt_iir)77647dc10d7SGordon Ross static void snb_gt_irq_handler(struct drm_device *dev,
77747dc10d7SGordon Ross 			       struct drm_i915_private *dev_priv,
77847dc10d7SGordon Ross 			       u32 gt_iir)
77947dc10d7SGordon Ross {
78047dc10d7SGordon Ross 
78147dc10d7SGordon Ross 	if (gt_iir &
78247dc10d7SGordon Ross 	    (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
78347dc10d7SGordon Ross 		notify_ring(dev, &dev_priv->ring[RCS]);
78447dc10d7SGordon Ross 	if (gt_iir & GT_BSD_USER_INTERRUPT)
78547dc10d7SGordon Ross 		notify_ring(dev, &dev_priv->ring[VCS]);
78647dc10d7SGordon Ross 	if (gt_iir & GT_BLT_USER_INTERRUPT)
78747dc10d7SGordon Ross 		notify_ring(dev, &dev_priv->ring[BCS]);
78847dc10d7SGordon Ross 
78947dc10d7SGordon Ross 	if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
79047dc10d7SGordon Ross 		      GT_BSD_CS_ERROR_INTERRUPT |
79147dc10d7SGordon Ross 		      GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) {
79247dc10d7SGordon Ross 		DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
79347dc10d7SGordon Ross 		i915_handle_error(dev, false);
79447dc10d7SGordon Ross 	}
79547dc10d7SGordon Ross 
79647dc10d7SGordon Ross 	if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT)
79747dc10d7SGordon Ross 		ivybridge_handle_parity_error(dev);
79847dc10d7SGordon Ross }
79947dc10d7SGordon Ross 
gen6_queue_rps_work(struct drm_i915_private * dev_priv,u32 pm_iir)80047dc10d7SGordon Ross static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
80147dc10d7SGordon Ross 				u32 pm_iir)
80247dc10d7SGordon Ross {
80347dc10d7SGordon Ross 	unsigned long flags;
80447dc10d7SGordon Ross 
80547dc10d7SGordon Ross 	/*
80647dc10d7SGordon Ross 	 * IIR bits should never already be set because IMR should
80747dc10d7SGordon Ross 	 * prevent an interrupt from being shown in IIR. The warning
80847dc10d7SGordon Ross 	 * displays a case where we've unsafely cleared
80947dc10d7SGordon Ross 	 * dev_priv->rps.pm_iir. Although missing an interrupt of the same
81047dc10d7SGordon Ross 	 * type is not a problem, it displays a problem in the logic.
81147dc10d7SGordon Ross 	 *
81247dc10d7SGordon Ross 	 * The mask bit in IMR is cleared by dev_priv->rps.work.
81347dc10d7SGordon Ross 	 */
81447dc10d7SGordon Ross 
81547dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->rps.lock, flags);
81647dc10d7SGordon Ross 	dev_priv->rps.pm_iir |= pm_iir;
81747dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir);
81847dc10d7SGordon Ross 	POSTING_READ(GEN6_PMIMR);
81947dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
82047dc10d7SGordon Ross 
82147dc10d7SGordon Ross 	queue_work(dev_priv->wq, &dev_priv->rps.work);
82247dc10d7SGordon Ross }
82347dc10d7SGordon Ross 
82447dc10d7SGordon Ross #define HPD_STORM_DETECT_PERIOD 1000
82547dc10d7SGordon Ross #define HPD_STORM_THRESHOLD 5
82647dc10d7SGordon Ross 
intel_hpd_irq_handler(struct drm_device * dev,u32 hotplug_trigger,const u32 * hpd)82747dc10d7SGordon Ross static inline void intel_hpd_irq_handler(struct drm_device *dev,
82847dc10d7SGordon Ross 					 u32 hotplug_trigger,
82947dc10d7SGordon Ross 					 const u32 *hpd)
83047dc10d7SGordon Ross {
83147dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = dev->dev_private;
83247dc10d7SGordon Ross 	int i;
83347dc10d7SGordon Ross 	bool storm_detected = false;
83447dc10d7SGordon Ross 
83547dc10d7SGordon Ross 	if (!hotplug_trigger)
83647dc10d7SGordon Ross 		return;
83747dc10d7SGordon Ross 
83847dc10d7SGordon Ross 	spin_lock(&dev_priv->irq_lock);
83947dc10d7SGordon Ross 	for (i = 1; i < HPD_NUM_PINS; i++) {
84047dc10d7SGordon Ross 
84147dc10d7SGordon Ross 		if (!(hpd[i] & hotplug_trigger) ||
84247dc10d7SGordon Ross 		    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
84347dc10d7SGordon Ross 			continue;
84447dc10d7SGordon Ross 
84547dc10d7SGordon Ross 		dev_priv->hpd_event_bits |= (1 << i);
84647dc10d7SGordon Ross 		if (!time_in_range(jiffies, dev_priv->hpd_stats[i].hpd_last_jiffies,
84747dc10d7SGordon Ross 				   dev_priv->hpd_stats[i].hpd_last_jiffies
84847dc10d7SGordon Ross 				   + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
84947dc10d7SGordon Ross 			dev_priv->hpd_stats[i].hpd_last_jiffies = jiffies;
85047dc10d7SGordon Ross 			dev_priv->hpd_stats[i].hpd_cnt = 0;
85147dc10d7SGordon Ross 		} else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) {
85247dc10d7SGordon Ross 			dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
85347dc10d7SGordon Ross 			dev_priv->hpd_event_bits &= ~(1 << i);
85447dc10d7SGordon Ross 			DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", i);
85547dc10d7SGordon Ross 			storm_detected = true;
85647dc10d7SGordon Ross 		} else {
85747dc10d7SGordon Ross 			dev_priv->hpd_stats[i].hpd_cnt++;
85847dc10d7SGordon Ross 		}
85947dc10d7SGordon Ross 	}
86047dc10d7SGordon Ross 
86147dc10d7SGordon Ross 	if (storm_detected)
86247dc10d7SGordon Ross 		dev_priv->display.hpd_irq_setup(dev);
86347dc10d7SGordon Ross 	spin_unlock(&dev_priv->irq_lock);
86447dc10d7SGordon Ross 
86547dc10d7SGordon Ross 	queue_work(dev_priv->wq,
86647dc10d7SGordon Ross 		   &dev_priv->hotplug_work);
86747dc10d7SGordon Ross }
86847dc10d7SGordon Ross 
gmbus_irq_handler(struct drm_device * dev)86947dc10d7SGordon Ross static void gmbus_irq_handler(struct drm_device *dev)
87047dc10d7SGordon Ross {
87147dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private;
87247dc10d7SGordon Ross 
87347dc10d7SGordon Ross 	wake_up_all(&dev_priv->gmbus_wait_queue);
87447dc10d7SGordon Ross }
87547dc10d7SGordon Ross 
dp_aux_irq_handler(struct drm_device * dev)87647dc10d7SGordon Ross static void dp_aux_irq_handler(struct drm_device *dev)
87747dc10d7SGordon Ross {
87847dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private;
87947dc10d7SGordon Ross 
88047dc10d7SGordon Ross 	wake_up_all(&dev_priv->gmbus_wait_queue);
88147dc10d7SGordon Ross }
88247dc10d7SGordon Ross 
88347dc10d7SGordon Ross /* Unlike gen6_queue_rps_work() from which this function is originally derived,
88447dc10d7SGordon Ross  * we must be able to deal with other PM interrupts. This is complicated because
88547dc10d7SGordon Ross  * of the way in which we use the masks to defer the RPS work (which for
88647dc10d7SGordon Ross  * posterity is necessary because of forcewake).
88747dc10d7SGordon Ross  */
hsw_pm_irq_handler(struct drm_i915_private * dev_priv,u32 pm_iir)88847dc10d7SGordon Ross static void hsw_pm_irq_handler(struct drm_i915_private *dev_priv,
88947dc10d7SGordon Ross 			       u32 pm_iir)
89047dc10d7SGordon Ross {
89147dc10d7SGordon Ross 	unsigned long flags;
89247dc10d7SGordon Ross 
89347dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->rps.lock, flags);
89447dc10d7SGordon Ross 	dev_priv->rps.pm_iir |= pm_iir & GEN6_PM_RPS_EVENTS;
89547dc10d7SGordon Ross 	if (dev_priv->rps.pm_iir) {
89647dc10d7SGordon Ross 		I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir);
89747dc10d7SGordon Ross 		/* never want to mask useful interrupts. (also posting read) */
89847dc10d7SGordon Ross 		WARN_ON(I915_READ_NOTRACE(GEN6_PMIMR) & ~GEN6_PM_RPS_EVENTS);
89947dc10d7SGordon Ross 		/* TODO: if queue_work is slow, move it out of the spinlock */
90047dc10d7SGordon Ross 		queue_work(dev_priv->wq, &dev_priv->rps.work);
90147dc10d7SGordon Ross 	}
90247dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
90347dc10d7SGordon Ross 
90447dc10d7SGordon Ross 	if (pm_iir & ~GEN6_PM_RPS_EVENTS) {
90547dc10d7SGordon Ross 		if (pm_iir & PM_VEBOX_USER_INTERRUPT)
90647dc10d7SGordon Ross 			notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
90747dc10d7SGordon Ross 
90847dc10d7SGordon Ross 		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
90947dc10d7SGordon Ross 			DRM_ERROR("VEBOX CS error interrupt 0x%08x\n", pm_iir);
91047dc10d7SGordon Ross 			i915_handle_error(dev_priv->dev, false);
91147dc10d7SGordon Ross 		}
91247dc10d7SGordon Ross 	}
91347dc10d7SGordon Ross }
91447dc10d7SGordon Ross 
valleyview_irq_handler(DRM_IRQ_ARGS)91547dc10d7SGordon Ross static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
91647dc10d7SGordon Ross {
91747dc10d7SGordon Ross 	/* LINTED */
91847dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *) arg;
91947dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
92047dc10d7SGordon Ross 	u32 iir, gt_iir, pm_iir;
92147dc10d7SGordon Ross 	irqreturn_t ret = IRQ_NONE;
92247dc10d7SGordon Ross 	unsigned long irqflags;
92347dc10d7SGordon Ross 	int pipe;
92447dc10d7SGordon Ross 	u32 pipe_stats[I915_MAX_PIPES] = { 0 };
92547dc10d7SGordon Ross 
92647dc10d7SGordon Ross 	atomic_inc(&dev_priv->irq_received);
92747dc10d7SGordon Ross 
92847dc10d7SGordon Ross 	while (true) {
92947dc10d7SGordon Ross 		iir = I915_READ(VLV_IIR);
93047dc10d7SGordon Ross 		gt_iir = I915_READ(GTIIR);
93147dc10d7SGordon Ross 		pm_iir = I915_READ(GEN6_PMIIR);
93247dc10d7SGordon Ross 
93347dc10d7SGordon Ross 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
93447dc10d7SGordon Ross 			goto out;
93547dc10d7SGordon Ross 
93647dc10d7SGordon Ross 		ret = IRQ_HANDLED;
93747dc10d7SGordon Ross 
93847dc10d7SGordon Ross 		snb_gt_irq_handler(dev, dev_priv, gt_iir);
93947dc10d7SGordon Ross 
94047dc10d7SGordon Ross 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
94147dc10d7SGordon Ross 		for_each_pipe(pipe) {
94247dc10d7SGordon Ross 			int reg = PIPESTAT(pipe);
94347dc10d7SGordon Ross 			pipe_stats[pipe] = I915_READ(reg);
94447dc10d7SGordon Ross 
94547dc10d7SGordon Ross 			/*
94647dc10d7SGordon Ross 			 * Clear the PIPE*STAT regs before the IIR
94747dc10d7SGordon Ross 			 */
94847dc10d7SGordon Ross 			if (pipe_stats[pipe] & 0x8000ffff) {
94947dc10d7SGordon Ross 				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
95047dc10d7SGordon Ross 					DRM_DEBUG_DRIVER("pipe %c underrun\n",
95147dc10d7SGordon Ross 							 pipe_name(pipe));
95247dc10d7SGordon Ross 				I915_WRITE(reg, pipe_stats[pipe]);
95347dc10d7SGordon Ross 			}
95447dc10d7SGordon Ross 		}
95547dc10d7SGordon Ross 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
95647dc10d7SGordon Ross 
95747dc10d7SGordon Ross 		for_each_pipe(pipe) {
95847dc10d7SGordon Ross 			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
95947dc10d7SGordon Ross 				drm_handle_vblank(dev, pipe);
96047dc10d7SGordon Ross 
96147dc10d7SGordon Ross 			if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) {
96247dc10d7SGordon Ross 				intel_prepare_page_flip(dev, pipe);
96347dc10d7SGordon Ross 				intel_finish_page_flip(dev, pipe);
96447dc10d7SGordon Ross 			}
96547dc10d7SGordon Ross 		}
96647dc10d7SGordon Ross 
96747dc10d7SGordon Ross 		/* Consume port.  Then clear IIR or we'll miss events */
96847dc10d7SGordon Ross 		if (iir & I915_DISPLAY_PORT_INTERRUPT) {
96947dc10d7SGordon Ross 			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
97047dc10d7SGordon Ross 			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
97147dc10d7SGordon Ross 
97247dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
97347dc10d7SGordon Ross 					 hotplug_status);
97447dc10d7SGordon Ross 
97547dc10d7SGordon Ross 			intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
97647dc10d7SGordon Ross 
97747dc10d7SGordon Ross 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
97847dc10d7SGordon Ross 			I915_READ(PORT_HOTPLUG_STAT);
97947dc10d7SGordon Ross 		}
98047dc10d7SGordon Ross 
98147dc10d7SGordon Ross 		if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
98247dc10d7SGordon Ross 			gmbus_irq_handler(dev);
98347dc10d7SGordon Ross 
98447dc10d7SGordon Ross 		if (pm_iir & GEN6_PM_RPS_EVENTS)
98547dc10d7SGordon Ross 			gen6_queue_rps_work(dev_priv, pm_iir);
98647dc10d7SGordon Ross 
98747dc10d7SGordon Ross 		I915_WRITE(GTIIR, gt_iir);
98847dc10d7SGordon Ross 		I915_WRITE(GEN6_PMIIR, pm_iir);
98947dc10d7SGordon Ross 		I915_WRITE(VLV_IIR, iir);
99047dc10d7SGordon Ross 	}
99147dc10d7SGordon Ross 
99247dc10d7SGordon Ross out:
99347dc10d7SGordon Ross 	return ret;
99447dc10d7SGordon Ross }
99547dc10d7SGordon Ross 
ibx_irq_handler(struct drm_device * dev,u32 pch_iir)99647dc10d7SGordon Ross static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
99747dc10d7SGordon Ross {
99847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
99947dc10d7SGordon Ross 	int pipe;
100047dc10d7SGordon Ross 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
100147dc10d7SGordon Ross 
100247dc10d7SGordon Ross 	intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
100347dc10d7SGordon Ross 
100447dc10d7SGordon Ross 	if (pch_iir & SDE_AUDIO_POWER_MASK) {
100547dc10d7SGordon Ross 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
100647dc10d7SGordon Ross 			       SDE_AUDIO_POWER_SHIFT);
100747dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
100847dc10d7SGordon Ross 				 port_name(port));
100947dc10d7SGordon Ross 	}
101047dc10d7SGordon Ross 
101147dc10d7SGordon Ross 	if (pch_iir & SDE_AUX_MASK)
101247dc10d7SGordon Ross 		dp_aux_irq_handler(dev);
101347dc10d7SGordon Ross 
101447dc10d7SGordon Ross 	if (pch_iir & SDE_GMBUS)
101547dc10d7SGordon Ross 		gmbus_irq_handler(dev);
101647dc10d7SGordon Ross 
101747dc10d7SGordon Ross 	if (pch_iir & SDE_AUDIO_HDCP_MASK)
101847dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n");
101947dc10d7SGordon Ross 
102047dc10d7SGordon Ross 	if (pch_iir & SDE_AUDIO_TRANS_MASK)
102147dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n");
102247dc10d7SGordon Ross 
102347dc10d7SGordon Ross 	if (pch_iir & SDE_POISON)
102447dc10d7SGordon Ross 		DRM_ERROR("PCH poison interrupt\n");
102547dc10d7SGordon Ross 
102647dc10d7SGordon Ross 	if (pch_iir & SDE_FDI_MASK)
102747dc10d7SGordon Ross 		for_each_pipe(pipe)
102847dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("  pipe %c FDI IIR: 0x%08x\n",
102947dc10d7SGordon Ross 					 pipe_name(pipe),
103047dc10d7SGordon Ross 					 I915_READ(FDI_RX_IIR(pipe)));
103147dc10d7SGordon Ross 
103247dc10d7SGordon Ross 	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
103347dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n");
103447dc10d7SGordon Ross 
103547dc10d7SGordon Ross 	if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
103647dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
103747dc10d7SGordon Ross 
103847dc10d7SGordon Ross 	if (pch_iir & SDE_TRANSA_FIFO_UNDER)
103947dc10d7SGordon Ross 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
104047dc10d7SGordon Ross 							  false))
104147dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n");
104247dc10d7SGordon Ross 
104347dc10d7SGordon Ross 	if (pch_iir & SDE_TRANSB_FIFO_UNDER)
104447dc10d7SGordon Ross 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
104547dc10d7SGordon Ross 							  false))
104647dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n");
104747dc10d7SGordon Ross }
104847dc10d7SGordon Ross 
ivb_err_int_handler(struct drm_device * dev)104947dc10d7SGordon Ross static void ivb_err_int_handler(struct drm_device *dev)
105047dc10d7SGordon Ross {
105147dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
105247dc10d7SGordon Ross 	u32 err_int = I915_READ(GEN7_ERR_INT);
105347dc10d7SGordon Ross 
105447dc10d7SGordon Ross 	if (err_int & ERR_INT_POISON)
105547dc10d7SGordon Ross 		DRM_ERROR("Poison interrupt\n");
105647dc10d7SGordon Ross 
105747dc10d7SGordon Ross 	if (err_int & ERR_INT_FIFO_UNDERRUN_A)
105847dc10d7SGordon Ross 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
105947dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
106047dc10d7SGordon Ross 
106147dc10d7SGordon Ross 	if (err_int & ERR_INT_FIFO_UNDERRUN_B)
106247dc10d7SGordon Ross 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
106347dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
106447dc10d7SGordon Ross 
106547dc10d7SGordon Ross 	if (err_int & ERR_INT_FIFO_UNDERRUN_C)
106647dc10d7SGordon Ross 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false))
106747dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
106847dc10d7SGordon Ross 
106947dc10d7SGordon Ross 	I915_WRITE(GEN7_ERR_INT, err_int);
107047dc10d7SGordon Ross }
107147dc10d7SGordon Ross 
cpt_serr_int_handler(struct drm_device * dev)107247dc10d7SGordon Ross static void cpt_serr_int_handler(struct drm_device *dev)
107347dc10d7SGordon Ross {
107447dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
107547dc10d7SGordon Ross 	u32 serr_int = I915_READ(SERR_INT);
107647dc10d7SGordon Ross 
107747dc10d7SGordon Ross 	if (serr_int & SERR_INT_POISON)
107847dc10d7SGordon Ross 		DRM_ERROR("PCH poison interrupt\n");
107947dc10d7SGordon Ross 
108047dc10d7SGordon Ross 	if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN)
108147dc10d7SGordon Ross 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A,
108247dc10d7SGordon Ross 							  false))
108347dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("PCH transcoder A FIFO underrun\n");
108447dc10d7SGordon Ross 
108547dc10d7SGordon Ross 	if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN)
108647dc10d7SGordon Ross 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B,
108747dc10d7SGordon Ross 							  false))
108847dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("PCH transcoder B FIFO underrun\n");
108947dc10d7SGordon Ross 
109047dc10d7SGordon Ross 	if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN)
109147dc10d7SGordon Ross 		if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_C,
109247dc10d7SGordon Ross 							  false))
109347dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("PCH transcoder C FIFO underrun\n");
109447dc10d7SGordon Ross 
109547dc10d7SGordon Ross 	I915_WRITE(SERR_INT, serr_int);
109647dc10d7SGordon Ross }
109747dc10d7SGordon Ross 
cpt_irq_handler(struct drm_device * dev,u32 pch_iir)109847dc10d7SGordon Ross static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
109947dc10d7SGordon Ross {
110047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
110147dc10d7SGordon Ross 	int pipe;
110247dc10d7SGordon Ross 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
110347dc10d7SGordon Ross 
110447dc10d7SGordon Ross 	intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
110547dc10d7SGordon Ross 
110647dc10d7SGordon Ross 	if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
110747dc10d7SGordon Ross 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
110847dc10d7SGordon Ross 			       SDE_AUDIO_POWER_SHIFT_CPT);
110947dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("PCH audio power change on port %c\n",
111047dc10d7SGordon Ross 				 port_name(port));
111147dc10d7SGordon Ross 	}
111247dc10d7SGordon Ross 
111347dc10d7SGordon Ross 	if (pch_iir & SDE_AUX_MASK_CPT)
111447dc10d7SGordon Ross 		dp_aux_irq_handler(dev);
111547dc10d7SGordon Ross 
111647dc10d7SGordon Ross 	if (pch_iir & SDE_GMBUS_CPT)
111747dc10d7SGordon Ross 		gmbus_irq_handler(dev);
111847dc10d7SGordon Ross 
111947dc10d7SGordon Ross 	if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
112047dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("Audio CP request interrupt\n");
112147dc10d7SGordon Ross 
112247dc10d7SGordon Ross 	if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
112347dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("Audio CP change interrupt\n");
112447dc10d7SGordon Ross 
112547dc10d7SGordon Ross 	if (pch_iir & SDE_FDI_MASK_CPT)
112647dc10d7SGordon Ross 		for_each_pipe(pipe)
112747dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("  pipe %c FDI IIR: 0x%08x\n",
112847dc10d7SGordon Ross 					 pipe_name(pipe),
112947dc10d7SGordon Ross 					 I915_READ(FDI_RX_IIR(pipe)));
113047dc10d7SGordon Ross 
113147dc10d7SGordon Ross 	if (pch_iir & SDE_ERROR_CPT)
113247dc10d7SGordon Ross 		cpt_serr_int_handler(dev);
113347dc10d7SGordon Ross }
113447dc10d7SGordon Ross 
ivybridge_irq_handler(DRM_IRQ_ARGS)113547dc10d7SGordon Ross static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
113647dc10d7SGordon Ross {
113747dc10d7SGordon Ross 	/* LINTED */
113847dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *) arg;
113947dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
114047dc10d7SGordon Ross 	u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
114147dc10d7SGordon Ross 	irqreturn_t ret = IRQ_NONE;
114247dc10d7SGordon Ross 	int i;
114347dc10d7SGordon Ross 
114447dc10d7SGordon Ross 	atomic_inc(&dev_priv->irq_received);
114547dc10d7SGordon Ross 
114647dc10d7SGordon Ross 	/* We get interrupts on unclaimed registers, so check for this before we
114747dc10d7SGordon Ross 	 * do any I915_{READ,WRITE}. */
114847dc10d7SGordon Ross 	if (IS_HASWELL(dev) &&
114947dc10d7SGordon Ross 	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
115047dc10d7SGordon Ross 		DRM_ERROR("Unclaimed register before interrupt\n");
115147dc10d7SGordon Ross 		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
115247dc10d7SGordon Ross 	}
115347dc10d7SGordon Ross 
115447dc10d7SGordon Ross 	/* disable master interrupt before clearing iir  */
115547dc10d7SGordon Ross 	de_ier = I915_READ(DEIER);
115647dc10d7SGordon Ross 	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
115747dc10d7SGordon Ross 
115847dc10d7SGordon Ross 	/* Disable south interrupts. We'll only write to SDEIIR once, so further
115947dc10d7SGordon Ross 	 * interrupts will will be stored on its back queue, and then we'll be
116047dc10d7SGordon Ross 	 * able to process them after we restore SDEIER (as soon as we restore
116147dc10d7SGordon Ross 	 * it, we'll get an interrupt if SDEIIR still has something to process
116247dc10d7SGordon Ross 	 * due to its back queue). */
116347dc10d7SGordon Ross 	if (!HAS_PCH_NOP(dev)) {
116447dc10d7SGordon Ross 		sde_ier = I915_READ(SDEIER);
116547dc10d7SGordon Ross 		I915_WRITE(SDEIER, 0);
116647dc10d7SGordon Ross 		POSTING_READ(SDEIER);
116734389f68SGordon Ross 	} else {
116834389f68SGordon Ross 		sde_ier = 0; /* Fix GCC "used unitialized" warning */
116947dc10d7SGordon Ross 	}
117047dc10d7SGordon Ross 
117147dc10d7SGordon Ross 	/* On Haswell, also mask ERR_INT because we don't want to risk
117247dc10d7SGordon Ross 	 * generating "unclaimed register" interrupts from inside the interrupt
117347dc10d7SGordon Ross 	 * handler. */
117447dc10d7SGordon Ross 	if (IS_HASWELL(dev)) {
117547dc10d7SGordon Ross 		spin_lock(&dev_priv->irq_lock);
117647dc10d7SGordon Ross 		ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
117747dc10d7SGordon Ross 		spin_unlock(&dev_priv->irq_lock);
117847dc10d7SGordon Ross 	}
117947dc10d7SGordon Ross 
118047dc10d7SGordon Ross 	gt_iir = I915_READ(GTIIR);
118147dc10d7SGordon Ross 	if (gt_iir) {
118247dc10d7SGordon Ross 		snb_gt_irq_handler(dev, dev_priv, gt_iir);
118347dc10d7SGordon Ross 		I915_WRITE(GTIIR, gt_iir);
118447dc10d7SGordon Ross 		ret = IRQ_HANDLED;
118547dc10d7SGordon Ross 	}
118647dc10d7SGordon Ross 
118747dc10d7SGordon Ross 	de_iir = I915_READ(DEIIR);
118847dc10d7SGordon Ross 	if (de_iir) {
118947dc10d7SGordon Ross 		if (de_iir & DE_ERR_INT_IVB)
119047dc10d7SGordon Ross 			ivb_err_int_handler(dev);
119147dc10d7SGordon Ross 
119247dc10d7SGordon Ross 		if (de_iir & DE_AUX_CHANNEL_A_IVB)
119347dc10d7SGordon Ross 			dp_aux_irq_handler(dev);
119447dc10d7SGordon Ross 
119547dc10d7SGordon Ross 
119647dc10d7SGordon Ross 		for (i = 0; i < 3; i++) {
119747dc10d7SGordon Ross 			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
119847dc10d7SGordon Ross 				drm_handle_vblank(dev, i);
119947dc10d7SGordon Ross 			if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
120047dc10d7SGordon Ross 				intel_prepare_page_flip(dev, i);
120147dc10d7SGordon Ross 				intel_finish_page_flip_plane(dev, i);
120247dc10d7SGordon Ross 			}
120347dc10d7SGordon Ross 		}
120447dc10d7SGordon Ross 
120547dc10d7SGordon Ross 		/* check event from PCH */
120647dc10d7SGordon Ross 		if (!HAS_PCH_NOP(dev) && (de_iir & DE_PCH_EVENT_IVB)) {
120747dc10d7SGordon Ross 			u32 pch_iir = I915_READ(SDEIIR);
120847dc10d7SGordon Ross 
120947dc10d7SGordon Ross 			cpt_irq_handler(dev, pch_iir);
121047dc10d7SGordon Ross 
121147dc10d7SGordon Ross 			/* clear PCH hotplug event before clear CPU irq */
121247dc10d7SGordon Ross 			I915_WRITE(SDEIIR, pch_iir);
121347dc10d7SGordon Ross 		}
121447dc10d7SGordon Ross 
121547dc10d7SGordon Ross 		I915_WRITE(DEIIR, de_iir);
121647dc10d7SGordon Ross 		ret = IRQ_HANDLED;
121747dc10d7SGordon Ross 	}
121847dc10d7SGordon Ross 
121947dc10d7SGordon Ross 	pm_iir = I915_READ(GEN6_PMIIR);
122047dc10d7SGordon Ross 	if (pm_iir) {
122147dc10d7SGordon Ross 		if (IS_HASWELL(dev))
122247dc10d7SGordon Ross 			hsw_pm_irq_handler(dev_priv, pm_iir);
122347dc10d7SGordon Ross 		else if (pm_iir & GEN6_PM_RPS_EVENTS)
122447dc10d7SGordon Ross 			gen6_queue_rps_work(dev_priv, pm_iir);
122547dc10d7SGordon Ross 		I915_WRITE(GEN6_PMIIR, pm_iir);
122647dc10d7SGordon Ross 		ret = IRQ_HANDLED;
122747dc10d7SGordon Ross 	}
122847dc10d7SGordon Ross 
122947dc10d7SGordon Ross 	if (IS_HASWELL(dev)) {
123047dc10d7SGordon Ross 		spin_lock(&dev_priv->irq_lock);
123147dc10d7SGordon Ross 		if (ivb_can_enable_err_int(dev))
123247dc10d7SGordon Ross 			ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
123347dc10d7SGordon Ross 		spin_unlock(&dev_priv->irq_lock);
123447dc10d7SGordon Ross 	}
123547dc10d7SGordon Ross 
123647dc10d7SGordon Ross 	I915_WRITE(DEIER, de_ier);
123747dc10d7SGordon Ross 	POSTING_READ(DEIER);
123847dc10d7SGordon Ross 	if (!HAS_PCH_NOP(dev)) {
123947dc10d7SGordon Ross 		I915_WRITE(SDEIER, sde_ier);
124047dc10d7SGordon Ross 		POSTING_READ(SDEIER);
124147dc10d7SGordon Ross 	}
124247dc10d7SGordon Ross 
124347dc10d7SGordon Ross 	return ret;
124447dc10d7SGordon Ross }
124547dc10d7SGordon Ross 
ilk_gt_irq_handler(struct drm_device * dev,struct drm_i915_private * dev_priv,u32 gt_iir)124647dc10d7SGordon Ross static void ilk_gt_irq_handler(struct drm_device *dev,
124747dc10d7SGordon Ross 			       struct drm_i915_private *dev_priv,
124847dc10d7SGordon Ross 			       u32 gt_iir)
124947dc10d7SGordon Ross {
125047dc10d7SGordon Ross 	if (gt_iir &
125147dc10d7SGordon Ross 	    (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
125247dc10d7SGordon Ross 		notify_ring(dev, &dev_priv->ring[RCS]);
125347dc10d7SGordon Ross 	if (gt_iir & ILK_BSD_USER_INTERRUPT)
125447dc10d7SGordon Ross 		notify_ring(dev, &dev_priv->ring[VCS]);
125547dc10d7SGordon Ross }
125647dc10d7SGordon Ross 
ironlake_irq_handler(DRM_IRQ_ARGS)125747dc10d7SGordon Ross static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
125847dc10d7SGordon Ross {
125947dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *)(uintptr_t) arg;
126047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
126147dc10d7SGordon Ross 	int ret = IRQ_NONE;
126247dc10d7SGordon Ross 	u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
126347dc10d7SGordon Ross 
126447dc10d7SGordon Ross 	atomic_inc(&dev_priv->irq_received);
126547dc10d7SGordon Ross 
126647dc10d7SGordon Ross 	/* disable master interrupt before clearing iir  */
126747dc10d7SGordon Ross 	de_ier = I915_READ(DEIER);
126847dc10d7SGordon Ross 	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
126947dc10d7SGordon Ross 	POSTING_READ(DEIER);
127047dc10d7SGordon Ross 
127147dc10d7SGordon Ross 	/* Disable south interrupts. We'll only write to SDEIIR once, so further
127247dc10d7SGordon Ross 	 * interrupts will will be stored on its back queue, and then we'll be
127347dc10d7SGordon Ross 	 * able to process them after we restore SDEIER (as soon as we restore
127447dc10d7SGordon Ross 	 * it, we'll get an interrupt if SDEIIR still has something to process
127547dc10d7SGordon Ross 	 * due to its back queue). */
127647dc10d7SGordon Ross 	sde_ier = I915_READ(SDEIER);
127747dc10d7SGordon Ross 	I915_WRITE(SDEIER, 0);
127847dc10d7SGordon Ross 	POSTING_READ(SDEIER);
127947dc10d7SGordon Ross 
128047dc10d7SGordon Ross 	de_iir = I915_READ(DEIIR);
128147dc10d7SGordon Ross 	gt_iir = I915_READ(GTIIR);
128247dc10d7SGordon Ross 	pm_iir = I915_READ(GEN6_PMIIR);
128347dc10d7SGordon Ross 
128447dc10d7SGordon Ross 	if (de_iir == 0 && gt_iir == 0 && (!IS_GEN6(dev) || pm_iir == 0))
128547dc10d7SGordon Ross 		goto done;
128647dc10d7SGordon Ross 
128747dc10d7SGordon Ross 	ret = IRQ_HANDLED;
128847dc10d7SGordon Ross 
128947dc10d7SGordon Ross 	if (IS_GEN5(dev))
129047dc10d7SGordon Ross 		ilk_gt_irq_handler(dev, dev_priv, gt_iir);
129147dc10d7SGordon Ross 	else
129247dc10d7SGordon Ross 		snb_gt_irq_handler(dev, dev_priv, gt_iir);
129347dc10d7SGordon Ross 
129447dc10d7SGordon Ross 	if (de_iir & DE_AUX_CHANNEL_A)
129547dc10d7SGordon Ross 		dp_aux_irq_handler(dev);
129647dc10d7SGordon Ross 
129747dc10d7SGordon Ross 
129847dc10d7SGordon Ross 	if (de_iir & DE_PIPEA_VBLANK)
129947dc10d7SGordon Ross 		drm_handle_vblank(dev, 0);
130047dc10d7SGordon Ross 
130147dc10d7SGordon Ross 	if (de_iir & DE_PIPEB_VBLANK)
130247dc10d7SGordon Ross 		drm_handle_vblank(dev, 1);
130347dc10d7SGordon Ross 
130447dc10d7SGordon Ross 	if (de_iir & DE_POISON)
130547dc10d7SGordon Ross 		DRM_ERROR("Poison interrupt\n");
130647dc10d7SGordon Ross 
130747dc10d7SGordon Ross 	if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
130847dc10d7SGordon Ross 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
130947dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
131047dc10d7SGordon Ross 
131147dc10d7SGordon Ross 	if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
131247dc10d7SGordon Ross 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
131347dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
131447dc10d7SGordon Ross 
131547dc10d7SGordon Ross 	if (de_iir & DE_PLANEA_FLIP_DONE) {
131647dc10d7SGordon Ross 		intel_prepare_page_flip(dev, 0);
131747dc10d7SGordon Ross 		intel_finish_page_flip_plane(dev, 0);
131847dc10d7SGordon Ross 	}
131947dc10d7SGordon Ross 
132047dc10d7SGordon Ross 	if (de_iir & DE_PLANEB_FLIP_DONE) {
132147dc10d7SGordon Ross 		intel_prepare_page_flip(dev, 1);
132247dc10d7SGordon Ross 		intel_finish_page_flip_plane(dev, 1);
132347dc10d7SGordon Ross 	}
132447dc10d7SGordon Ross 
132547dc10d7SGordon Ross 	/* check event from PCH */
132647dc10d7SGordon Ross 	if (de_iir & DE_PCH_EVENT) {
132747dc10d7SGordon Ross 		u32 pch_iir = I915_READ(SDEIIR);
132847dc10d7SGordon Ross 
132947dc10d7SGordon Ross 		if (HAS_PCH_CPT(dev))
133047dc10d7SGordon Ross 			cpt_irq_handler(dev, pch_iir);
133147dc10d7SGordon Ross 		else
133247dc10d7SGordon Ross 			ibx_irq_handler(dev, pch_iir);
133347dc10d7SGordon Ross 
133447dc10d7SGordon Ross 		/* should clear PCH hotplug event before clear CPU irq */
133547dc10d7SGordon Ross 		I915_WRITE(SDEIIR, pch_iir);
133647dc10d7SGordon Ross 	}
133747dc10d7SGordon Ross 
133847dc10d7SGordon Ross 	if (IS_GEN5(dev) &&  de_iir & DE_PCU_EVENT)
133947dc10d7SGordon Ross 		ironlake_handle_rps_change(dev);
134047dc10d7SGordon Ross 
134147dc10d7SGordon Ross 	if (IS_GEN6(dev) && pm_iir & GEN6_PM_RPS_EVENTS)
134247dc10d7SGordon Ross 		gen6_queue_rps_work(dev_priv, pm_iir);
134347dc10d7SGordon Ross 
134447dc10d7SGordon Ross 	I915_WRITE(GTIIR, gt_iir);
134547dc10d7SGordon Ross 	I915_WRITE(DEIIR, de_iir);
134647dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIIR, pm_iir);
134747dc10d7SGordon Ross 
134847dc10d7SGordon Ross done:
134947dc10d7SGordon Ross 	I915_WRITE(DEIER, de_ier);
135047dc10d7SGordon Ross 	POSTING_READ(DEIER);
135147dc10d7SGordon Ross 	I915_WRITE(SDEIER, sde_ier);
135247dc10d7SGordon Ross 	POSTING_READ(SDEIER);
135347dc10d7SGordon Ross 
135447dc10d7SGordon Ross 	return ret;
135547dc10d7SGordon Ross }
135647dc10d7SGordon Ross 
135747dc10d7SGordon Ross /**
135847dc10d7SGordon Ross  * i915_error_work_func - do process context error handling work
135947dc10d7SGordon Ross  * @work: work struct
136047dc10d7SGordon Ross  *
136147dc10d7SGordon Ross  * Fire an error uevent so userspace can see that a hang or error
136247dc10d7SGordon Ross  * was detected.
136347dc10d7SGordon Ross  */
i915_error_work_func(struct work_struct * work)136447dc10d7SGordon Ross static void i915_error_work_func(struct work_struct *work)
136547dc10d7SGordon Ross {
136647dc10d7SGordon Ross 	struct i915_gpu_error *error = container_of(work, struct i915_gpu_error,
136747dc10d7SGordon Ross 						    work);
136847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = container_of(error, drm_i915_private_t,
136947dc10d7SGordon Ross 						    gpu_error);
137047dc10d7SGordon Ross 	struct drm_device *dev = dev_priv->dev;
137147dc10d7SGordon Ross 	struct intel_ring_buffer *ring;
137247dc10d7SGordon Ross 	/* LINTED */
137347dc10d7SGordon Ross 	char *error_event[] = { "ERROR=1", NULL };
137447dc10d7SGordon Ross 	/* LINTED */
137547dc10d7SGordon Ross 	char *reset_event[] = { "RESET=1", NULL };
137647dc10d7SGordon Ross 	/* LINTED */
137747dc10d7SGordon Ross 	char *reset_done_event[] = { "ERROR=0", NULL };
137847dc10d7SGordon Ross 	int i, ret;
137947dc10d7SGordon Ross 
138047dc10d7SGordon Ross 	DRM_DEBUG_DRIVER("generating error event\n");
138147dc10d7SGordon Ross 	/* OSOL_i915: kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); */
138247dc10d7SGordon Ross 
138347dc10d7SGordon Ross 	/*
138447dc10d7SGordon Ross 	 * Note that there's only one work item which does gpu resets, so we
138547dc10d7SGordon Ross 	 * need not worry about concurrent gpu resets potentially incrementing
138647dc10d7SGordon Ross 	 * error->reset_counter twice. We only need to take care of another
138747dc10d7SGordon Ross 	 * racing irq/hangcheck declaring the gpu dead for a second time. A
138847dc10d7SGordon Ross 	 * quick check for that is good enough: schedule_work ensures the
138947dc10d7SGordon Ross 	 * correct ordering between hang detection and this work item, and since
139047dc10d7SGordon Ross 	 * the reset in-progress bit is only ever set by code outside of this
139147dc10d7SGordon Ross 	 * work we don't need to worry about any other races.
139247dc10d7SGordon Ross 	 */
139347dc10d7SGordon Ross 	if (i915_reset_in_progress(error) && !i915_terminally_wedged(error)) {
139447dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("resetting chip\n");
139547dc10d7SGordon Ross 		/* OSOL_i915: kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); */
139647dc10d7SGordon Ross 		ret = i915_reset(dev);
139747dc10d7SGordon Ross 
139847dc10d7SGordon Ross 		if (ret == 0) {
139947dc10d7SGordon Ross 			/*
140047dc10d7SGordon Ross 			 * After all the gem state is reset, increment the reset
140147dc10d7SGordon Ross 			 * counter and wake up everyone waiting for the reset to
140247dc10d7SGordon Ross 			 * complete.
140347dc10d7SGordon Ross 			 *
140447dc10d7SGordon Ross 			 * Since unlock operations are a one-sided barrier only,
140547dc10d7SGordon Ross 			 * we need to insert a barrier here to order any seqno
140647dc10d7SGordon Ross 			 * updates before
140747dc10d7SGordon Ross 			 * the counter increment.
140847dc10d7SGordon Ross 			 */
140947dc10d7SGordon Ross 			atomic_inc(&dev_priv->gpu_error.reset_counter);
141047dc10d7SGordon Ross 			if (gpu_dump > 0) {
141147dc10d7SGordon Ross 				for_each_ring(ring, dev_priv, i)
141247dc10d7SGordon Ross 					ring_dump(dev, ring);
141347dc10d7SGordon Ross 				register_dump(dev);
141447dc10d7SGordon Ross 				gtt_dump(dev);
141547dc10d7SGordon Ross 			}
141647dc10d7SGordon Ross 		} else {
141747dc10d7SGordon Ross 			atomic_set(&error->reset_counter, I915_WEDGED);
141847dc10d7SGordon Ross 		}
141947dc10d7SGordon Ross 
142047dc10d7SGordon Ross 		for_each_ring(ring, dev_priv, i)
142147dc10d7SGordon Ross 			wake_up_all(&ring->irq_queue);
142247dc10d7SGordon Ross 
142347dc10d7SGordon Ross 		wake_up_all(&dev_priv->gpu_error.reset_queue);
142447dc10d7SGordon Ross 		DRM_INFO("resetting done");
142547dc10d7SGordon Ross 	}
142647dc10d7SGordon Ross }
142747dc10d7SGordon Ross 
142847dc10d7SGordon Ross /* NB: please notice the memset */
i915_get_extra_instdone(struct drm_device * dev,uint32_t * instdone)142947dc10d7SGordon Ross static void i915_get_extra_instdone(struct drm_device *dev,
143047dc10d7SGordon Ross 				    uint32_t *instdone)
143147dc10d7SGordon Ross {
143247dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
143347dc10d7SGordon Ross 	(void) memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
143447dc10d7SGordon Ross 
143547dc10d7SGordon Ross 	switch(INTEL_INFO(dev)->gen) {
143647dc10d7SGordon Ross 	case 2:
143747dc10d7SGordon Ross 	case 3:
143847dc10d7SGordon Ross 		instdone[0] = I915_READ(INSTDONE);
143947dc10d7SGordon Ross 		break;
144047dc10d7SGordon Ross 	case 4:
144147dc10d7SGordon Ross 	case 5:
144247dc10d7SGordon Ross 	case 6:
144347dc10d7SGordon Ross 		instdone[0] = I915_READ(INSTDONE_I965);
144447dc10d7SGordon Ross 		instdone[1] = I915_READ(INSTDONE1);
144547dc10d7SGordon Ross 		break;
144647dc10d7SGordon Ross 	default:
144747dc10d7SGordon Ross 		DRM_INFO("Unsupported platform\n");
1448*19482684SGordon Ross 		/* FALLTHROUGH */
144947dc10d7SGordon Ross 	case 7:
145047dc10d7SGordon Ross 		instdone[0] = I915_READ(GEN7_INSTDONE_1);
145147dc10d7SGordon Ross 		instdone[1] = I915_READ(GEN7_SC_INSTDONE);
145247dc10d7SGordon Ross 		instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
145347dc10d7SGordon Ross 		instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
145447dc10d7SGordon Ross 		break;
145547dc10d7SGordon Ross 	}
145647dc10d7SGordon Ross }
145747dc10d7SGordon Ross 
145847dc10d7SGordon Ross #ifdef CONFIG_DEBUG_FS
145947dc10d7SGordon Ross static struct drm_i915_error_object *
i915_error_object_create_sized(struct drm_i915_private * dev_priv,struct drm_i915_gem_object * src,const int num_pages)146047dc10d7SGordon Ross i915_error_object_create_sized(struct drm_i915_private *dev_priv,
146147dc10d7SGordon Ross 			       struct drm_i915_gem_object *src,
146247dc10d7SGordon Ross 			       const int num_pages)
146347dc10d7SGordon Ross {
146447dc10d7SGordon Ross 	struct drm_i915_error_object *dst;
146547dc10d7SGordon Ross 	int i;
146647dc10d7SGordon Ross 	u32 reloc_offset;
146747dc10d7SGordon Ross 
146847dc10d7SGordon Ross 	if (src == NULL || src->pages == NULL)
146947dc10d7SGordon Ross 		return NULL;
147047dc10d7SGordon Ross 
147147dc10d7SGordon Ross 	dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
147247dc10d7SGordon Ross 	if (dst == NULL)
147347dc10d7SGordon Ross 		return NULL;
147447dc10d7SGordon Ross 
147547dc10d7SGordon Ross 	reloc_offset = src->gtt_offset;
147647dc10d7SGordon Ross 	for (i = 0; i < num_pages; i++) {
147747dc10d7SGordon Ross 		unsigned long flags;
147847dc10d7SGordon Ross 		void *d;
147947dc10d7SGordon Ross 
148047dc10d7SGordon Ross 		d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
148147dc10d7SGordon Ross 		if (d == NULL)
148247dc10d7SGordon Ross 			goto unwind;
148347dc10d7SGordon Ross 
148447dc10d7SGordon Ross 		local_irq_save(flags);
148547dc10d7SGordon Ross 		if (reloc_offset < dev_priv->gtt.mappable_end &&
148647dc10d7SGordon Ross 		    src->has_global_gtt_mapping) {
148747dc10d7SGordon Ross 			void __iomem *s;
148847dc10d7SGordon Ross 
148947dc10d7SGordon Ross 			/* Simply ignore tiling or any overlapping fence.
149047dc10d7SGordon Ross 			 * It's part of the error state, and this hopefully
149147dc10d7SGordon Ross 			 * captures what the GPU read.
149247dc10d7SGordon Ross 			 */
149347dc10d7SGordon Ross 
149447dc10d7SGordon Ross 			s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
149547dc10d7SGordon Ross 						     reloc_offset);
149647dc10d7SGordon Ross 			memcpy_fromio(d, s, PAGE_SIZE);
149747dc10d7SGordon Ross 			io_mapping_unmap_atomic(s);
149847dc10d7SGordon Ross 		} else if (src->stolen) {
149947dc10d7SGordon Ross 			unsigned long offset;
150047dc10d7SGordon Ross 
150147dc10d7SGordon Ross 			offset = dev_priv->mm.stolen_base;
150247dc10d7SGordon Ross 			offset += src->stolen->start;
150347dc10d7SGordon Ross 			offset += i << PAGE_SHIFT;
150447dc10d7SGordon Ross 
150547dc10d7SGordon Ross 			memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE);
150647dc10d7SGordon Ross 		} else {
150747dc10d7SGordon Ross 			struct page *page;
150847dc10d7SGordon Ross 			void *s;
150947dc10d7SGordon Ross 
151047dc10d7SGordon Ross 			page = i915_gem_object_get_page(src, i);
151147dc10d7SGordon Ross 
151247dc10d7SGordon Ross 			drm_clflush_pages(&page, 1);
151347dc10d7SGordon Ross 
151447dc10d7SGordon Ross 			s = kmap_atomic(page);
151547dc10d7SGordon Ross 			memcpy(d, s, PAGE_SIZE);
151647dc10d7SGordon Ross 			kunmap_atomic(s);
151747dc10d7SGordon Ross 
151847dc10d7SGordon Ross 			drm_clflush_pages(&page, 1);
151947dc10d7SGordon Ross 		}
152047dc10d7SGordon Ross 		local_irq_restore(flags);
152147dc10d7SGordon Ross 
152247dc10d7SGordon Ross 		dst->pages[i] = d;
152347dc10d7SGordon Ross 
152447dc10d7SGordon Ross 		reloc_offset += PAGE_SIZE;
152547dc10d7SGordon Ross 	}
152647dc10d7SGordon Ross 	dst->page_count = num_pages;
152747dc10d7SGordon Ross 	dst->gtt_offset = src->gtt_offset;
152847dc10d7SGordon Ross 
152947dc10d7SGordon Ross 	return dst;
153047dc10d7SGordon Ross 
153147dc10d7SGordon Ross unwind:
153247dc10d7SGordon Ross 	while (i--)
153347dc10d7SGordon Ross 		kfree(dst->pages[i]);
153447dc10d7SGordon Ross 	kfree(dst);
153547dc10d7SGordon Ross 	return NULL;
153647dc10d7SGordon Ross }
153747dc10d7SGordon Ross #define i915_error_object_create(dev_priv, src) \
153847dc10d7SGordon Ross 	i915_error_object_create_sized((dev_priv), (src), \
153947dc10d7SGordon Ross 				       (src)->base.size>>PAGE_SHIFT)
154047dc10d7SGordon Ross 
154147dc10d7SGordon Ross static void
i915_error_object_free(struct drm_i915_error_object * obj)154247dc10d7SGordon Ross i915_error_object_free(struct drm_i915_error_object *obj)
154347dc10d7SGordon Ross {
154447dc10d7SGordon Ross 	int page;
154547dc10d7SGordon Ross 
154647dc10d7SGordon Ross 	if (obj == NULL)
154747dc10d7SGordon Ross 		return;
154847dc10d7SGordon Ross 
154947dc10d7SGordon Ross 	for (page = 0; page < obj->page_count; page++)
155047dc10d7SGordon Ross 		kfree(obj->pages[page]);
155147dc10d7SGordon Ross 
155247dc10d7SGordon Ross 	kfree(obj);
155347dc10d7SGordon Ross }
155447dc10d7SGordon Ross 
155547dc10d7SGordon Ross void
i915_error_state_free(struct kref * error_ref)155647dc10d7SGordon Ross i915_error_state_free(struct kref *error_ref)
155747dc10d7SGordon Ross {
155847dc10d7SGordon Ross 	struct drm_i915_error_state *error = container_of(error_ref,
155947dc10d7SGordon Ross 							  typeof(*error), ref);
156047dc10d7SGordon Ross 	int i;
156147dc10d7SGordon Ross 
156247dc10d7SGordon Ross 	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
156347dc10d7SGordon Ross 		i915_error_object_free(error->ring[i].batchbuffer);
156447dc10d7SGordon Ross 		i915_error_object_free(error->ring[i].ringbuffer);
156547dc10d7SGordon Ross 		i915_error_object_free(error->ring[i].ctx);
156647dc10d7SGordon Ross 		kfree(error->ring[i].requests);
156747dc10d7SGordon Ross 	}
156847dc10d7SGordon Ross 
156947dc10d7SGordon Ross 	kfree(error->active_bo);
157047dc10d7SGordon Ross 	kfree(error->overlay);
157147dc10d7SGordon Ross 	kfree(error->display);
157247dc10d7SGordon Ross 	kfree(error);
157347dc10d7SGordon Ross }
capture_bo(struct drm_i915_error_buffer * err,struct drm_i915_gem_object * obj)157447dc10d7SGordon Ross static void capture_bo(struct drm_i915_error_buffer *err,
157547dc10d7SGordon Ross 		       struct drm_i915_gem_object *obj)
157647dc10d7SGordon Ross {
157747dc10d7SGordon Ross 	err->size = obj->base.size;
157847dc10d7SGordon Ross 	err->name = obj->base.name;
157947dc10d7SGordon Ross 	err->rseqno = obj->last_read_seqno;
158047dc10d7SGordon Ross 	err->wseqno = obj->last_write_seqno;
158147dc10d7SGordon Ross 	err->gtt_offset = obj->gtt_offset;
158247dc10d7SGordon Ross 	err->read_domains = obj->base.read_domains;
158347dc10d7SGordon Ross 	err->write_domain = obj->base.write_domain;
158447dc10d7SGordon Ross 	err->fence_reg = obj->fence_reg;
158547dc10d7SGordon Ross 	err->pinned = 0;
158647dc10d7SGordon Ross 	if (obj->pin_count > 0)
158747dc10d7SGordon Ross 		err->pinned = 1;
158847dc10d7SGordon Ross 	if (obj->user_pin_count > 0)
158947dc10d7SGordon Ross 		err->pinned = -1;
159047dc10d7SGordon Ross 	err->tiling = obj->tiling_mode;
159147dc10d7SGordon Ross 	err->dirty = obj->dirty;
159247dc10d7SGordon Ross 	err->purgeable = obj->madv != I915_MADV_WILLNEED;
159347dc10d7SGordon Ross 	err->ring = obj->ring ? obj->ring->id : -1;
159447dc10d7SGordon Ross 	err->cache_level = obj->cache_level;
159547dc10d7SGordon Ross }
159647dc10d7SGordon Ross 
capture_active_bo(struct drm_i915_error_buffer * err,int count,struct list_head * head)159747dc10d7SGordon Ross static u32 capture_active_bo(struct drm_i915_error_buffer *err,
159847dc10d7SGordon Ross 			     int count, struct list_head *head)
159947dc10d7SGordon Ross {
160047dc10d7SGordon Ross 	struct drm_i915_gem_object *obj;
160147dc10d7SGordon Ross 	int i = 0;
160247dc10d7SGordon Ross 
160347dc10d7SGordon Ross 	list_for_each_entry(obj, head, mm_list) {
160447dc10d7SGordon Ross 		capture_bo(err++, obj);
160547dc10d7SGordon Ross 		if (++i == count)
160647dc10d7SGordon Ross 			break;
160747dc10d7SGordon Ross 	}
160847dc10d7SGordon Ross 
160947dc10d7SGordon Ross 	return i;
161047dc10d7SGordon Ross }
161147dc10d7SGordon Ross 
capture_pinned_bo(struct drm_i915_error_buffer * err,int count,struct list_head * head)161247dc10d7SGordon Ross static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
161347dc10d7SGordon Ross 			     int count, struct list_head *head)
161447dc10d7SGordon Ross {
161547dc10d7SGordon Ross 	struct drm_i915_gem_object *obj;
161647dc10d7SGordon Ross 	int i = 0;
161747dc10d7SGordon Ross 
161847dc10d7SGordon Ross 	list_for_each_entry(obj, head, global_list) {
161947dc10d7SGordon Ross 		if (obj->pin_count == 0)
162047dc10d7SGordon Ross 			continue;
162147dc10d7SGordon Ross 
162247dc10d7SGordon Ross 		capture_bo(err++, obj);
162347dc10d7SGordon Ross 		if (++i == count)
162447dc10d7SGordon Ross 			break;
162547dc10d7SGordon Ross 	}
162647dc10d7SGordon Ross 
162747dc10d7SGordon Ross 	return i;
162847dc10d7SGordon Ross }
162947dc10d7SGordon Ross 
i915_gem_record_fences(struct drm_device * dev,struct drm_i915_error_state * error)163047dc10d7SGordon Ross static void i915_gem_record_fences(struct drm_device *dev,
163147dc10d7SGordon Ross 				   struct drm_i915_error_state *error)
163247dc10d7SGordon Ross {
163347dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
163447dc10d7SGordon Ross 	int i;
163547dc10d7SGordon Ross 
163647dc10d7SGordon Ross 	/* Fences */
163747dc10d7SGordon Ross 	switch (INTEL_INFO(dev)->gen) {
163847dc10d7SGordon Ross 	case 7:
163947dc10d7SGordon Ross 	case 6:
164047dc10d7SGordon Ross 		for (i = 0; i < dev_priv->num_fence_regs; i++)
164147dc10d7SGordon Ross 			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
164247dc10d7SGordon Ross 		break;
164347dc10d7SGordon Ross 	case 5:
164447dc10d7SGordon Ross 	case 4:
164547dc10d7SGordon Ross 		for (i = 0; i < 16; i++)
164647dc10d7SGordon Ross 			error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
164747dc10d7SGordon Ross 		break;
164847dc10d7SGordon Ross 	case 3:
164947dc10d7SGordon Ross 		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
165047dc10d7SGordon Ross 			for (i = 0; i < 8; i++)
165147dc10d7SGordon Ross 				error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
165247dc10d7SGordon Ross 	case 2:
165347dc10d7SGordon Ross 		for (i = 0; i < 8; i++)
165447dc10d7SGordon Ross 			error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
165547dc10d7SGordon Ross 		break;
165647dc10d7SGordon Ross 
165747dc10d7SGordon Ross 	default:
165847dc10d7SGordon Ross 		BUG();
165947dc10d7SGordon Ross 	}
166047dc10d7SGordon Ross }
166147dc10d7SGordon Ross 
166247dc10d7SGordon Ross static struct drm_i915_error_object *
i915_error_first_batchbuffer(struct drm_i915_private * dev_priv,struct intel_ring_buffer * ring)166347dc10d7SGordon Ross i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
166447dc10d7SGordon Ross 			     struct intel_ring_buffer *ring)
166547dc10d7SGordon Ross {
166647dc10d7SGordon Ross 	struct drm_i915_gem_object *obj;
166747dc10d7SGordon Ross 	u32 seqno;
166847dc10d7SGordon Ross 
166947dc10d7SGordon Ross 	if (!ring->get_seqno)
167047dc10d7SGordon Ross 		return NULL;
167147dc10d7SGordon Ross 
167247dc10d7SGordon Ross 	if (HAS_BROKEN_CS_TLB(dev_priv->dev)) {
167347dc10d7SGordon Ross 		u32 acthd = I915_READ(ACTHD);
167447dc10d7SGordon Ross 
167547dc10d7SGordon Ross 		if (WARN_ON(ring->id != RCS))
167647dc10d7SGordon Ross 			return NULL;
167747dc10d7SGordon Ross 
167847dc10d7SGordon Ross 		obj = ring->private;
167947dc10d7SGordon Ross 		if (acthd >= obj->gtt_offset &&
168047dc10d7SGordon Ross 		    acthd < obj->gtt_offset + obj->base.size)
168147dc10d7SGordon Ross 			return i915_error_object_create(dev_priv, obj);
168247dc10d7SGordon Ross 	}
168347dc10d7SGordon Ross 
168447dc10d7SGordon Ross 	seqno = ring->get_seqno(ring, false);
168547dc10d7SGordon Ross 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
168647dc10d7SGordon Ross 		if (obj->ring != ring)
168747dc10d7SGordon Ross 			continue;
168847dc10d7SGordon Ross 
168947dc10d7SGordon Ross 		if (i915_seqno_passed(seqno, obj->last_read_seqno))
169047dc10d7SGordon Ross 			continue;
169147dc10d7SGordon Ross 
169247dc10d7SGordon Ross 		if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
169347dc10d7SGordon Ross 			continue;
169447dc10d7SGordon Ross 
169547dc10d7SGordon Ross 		/* We need to copy these to an anonymous buffer as the simplest
169647dc10d7SGordon Ross 		 * method to avoid being overwritten by userspace.
169747dc10d7SGordon Ross 		 */
169847dc10d7SGordon Ross 		return i915_error_object_create(dev_priv, obj);
169947dc10d7SGordon Ross 	}
170047dc10d7SGordon Ross 
170147dc10d7SGordon Ross 	return NULL;
170247dc10d7SGordon Ross }
170347dc10d7SGordon Ross 
i915_record_ring_state(struct drm_device * dev,struct drm_i915_error_state * error,struct intel_ring_buffer * ring)170447dc10d7SGordon Ross static void i915_record_ring_state(struct drm_device *dev,
170547dc10d7SGordon Ross 				   struct drm_i915_error_state *error,
170647dc10d7SGordon Ross 				   struct intel_ring_buffer *ring)
170747dc10d7SGordon Ross {
170847dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
170947dc10d7SGordon Ross 
171047dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 6) {
171147dc10d7SGordon Ross 		error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50);
171247dc10d7SGordon Ross 		error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
171347dc10d7SGordon Ross 		error->semaphore_mboxes[ring->id][0]
171447dc10d7SGordon Ross 			= I915_READ(RING_SYNC_0(ring->mmio_base));
171547dc10d7SGordon Ross 		error->semaphore_mboxes[ring->id][1]
171647dc10d7SGordon Ross 			= I915_READ(RING_SYNC_1(ring->mmio_base));
171747dc10d7SGordon Ross 		error->semaphore_seqno[ring->id][0] = ring->sync_seqno[0];
171847dc10d7SGordon Ross 		error->semaphore_seqno[ring->id][1] = ring->sync_seqno[1];
171947dc10d7SGordon Ross 	}
172047dc10d7SGordon Ross 
172147dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 4) {
172247dc10d7SGordon Ross 		error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
172347dc10d7SGordon Ross 		error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
172447dc10d7SGordon Ross 		error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
172547dc10d7SGordon Ross 		error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
172647dc10d7SGordon Ross 		error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
172747dc10d7SGordon Ross 		if (ring->id == RCS)
172847dc10d7SGordon Ross 			error->bbaddr = I915_READ64(BB_ADDR);
172947dc10d7SGordon Ross 	} else {
173047dc10d7SGordon Ross 		error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
173147dc10d7SGordon Ross 		error->ipeir[ring->id] = I915_READ(IPEIR);
173247dc10d7SGordon Ross 		error->ipehr[ring->id] = I915_READ(IPEHR);
173347dc10d7SGordon Ross 		error->instdone[ring->id] = I915_READ(INSTDONE);
173447dc10d7SGordon Ross 	}
173547dc10d7SGordon Ross 
173647dc10d7SGordon Ross 	error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
173747dc10d7SGordon Ross 	error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
173847dc10d7SGordon Ross 	error->seqno[ring->id] = ring->get_seqno(ring, false);
173947dc10d7SGordon Ross 	error->acthd[ring->id] = intel_ring_get_active_head(ring);
174047dc10d7SGordon Ross 	error->head[ring->id] = I915_READ_HEAD(ring);
174147dc10d7SGordon Ross 	error->tail[ring->id] = I915_READ_TAIL(ring);
174247dc10d7SGordon Ross 	error->ctl[ring->id] = I915_READ_CTL(ring);
174347dc10d7SGordon Ross 
174447dc10d7SGordon Ross 	error->cpu_ring_head[ring->id] = ring->head;
174547dc10d7SGordon Ross 	error->cpu_ring_tail[ring->id] = ring->tail;
174647dc10d7SGordon Ross }
174747dc10d7SGordon Ross 
174847dc10d7SGordon Ross 
i915_gem_record_active_context(struct intel_ring_buffer * ring,struct drm_i915_error_state * error,struct drm_i915_error_ring * ering)174947dc10d7SGordon Ross static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
175047dc10d7SGordon Ross 					   struct drm_i915_error_state *error,
175147dc10d7SGordon Ross 					   struct drm_i915_error_ring *ering)
175247dc10d7SGordon Ross {
175347dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
175447dc10d7SGordon Ross 	struct drm_i915_gem_object *obj;
175547dc10d7SGordon Ross 
175647dc10d7SGordon Ross 	/* Currently render ring is the only HW context user */
175747dc10d7SGordon Ross 	if (ring->id != RCS || !error->ccid)
175847dc10d7SGordon Ross 		return;
175947dc10d7SGordon Ross 
176047dc10d7SGordon Ross 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
176147dc10d7SGordon Ross 		if ((error->ccid & PAGE_MASK) == obj->gtt_offset) {
176247dc10d7SGordon Ross 			ering->ctx = i915_error_object_create_sized(dev_priv,
176347dc10d7SGordon Ross 								    obj, 1);
176447dc10d7SGordon Ross 		}
176547dc10d7SGordon Ross 	}
176647dc10d7SGordon Ross }
176747dc10d7SGordon Ross 
i915_gem_record_rings(struct drm_device * dev,struct drm_i915_error_state * error)176847dc10d7SGordon Ross static void i915_gem_record_rings(struct drm_device *dev,
176947dc10d7SGordon Ross 				  struct drm_i915_error_state *error)
177047dc10d7SGordon Ross {
177147dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
177247dc10d7SGordon Ross 	struct intel_ring_buffer *ring;
177347dc10d7SGordon Ross 	struct drm_i915_gem_request *request;
177447dc10d7SGordon Ross 	int i, count;
177547dc10d7SGordon Ross 
177647dc10d7SGordon Ross 	for_each_ring(ring, dev_priv, i) {
177747dc10d7SGordon Ross 		i915_record_ring_state(dev, error, ring);
177847dc10d7SGordon Ross 
177947dc10d7SGordon Ross 		error->ring[i].batchbuffer =
178047dc10d7SGordon Ross 			i915_error_first_batchbuffer(dev_priv, ring);
178147dc10d7SGordon Ross 
178247dc10d7SGordon Ross 		error->ring[i].ringbuffer =
178347dc10d7SGordon Ross 			i915_error_object_create(dev_priv, ring->obj);
178447dc10d7SGordon Ross 
178547dc10d7SGordon Ross 
178647dc10d7SGordon Ross 		i915_gem_record_active_context(ring, error, &error->ring[i]);
178747dc10d7SGordon Ross 
178847dc10d7SGordon Ross 		count = 0;
178947dc10d7SGordon Ross 		list_for_each_entry(request, &ring->request_list, list)
179047dc10d7SGordon Ross 			count++;
179147dc10d7SGordon Ross 
179247dc10d7SGordon Ross 		error->ring[i].num_requests = count;
179347dc10d7SGordon Ross 		error->ring[i].requests =
179447dc10d7SGordon Ross 			kmalloc(count*sizeof(struct drm_i915_error_request),
179547dc10d7SGordon Ross 				GFP_ATOMIC);
179647dc10d7SGordon Ross 		if (error->ring[i].requests == NULL) {
179747dc10d7SGordon Ross 			error->ring[i].num_requests = 0;
179847dc10d7SGordon Ross 			continue;
179947dc10d7SGordon Ross 		}
180047dc10d7SGordon Ross 
180147dc10d7SGordon Ross 		count = 0;
180247dc10d7SGordon Ross 		list_for_each_entry(request, &ring->request_list, list) {
180347dc10d7SGordon Ross 			struct drm_i915_error_request *erq;
180447dc10d7SGordon Ross 
180547dc10d7SGordon Ross 			erq = &error->ring[i].requests[count++];
180647dc10d7SGordon Ross 			erq->seqno = request->seqno;
180747dc10d7SGordon Ross 			erq->jiffies = request->emitted_jiffies;
180847dc10d7SGordon Ross 			erq->tail = request->tail;
180947dc10d7SGordon Ross 		}
181047dc10d7SGordon Ross 	}
181147dc10d7SGordon Ross }
181247dc10d7SGordon Ross 
181347dc10d7SGordon Ross /**
181447dc10d7SGordon Ross  * i915_capture_error_state - capture an error record for later analysis
181547dc10d7SGordon Ross  * @dev: drm device
181647dc10d7SGordon Ross  *
181747dc10d7SGordon Ross  * Should be called when an error is detected (either a hang or an error
181847dc10d7SGordon Ross  * interrupt) to capture error state from the time of the error.  Fills
181947dc10d7SGordon Ross  * out a structure which becomes available in debugfs for user level tools
182047dc10d7SGordon Ross  * to pick up.
182147dc10d7SGordon Ross  */
i915_capture_error_state(struct drm_device * dev)182247dc10d7SGordon Ross static void i915_capture_error_state(struct drm_device *dev)
182347dc10d7SGordon Ross {
182447dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
182547dc10d7SGordon Ross 	struct drm_i915_gem_object *obj;
182647dc10d7SGordon Ross 	struct drm_i915_error_state *error;
182747dc10d7SGordon Ross 	unsigned long flags;
182847dc10d7SGordon Ross 	int i, pipe;
182947dc10d7SGordon Ross 
183047dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
183147dc10d7SGordon Ross 	error = dev_priv->gpu_error.first_error;
183247dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
183347dc10d7SGordon Ross 	if (error)
183447dc10d7SGordon Ross 		return;
183547dc10d7SGordon Ross 
183647dc10d7SGordon Ross 	/* Account for pipe specific data like PIPE*STAT */
183747dc10d7SGordon Ross 	error = kzalloc(sizeof(*error), GFP_ATOMIC);
183847dc10d7SGordon Ross 	if (!error) {
183947dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
184047dc10d7SGordon Ross 		return;
184147dc10d7SGordon Ross 	}
184247dc10d7SGordon Ross 
184347dc10d7SGordon Ross 	DRM_INFO("capturing error event; look for more information in "
184447dc10d7SGordon Ross 		 "/sys/kernel/debug/dri/%d/i915_error_state\n",
184547dc10d7SGordon Ross 		dev->primary->index);
184647dc10d7SGordon Ross 
184747dc10d7SGordon Ross 	kref_init(&error->ref);
184847dc10d7SGordon Ross 	error->eir = I915_READ(EIR);
184947dc10d7SGordon Ross 	error->pgtbl_er = I915_READ(PGTBL_ER);
185047dc10d7SGordon Ross 	if (HAS_HW_CONTEXTS(dev))
185147dc10d7SGordon Ross 		error->ccid = I915_READ(CCID);
185247dc10d7SGordon Ross 
185347dc10d7SGordon Ross 	if (HAS_PCH_SPLIT(dev))
185447dc10d7SGordon Ross 		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
185547dc10d7SGordon Ross 	else if (IS_VALLEYVIEW(dev))
185647dc10d7SGordon Ross 		error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
185747dc10d7SGordon Ross 	else if (IS_GEN2(dev))
185847dc10d7SGordon Ross 		error->ier = I915_READ16(IER);
185947dc10d7SGordon Ross 	else
186047dc10d7SGordon Ross 		error->ier = I915_READ(IER);
186147dc10d7SGordon Ross 
186247dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 6)
186347dc10d7SGordon Ross 		error->derrmr = I915_READ(DERRMR);
186447dc10d7SGordon Ross 
186547dc10d7SGordon Ross 	if (IS_VALLEYVIEW(dev))
186647dc10d7SGordon Ross 		error->forcewake = I915_READ(FORCEWAKE_VLV);
186747dc10d7SGordon Ross 	else if (INTEL_INFO(dev)->gen >= 7)
186847dc10d7SGordon Ross 		error->forcewake = I915_READ(FORCEWAKE_MT);
186947dc10d7SGordon Ross 	else if (INTEL_INFO(dev)->gen == 6)
187047dc10d7SGordon Ross 		error->forcewake = I915_READ(FORCEWAKE);
187147dc10d7SGordon Ross 
187247dc10d7SGordon Ross 	if (!HAS_PCH_SPLIT(dev))
187347dc10d7SGordon Ross 		for_each_pipe(pipe)
187447dc10d7SGordon Ross 			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
187547dc10d7SGordon Ross 
187647dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 6) {
187747dc10d7SGordon Ross 		error->error = I915_READ(ERROR_GEN6);
187847dc10d7SGordon Ross 		error->done_reg = I915_READ(DONE_REG);
187947dc10d7SGordon Ross 	}
188047dc10d7SGordon Ross 
188147dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen == 7)
188247dc10d7SGordon Ross 		error->err_int = I915_READ(GEN7_ERR_INT);
188347dc10d7SGordon Ross 
188447dc10d7SGordon Ross 	i915_get_extra_instdone(dev, error->extra_instdone);
188547dc10d7SGordon Ross 
188647dc10d7SGordon Ross 	i915_gem_record_fences(dev, error);
188747dc10d7SGordon Ross 	i915_gem_record_rings(dev, error);
188847dc10d7SGordon Ross 
188947dc10d7SGordon Ross 	/* Record buffers on the active and pinned lists. */
189047dc10d7SGordon Ross 	error->active_bo = NULL;
189147dc10d7SGordon Ross 	error->pinned_bo = NULL;
189247dc10d7SGordon Ross 
189347dc10d7SGordon Ross 	i = 0;
189447dc10d7SGordon Ross 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
189547dc10d7SGordon Ross 		i++;
189647dc10d7SGordon Ross 	error->active_bo_count = i;
189747dc10d7SGordon Ross 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
189847dc10d7SGordon Ross 		if (obj->pin_count)
189947dc10d7SGordon Ross 		i++;
190047dc10d7SGordon Ross 	error->pinned_bo_count = i - error->active_bo_count;
190147dc10d7SGordon Ross 
190247dc10d7SGordon Ross 	error->active_bo = NULL;
190347dc10d7SGordon Ross 	error->pinned_bo = NULL;
190447dc10d7SGordon Ross 	if (i) {
190547dc10d7SGordon Ross 		error->active_bo = kmalloc(sizeof(*error->active_bo)*i,
190647dc10d7SGordon Ross 					   GFP_ATOMIC);
190747dc10d7SGordon Ross 		if (error->active_bo)
190847dc10d7SGordon Ross 			error->pinned_bo =
190947dc10d7SGordon Ross 				error->active_bo + error->active_bo_count;
191047dc10d7SGordon Ross 	}
191147dc10d7SGordon Ross 
191247dc10d7SGordon Ross 	if (error->active_bo)
191347dc10d7SGordon Ross 		error->active_bo_count =
191447dc10d7SGordon Ross 			capture_active_bo(error->active_bo,
191547dc10d7SGordon Ross 					  error->active_bo_count,
191647dc10d7SGordon Ross 					  &dev_priv->mm.active_list);
191747dc10d7SGordon Ross 
191847dc10d7SGordon Ross 	if (error->pinned_bo)
191947dc10d7SGordon Ross 		error->pinned_bo_count =
192047dc10d7SGordon Ross 			capture_pinned_bo(error->pinned_bo,
192147dc10d7SGordon Ross 					  error->pinned_bo_count,
192247dc10d7SGordon Ross 					  &dev_priv->mm.bound_list);
192347dc10d7SGordon Ross 
192447dc10d7SGordon Ross 	do_gettimeofday(&error->time);
192547dc10d7SGordon Ross 
192647dc10d7SGordon Ross 	error->overlay = intel_overlay_capture_error_state(dev);
192747dc10d7SGordon Ross 	error->display = intel_display_capture_error_state(dev);
192847dc10d7SGordon Ross 
192947dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
193047dc10d7SGordon Ross 	if (dev_priv->gpu_error.first_error == NULL) {
193147dc10d7SGordon Ross 		dev_priv->gpu_error.first_error = error;
193247dc10d7SGordon Ross 		error = NULL;
193347dc10d7SGordon Ross 	}
193447dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
193547dc10d7SGordon Ross 
193647dc10d7SGordon Ross 	if (error)
193747dc10d7SGordon Ross 		i915_error_state_free(&error->ref);
193847dc10d7SGordon Ross }
193947dc10d7SGordon Ross 
i915_destroy_error_state(struct drm_device * dev)194047dc10d7SGordon Ross void i915_destroy_error_state(struct drm_device *dev)
194147dc10d7SGordon Ross {
194247dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
194347dc10d7SGordon Ross 	struct drm_i915_error_state *error;
194447dc10d7SGordon Ross 	unsigned long flags;
194547dc10d7SGordon Ross 
194647dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
194747dc10d7SGordon Ross 	error = dev_priv->gpu_error.first_error;
194847dc10d7SGordon Ross 	dev_priv->gpu_error.first_error = NULL;
194947dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
195047dc10d7SGordon Ross 
195147dc10d7SGordon Ross 	if (error)
195247dc10d7SGordon Ross 		kref_put(&error->ref, i915_error_state_free);
195347dc10d7SGordon Ross }
195447dc10d7SGordon Ross #else
195547dc10d7SGordon Ross #define i915_capture_error_state(x)
195647dc10d7SGordon Ross #endif
195747dc10d7SGordon Ross 
i915_report_and_clear_eir(struct drm_device * dev)195847dc10d7SGordon Ross static void i915_report_and_clear_eir(struct drm_device *dev)
195947dc10d7SGordon Ross {
196047dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
196147dc10d7SGordon Ross 	uint32_t instdone[I915_NUM_INSTDONE_REG];
196247dc10d7SGordon Ross 	u32 eir = I915_READ(EIR);
196347dc10d7SGordon Ross 	int pipe;
196447dc10d7SGordon Ross 
196547dc10d7SGordon Ross 	if (!eir)
196647dc10d7SGordon Ross 		return;
196747dc10d7SGordon Ross 
196847dc10d7SGordon Ross 	DRM_ERROR("render error detected, EIR: 0x%08x\n", eir);
196947dc10d7SGordon Ross 
197047dc10d7SGordon Ross 	i915_get_extra_instdone(dev, instdone);
197147dc10d7SGordon Ross 
197247dc10d7SGordon Ross 	if (IS_G4X(dev)) {
197347dc10d7SGordon Ross 		if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
197447dc10d7SGordon Ross 			u32 ipeir = I915_READ(IPEIR_I965);
197547dc10d7SGordon Ross 
197647dc10d7SGordon Ross 			DRM_DEBUG("  IPEIR: 0x%08x\n",
197747dc10d7SGordon Ross 			       I915_READ(IPEIR_I965));
197847dc10d7SGordon Ross 			DRM_DEBUG("  IPEHR: 0x%08x\n",
197947dc10d7SGordon Ross 			       I915_READ(IPEHR_I965));
198047dc10d7SGordon Ross 			DRM_DEBUG("  INSTDONE: 0x%08x\n",
198147dc10d7SGordon Ross 			       I915_READ(INSTDONE_I965));
198247dc10d7SGordon Ross 			DRM_DEBUG("  INSTPS: 0x%08x\n",
198347dc10d7SGordon Ross 			       I915_READ(INSTPS));
198447dc10d7SGordon Ross 			DRM_DEBUG("  INSTDONE1: 0x%08x\n",
198547dc10d7SGordon Ross 			       I915_READ(INSTDONE1));
198647dc10d7SGordon Ross 			DRM_DEBUG("  ACTHD: 0x%08x\n",
198747dc10d7SGordon Ross 			       I915_READ(ACTHD_I965));
198847dc10d7SGordon Ross 			I915_WRITE(IPEIR_I965, ipeir);
198947dc10d7SGordon Ross 			POSTING_READ(IPEIR_I965);
199047dc10d7SGordon Ross 		}
199147dc10d7SGordon Ross 		if (eir & GM45_ERROR_PAGE_TABLE) {
199247dc10d7SGordon Ross 			u32 pgtbl_err = I915_READ(PGTBL_ER);
199347dc10d7SGordon Ross 			DRM_DEBUG("page table error\n");
199447dc10d7SGordon Ross 			DRM_DEBUG("  PGTBL_ER: 0x%08x\n",
199547dc10d7SGordon Ross 			       pgtbl_err);
199647dc10d7SGordon Ross 			I915_WRITE(PGTBL_ER, pgtbl_err);
199747dc10d7SGordon Ross 			POSTING_READ(PGTBL_ER);
199847dc10d7SGordon Ross 		}
199947dc10d7SGordon Ross 	}
200047dc10d7SGordon Ross 
200147dc10d7SGordon Ross 	if (!IS_GEN2(dev)) {
200247dc10d7SGordon Ross 		if (eir & I915_ERROR_PAGE_TABLE) {
200347dc10d7SGordon Ross 			u32 pgtbl_err = I915_READ(PGTBL_ER);
200447dc10d7SGordon Ross 			DRM_DEBUG("page table error\n");
200547dc10d7SGordon Ross 			DRM_DEBUG("  PGTBL_ER: 0x%08x\n",
200647dc10d7SGordon Ross 			       pgtbl_err);
200747dc10d7SGordon Ross 			I915_WRITE(PGTBL_ER, pgtbl_err);
200847dc10d7SGordon Ross 			POSTING_READ(PGTBL_ER);
200947dc10d7SGordon Ross 		}
201047dc10d7SGordon Ross 	}
201147dc10d7SGordon Ross 
201247dc10d7SGordon Ross 	if (eir & I915_ERROR_MEMORY_REFRESH) {
201347dc10d7SGordon Ross 		DRM_DEBUG("memory refresh error:\n");
201447dc10d7SGordon Ross 		for_each_pipe(pipe)
201547dc10d7SGordon Ross 			DRM_DEBUG("pipe %c stat: 0x%08x\n",
201647dc10d7SGordon Ross 			       pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
201747dc10d7SGordon Ross 		/* pipestat has already been acked */
201847dc10d7SGordon Ross 	}
201947dc10d7SGordon Ross 	if (eir & I915_ERROR_INSTRUCTION) {
202047dc10d7SGordon Ross 		DRM_DEBUG("instruction error\n");
202147dc10d7SGordon Ross 		DRM_DEBUG("  INSTPM: 0x%08x\n",
202247dc10d7SGordon Ross 		       I915_READ(INSTPM));
202347dc10d7SGordon Ross 		if (INTEL_INFO(dev)->gen < 4) {
202447dc10d7SGordon Ross 			u32 ipeir = I915_READ(IPEIR);
202547dc10d7SGordon Ross 
202647dc10d7SGordon Ross 			DRM_DEBUG("  IPEIR: 0x%08x\n",
202747dc10d7SGordon Ross 			       I915_READ(IPEIR));
202847dc10d7SGordon Ross 			DRM_DEBUG("  IPEHR: 0x%08x\n",
202947dc10d7SGordon Ross 			       I915_READ(IPEHR));
203047dc10d7SGordon Ross 			DRM_DEBUG("  INSTDONE: 0x%08x\n",
203147dc10d7SGordon Ross 			       I915_READ(INSTDONE));
203247dc10d7SGordon Ross 			DRM_DEBUG("  ACTHD: 0x%08x\n",
203347dc10d7SGordon Ross 			       I915_READ(ACTHD));
203447dc10d7SGordon Ross 			I915_WRITE(IPEIR, ipeir);
203547dc10d7SGordon Ross 			POSTING_READ(IPEIR);
203647dc10d7SGordon Ross 		} else {
203747dc10d7SGordon Ross 			u32 ipeir = I915_READ(IPEIR_I965);
203847dc10d7SGordon Ross 
203947dc10d7SGordon Ross 			DRM_DEBUG("  IPEIR: 0x%08x\n",
204047dc10d7SGordon Ross 			       I915_READ(IPEIR_I965));
204147dc10d7SGordon Ross 			DRM_DEBUG("  IPEHR: 0x%08x\n",
204247dc10d7SGordon Ross 			       I915_READ(IPEHR_I965));
204347dc10d7SGordon Ross 			DRM_DEBUG("  INSTDONE: 0x%08x\n",
204447dc10d7SGordon Ross 			       I915_READ(INSTDONE_I965));
204547dc10d7SGordon Ross 			DRM_DEBUG("  INSTPS: 0x%08x\n",
204647dc10d7SGordon Ross 			       I915_READ(INSTPS));
204747dc10d7SGordon Ross 			DRM_DEBUG("  INSTDONE1: 0x%08x\n",
204847dc10d7SGordon Ross 			       I915_READ(INSTDONE1));
204947dc10d7SGordon Ross 			DRM_DEBUG("  ACTHD: 0x%08x\n",
205047dc10d7SGordon Ross 			       I915_READ(ACTHD_I965));
205147dc10d7SGordon Ross 			I915_WRITE(IPEIR_I965, ipeir);
205247dc10d7SGordon Ross 			POSTING_READ(IPEIR_I965);
205347dc10d7SGordon Ross 		}
205447dc10d7SGordon Ross 	}
205547dc10d7SGordon Ross 
205647dc10d7SGordon Ross 	I915_WRITE(EIR, eir);
205747dc10d7SGordon Ross 	POSTING_READ(EIR);
205847dc10d7SGordon Ross 	eir = I915_READ(EIR);
205947dc10d7SGordon Ross 	if (eir) {
206047dc10d7SGordon Ross 		/*
206147dc10d7SGordon Ross 		 * some errors might have become stuck,
206247dc10d7SGordon Ross 		 * mask them.
206347dc10d7SGordon Ross 		 */
206447dc10d7SGordon Ross 		DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
206547dc10d7SGordon Ross 		I915_WRITE(EMR, I915_READ(EMR) | eir);
206647dc10d7SGordon Ross 		I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
206747dc10d7SGordon Ross 	}
206847dc10d7SGordon Ross }
206947dc10d7SGordon Ross 
207047dc10d7SGordon Ross /**
207147dc10d7SGordon Ross  * i915_handle_error - handle an error interrupt
207247dc10d7SGordon Ross  * @dev: drm device
207347dc10d7SGordon Ross  *
207447dc10d7SGordon Ross  * Do some basic checking of regsiter state at error interrupt time and
207547dc10d7SGordon Ross  * dump it to the syslog.  Also call i915_capture_error_state() to make
207647dc10d7SGordon Ross  * sure we get a record and make it available in debugfs.  Fire a uevent
207747dc10d7SGordon Ross  * so userspace knows something bad happened (should trigger collection
207847dc10d7SGordon Ross  * of a ring dump etc.).
207947dc10d7SGordon Ross  */
i915_handle_error(struct drm_device * dev,bool wedged)208047dc10d7SGordon Ross void i915_handle_error(struct drm_device *dev, bool wedged)
208147dc10d7SGordon Ross {
208247dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
208347dc10d7SGordon Ross 	struct intel_ring_buffer *ring;
208447dc10d7SGordon Ross 	int i;
208547dc10d7SGordon Ross 
208647dc10d7SGordon Ross 	i915_capture_error_state(dev);
208747dc10d7SGordon Ross 	i915_report_and_clear_eir(dev);
208847dc10d7SGordon Ross 
208947dc10d7SGordon Ross 	if (wedged) {
209047dc10d7SGordon Ross 		atomic_set_mask(I915_RESET_IN_PROGRESS_FLAG,
209147dc10d7SGordon Ross 				&dev_priv->gpu_error.reset_counter);
209247dc10d7SGordon Ross 
209347dc10d7SGordon Ross 		/*
209447dc10d7SGordon Ross 		 * Wakeup waiting processes so they don't hang
209547dc10d7SGordon Ross 		 */
209647dc10d7SGordon Ross 		for_each_ring(ring, dev_priv, i)
209747dc10d7SGordon Ross 			wake_up_all(&ring->irq_queue);
209847dc10d7SGordon Ross 	}
209947dc10d7SGordon Ross 
210047dc10d7SGordon Ross 	(void) queue_work(dev_priv->wq, &dev_priv->gpu_error.work);
210147dc10d7SGordon Ross }
210247dc10d7SGordon Ross 
i915_pageflip_stall_check(struct drm_device * dev,int pipe)210347dc10d7SGordon Ross static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
210447dc10d7SGordon Ross {
210547dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = dev->dev_private;
210647dc10d7SGordon Ross 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
210747dc10d7SGordon Ross 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
210847dc10d7SGordon Ross 	struct drm_i915_gem_object *obj;
210947dc10d7SGordon Ross 	struct intel_unpin_work *work;
211047dc10d7SGordon Ross 	unsigned long flags;
211147dc10d7SGordon Ross 	bool stall_detected;
211247dc10d7SGordon Ross 
211347dc10d7SGordon Ross 	/* Ignore early vblank irqs */
211447dc10d7SGordon Ross 	if (intel_crtc == NULL)
211547dc10d7SGordon Ross 		return;
211647dc10d7SGordon Ross 
211747dc10d7SGordon Ross 	spin_lock_irqsave(&dev->event_lock, flags);
211847dc10d7SGordon Ross 	work = intel_crtc->unpin_work;
211947dc10d7SGordon Ross 
212047dc10d7SGordon Ross 	if (work == NULL ||
212147dc10d7SGordon Ross 	    atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE ||
212247dc10d7SGordon Ross 	    !work->enable_stall_check) {
212347dc10d7SGordon Ross 		/* Either the pending flip IRQ arrived, or we're too early. Don't check */
212447dc10d7SGordon Ross 		spin_unlock_irqrestore(&dev->event_lock, flags);
212547dc10d7SGordon Ross 		return;
212647dc10d7SGordon Ross 	}
212747dc10d7SGordon Ross 
212847dc10d7SGordon Ross 	/* Potential stall - if we see that the flip has happened, assume a missed interrupt */
212947dc10d7SGordon Ross 	obj = work->pending_flip_obj;
213047dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 4) {
213147dc10d7SGordon Ross 		int dspsurf = DSPSURF(intel_crtc->plane);
213247dc10d7SGordon Ross 		stall_detected = I915_HI_DISPBASE(I915_READ(dspsurf)) ==
213347dc10d7SGordon Ross 					obj->gtt_offset;
213447dc10d7SGordon Ross 	} else {
213547dc10d7SGordon Ross 		int dspaddr = DSPADDR(intel_crtc->plane);
213647dc10d7SGordon Ross 		stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
213747dc10d7SGordon Ross 							crtc->y * crtc->fb->pitches[0] +
213847dc10d7SGordon Ross 							crtc->x * crtc->fb->bits_per_pixel/8);
213947dc10d7SGordon Ross 	}
214047dc10d7SGordon Ross 
214147dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev->event_lock, flags);
214247dc10d7SGordon Ross 
214347dc10d7SGordon Ross 	if (stall_detected) {
214447dc10d7SGordon Ross 		DRM_DEBUG_DRIVER("Pageflip stall detected\n");
214547dc10d7SGordon Ross 		intel_prepare_page_flip(dev, intel_crtc->plane);
214647dc10d7SGordon Ross 	}
214747dc10d7SGordon Ross }
214847dc10d7SGordon Ross 
214947dc10d7SGordon Ross /* Called from drm generic code, passed 'crtc' which
215047dc10d7SGordon Ross  * we use as a pipe index
215147dc10d7SGordon Ross  */
i915_enable_vblank(struct drm_device * dev,int pipe)215247dc10d7SGordon Ross static int i915_enable_vblank(struct drm_device *dev, int pipe)
215347dc10d7SGordon Ross {
215447dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
215547dc10d7SGordon Ross 	unsigned long irqflags;
215647dc10d7SGordon Ross 
215747dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe))
215847dc10d7SGordon Ross 		return -EINVAL;
215947dc10d7SGordon Ross 
216047dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
216147dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 4)
216247dc10d7SGordon Ross 		i915_enable_pipestat(dev_priv, pipe,
216347dc10d7SGordon Ross 				     PIPE_START_VBLANK_INTERRUPT_ENABLE);
216447dc10d7SGordon Ross 	else
216547dc10d7SGordon Ross 		i915_enable_pipestat(dev_priv, pipe,
216647dc10d7SGordon Ross 				     PIPE_VBLANK_INTERRUPT_ENABLE);
216747dc10d7SGordon Ross 
216847dc10d7SGordon Ross 	/* maintain vblank delivery even in deep C-states */
216947dc10d7SGordon Ross 	if (dev_priv->info->gen == 3)
217047dc10d7SGordon Ross 		I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
217147dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
217247dc10d7SGordon Ross 
217347dc10d7SGordon Ross 	return 0;
217447dc10d7SGordon Ross }
217547dc10d7SGordon Ross 
ironlake_enable_vblank(struct drm_device * dev,int pipe)217647dc10d7SGordon Ross static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
217747dc10d7SGordon Ross {
217847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
217947dc10d7SGordon Ross 	unsigned long irqflags;
218047dc10d7SGordon Ross 
218147dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe))
218247dc10d7SGordon Ross 		return -EINVAL;
218347dc10d7SGordon Ross 
218447dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
218547dc10d7SGordon Ross 	ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
218647dc10d7SGordon Ross 				    DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
218747dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
218847dc10d7SGordon Ross 
218947dc10d7SGordon Ross 	return 0;
219047dc10d7SGordon Ross }
219147dc10d7SGordon Ross 
ivybridge_enable_vblank(struct drm_device * dev,int pipe)219247dc10d7SGordon Ross static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
219347dc10d7SGordon Ross {
219447dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
219547dc10d7SGordon Ross 	unsigned long irqflags;
219647dc10d7SGordon Ross 
219747dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe))
219847dc10d7SGordon Ross 		return -EINVAL;
219947dc10d7SGordon Ross 
220047dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
220147dc10d7SGordon Ross 	ironlake_enable_display_irq(dev_priv,
220247dc10d7SGordon Ross 				    DE_PIPEA_VBLANK_IVB << (5 * pipe));
220347dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
220447dc10d7SGordon Ross 
220547dc10d7SGordon Ross 	return 0;
220647dc10d7SGordon Ross }
220747dc10d7SGordon Ross 
valleyview_enable_vblank(struct drm_device * dev,int pipe)220847dc10d7SGordon Ross static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
220947dc10d7SGordon Ross {
221047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
221147dc10d7SGordon Ross 	unsigned long irqflags;
221247dc10d7SGordon Ross 	u32 imr;
221347dc10d7SGordon Ross 
221447dc10d7SGordon Ross 	if (!i915_pipe_enabled(dev, pipe))
221547dc10d7SGordon Ross 		return -EINVAL;
221647dc10d7SGordon Ross 
221747dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
221847dc10d7SGordon Ross 	imr = I915_READ(VLV_IMR);
221947dc10d7SGordon Ross 	if (pipe == 0)
222047dc10d7SGordon Ross 		imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
222147dc10d7SGordon Ross 	else
222247dc10d7SGordon Ross 		imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
222347dc10d7SGordon Ross 	I915_WRITE(VLV_IMR, imr);
222447dc10d7SGordon Ross 	i915_enable_pipestat(dev_priv, pipe,
222547dc10d7SGordon Ross 			     PIPE_START_VBLANK_INTERRUPT_ENABLE);
222647dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
222747dc10d7SGordon Ross 
222847dc10d7SGordon Ross 	return 0;
222947dc10d7SGordon Ross }
223047dc10d7SGordon Ross 
223147dc10d7SGordon Ross /* Called from drm generic code, passed 'crtc' which
223247dc10d7SGordon Ross  * we use as a pipe index
223347dc10d7SGordon Ross  */
i915_disable_vblank(struct drm_device * dev,int pipe)223447dc10d7SGordon Ross static void i915_disable_vblank(struct drm_device *dev, int pipe)
223547dc10d7SGordon Ross {
223647dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
223747dc10d7SGordon Ross 	unsigned long irqflags;
223847dc10d7SGordon Ross 
223947dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
224047dc10d7SGordon Ross 	if (dev_priv->info->gen == 3)
224147dc10d7SGordon Ross 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
224247dc10d7SGordon Ross 
224347dc10d7SGordon Ross 	i915_disable_pipestat(dev_priv, pipe,
224447dc10d7SGordon Ross 			      PIPE_VBLANK_INTERRUPT_ENABLE |
224547dc10d7SGordon Ross 			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
224647dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
224747dc10d7SGordon Ross }
224847dc10d7SGordon Ross 
ironlake_disable_vblank(struct drm_device * dev,int pipe)224947dc10d7SGordon Ross static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
225047dc10d7SGordon Ross {
225147dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
225247dc10d7SGordon Ross 	unsigned long irqflags;
225347dc10d7SGordon Ross 
225447dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
225547dc10d7SGordon Ross 	ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
225647dc10d7SGordon Ross 				     DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
225747dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
225847dc10d7SGordon Ross }
225947dc10d7SGordon Ross 
ivybridge_disable_vblank(struct drm_device * dev,int pipe)226047dc10d7SGordon Ross static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)
226147dc10d7SGordon Ross {
226247dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
226347dc10d7SGordon Ross 	unsigned long irqflags;
226447dc10d7SGordon Ross 
226547dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
226647dc10d7SGordon Ross 	ironlake_disable_display_irq(dev_priv,
226747dc10d7SGordon Ross 				     DE_PIPEA_VBLANK_IVB << (pipe * 5));
226847dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
226947dc10d7SGordon Ross }
227047dc10d7SGordon Ross 
valleyview_disable_vblank(struct drm_device * dev,int pipe)227147dc10d7SGordon Ross static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
227247dc10d7SGordon Ross {
227347dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
227447dc10d7SGordon Ross 	unsigned long irqflags;
227547dc10d7SGordon Ross 	u32 imr;
227647dc10d7SGordon Ross 
227747dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
227847dc10d7SGordon Ross 	i915_disable_pipestat(dev_priv, pipe,
227947dc10d7SGordon Ross 			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
228047dc10d7SGordon Ross 	imr = I915_READ(VLV_IMR);
228147dc10d7SGordon Ross 	if (pipe == 0)
228247dc10d7SGordon Ross 		imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
228347dc10d7SGordon Ross 	else
228447dc10d7SGordon Ross 		imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
228547dc10d7SGordon Ross 	I915_WRITE(VLV_IMR, imr);
228647dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
228747dc10d7SGordon Ross }
228847dc10d7SGordon Ross 
228947dc10d7SGordon Ross static u32
ring_last_seqno(struct intel_ring_buffer * ring)229047dc10d7SGordon Ross ring_last_seqno(struct intel_ring_buffer *ring)
229147dc10d7SGordon Ross {
229247dc10d7SGordon Ross 	struct drm_i915_gem_request *last_req;
229347dc10d7SGordon Ross 	last_req = list_entry(ring->request_list.prev,
229447dc10d7SGordon Ross 			  struct drm_i915_gem_request, list);
229547dc10d7SGordon Ross 	return (last_req->seqno);
229647dc10d7SGordon Ross }
229747dc10d7SGordon Ross 
229847dc10d7SGordon Ross static bool
ring_idle(struct intel_ring_buffer * ring,u32 seqno)229947dc10d7SGordon Ross ring_idle(struct intel_ring_buffer *ring, u32 seqno)
230047dc10d7SGordon Ross {
230147dc10d7SGordon Ross 	return (list_empty(&ring->request_list) ||
230247dc10d7SGordon Ross 		i915_seqno_passed(seqno, ring_last_seqno(ring)));
230347dc10d7SGordon Ross }
230447dc10d7SGordon Ross 
230547dc10d7SGordon Ross static struct intel_ring_buffer *
semaphore_waits_for(struct intel_ring_buffer * ring,u32 * seqno)230647dc10d7SGordon Ross semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
230747dc10d7SGordon Ross {
230847dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
230947dc10d7SGordon Ross 	u32 cmd, ipehr, acthd, acthd_min;
231047dc10d7SGordon Ross 	u32 *tmp;
231147dc10d7SGordon Ross 
231247dc10d7SGordon Ross 	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
231347dc10d7SGordon Ross 	if ((ipehr & ~(0x3 << 16)) !=
231447dc10d7SGordon Ross 	    (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | MI_SEMAPHORE_REGISTER))
231547dc10d7SGordon Ross 		return NULL;
231647dc10d7SGordon Ross 
231747dc10d7SGordon Ross 	/* ACTHD is likely pointing to the dword after the actual command,
231847dc10d7SGordon Ross 	 * so scan backwards until we find the MBOX.
231947dc10d7SGordon Ross 	 */
232047dc10d7SGordon Ross 	acthd = intel_ring_get_active_head(ring) & HEAD_ADDR;
232147dc10d7SGordon Ross 	acthd_min = max((int)acthd - 3 * 4, 0);
232247dc10d7SGordon Ross 	do {
232347dc10d7SGordon Ross 		tmp = (u32 *)((intptr_t)ring->virtual_start + acthd);
232447dc10d7SGordon Ross 		cmd = *tmp;
232547dc10d7SGordon Ross 		if (cmd == ipehr)
232647dc10d7SGordon Ross 			break;
232747dc10d7SGordon Ross 
232847dc10d7SGordon Ross 		acthd -= 4;
232947dc10d7SGordon Ross 		if (acthd < acthd_min)
233047dc10d7SGordon Ross 			return NULL;
233147dc10d7SGordon Ross 	} while (1);
233247dc10d7SGordon Ross 
233347dc10d7SGordon Ross 	tmp = (u32 *)((intptr_t)ring->virtual_start + acthd + 4 );
233447dc10d7SGordon Ross 	*seqno = *tmp+1;
233547dc10d7SGordon Ross 	return &dev_priv->ring[(ring->id + (((ipehr >> 17) & 1) + 1)) % 3];
233647dc10d7SGordon Ross }
233747dc10d7SGordon Ross 
semaphore_passed(struct intel_ring_buffer * ring)233847dc10d7SGordon Ross static int semaphore_passed(struct intel_ring_buffer *ring)
233947dc10d7SGordon Ross {
234047dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
234147dc10d7SGordon Ross 	struct intel_ring_buffer *signaller;
234247dc10d7SGordon Ross 	u32 seqno, ctl;
234347dc10d7SGordon Ross 
234447dc10d7SGordon Ross 	ring->hangcheck.deadlock = true;
234547dc10d7SGordon Ross 
234647dc10d7SGordon Ross 	signaller = semaphore_waits_for(ring, &seqno);
234747dc10d7SGordon Ross 	if (signaller == NULL || signaller->hangcheck.deadlock)
234847dc10d7SGordon Ross 		return -1;
234947dc10d7SGordon Ross 
235047dc10d7SGordon Ross 	/* cursory check for an unkickable deadlock */
235147dc10d7SGordon Ross 	ctl = I915_READ_CTL(signaller);
235247dc10d7SGordon Ross 	if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
235347dc10d7SGordon Ross 		return -1;
235447dc10d7SGordon Ross 
235547dc10d7SGordon Ross 	return i915_seqno_passed(signaller->get_seqno(signaller, false), seqno);
235647dc10d7SGordon Ross }
235747dc10d7SGordon Ross 
semaphore_clear_deadlocks(struct drm_i915_private * dev_priv)235847dc10d7SGordon Ross static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
235947dc10d7SGordon Ross {
236047dc10d7SGordon Ross 	struct intel_ring_buffer *ring;
236147dc10d7SGordon Ross 	int i;
236247dc10d7SGordon Ross 
236347dc10d7SGordon Ross 	for_each_ring(ring, dev_priv, i)
236447dc10d7SGordon Ross 		ring->hangcheck.deadlock = false;
236547dc10d7SGordon Ross }
236647dc10d7SGordon Ross 
236747dc10d7SGordon Ross static enum intel_ring_hangcheck_action
ring_stuck(struct intel_ring_buffer * ring,u32 acthd)236847dc10d7SGordon Ross ring_stuck(struct intel_ring_buffer *ring, u32 acthd)
236947dc10d7SGordon Ross {
237047dc10d7SGordon Ross 	struct drm_device *dev = ring->dev;
237147dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
237247dc10d7SGordon Ross 	u32 tmp;
237347dc10d7SGordon Ross 
237447dc10d7SGordon Ross 	if (ring->hangcheck.acthd != acthd)
237547dc10d7SGordon Ross 		return active;
237647dc10d7SGordon Ross 
237747dc10d7SGordon Ross 	if (IS_GEN2(dev))
237847dc10d7SGordon Ross 		return hung;
237947dc10d7SGordon Ross 
238047dc10d7SGordon Ross 	/* Is the chip hanging on a WAIT_FOR_EVENT?
238147dc10d7SGordon Ross 	 * If so we can simply poke the RB_WAIT bit
238247dc10d7SGordon Ross 	 * and break the hang. This should work on
238347dc10d7SGordon Ross 	 * all but the second generation chipsets.
238447dc10d7SGordon Ross 	 */
238547dc10d7SGordon Ross 	tmp = I915_READ_CTL(ring);
238647dc10d7SGordon Ross 	if (tmp & RING_WAIT) {
238747dc10d7SGordon Ross 		DRM_ERROR("Kicking stuck wait on %s\n",
238847dc10d7SGordon Ross 			  ring->name);
238947dc10d7SGordon Ross 		I915_WRITE_CTL(ring, tmp);
239047dc10d7SGordon Ross 		return kick;
239147dc10d7SGordon Ross 	}
239247dc10d7SGordon Ross 
239347dc10d7SGordon Ross 	if (INTEL_INFO(dev)->gen >= 6 && tmp & RING_WAIT_SEMAPHORE) {
239447dc10d7SGordon Ross 		switch (semaphore_passed(ring)) {
239547dc10d7SGordon Ross 		default:
239647dc10d7SGordon Ross 			return hung;
239747dc10d7SGordon Ross 		case 1:
239847dc10d7SGordon Ross 			DRM_ERROR("Kicking stuck semaphore on %s\n",
239947dc10d7SGordon Ross 				  ring->name);
240047dc10d7SGordon Ross 			I915_WRITE_CTL(ring, tmp);
240147dc10d7SGordon Ross 			return kick;
240247dc10d7SGordon Ross 		case 0:
240347dc10d7SGordon Ross 			return wait;
240447dc10d7SGordon Ross 		}
240547dc10d7SGordon Ross 	}
240647dc10d7SGordon Ross 
240747dc10d7SGordon Ross 	return hung;
240847dc10d7SGordon Ross }
240947dc10d7SGordon Ross 
241047dc10d7SGordon Ross /**
241147dc10d7SGordon Ross  * This is called when the chip hasn't reported back with completed
241247dc10d7SGordon Ross  * batchbuffers in a long time. The first time this is called we simply record
241347dc10d7SGordon Ross  * ACTHD. If ACTHD hasn't changed by the time the hangcheck timer elapses
241447dc10d7SGordon Ross  * Further, acthd is inspected to see if the ring is stuck. On stuck case
241547dc10d7SGordon Ross  * we kick the ring. If we see no progress on three subsequent calls
241647dc10d7SGordon Ross  * again, we assume the chip is wedged and try to fix it.
241747dc10d7SGordon Ross  */
i915_hangcheck_elapsed(void * data)241847dc10d7SGordon Ross void i915_hangcheck_elapsed(void* data)
241947dc10d7SGordon Ross {
242047dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *)data;
242147dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = dev->dev_private;
242247dc10d7SGordon Ross 	struct intel_ring_buffer *ring;
242347dc10d7SGordon Ross 	int i;
242447dc10d7SGordon Ross 	int busy_count = 0, rings_hung = 0;
242547dc10d7SGordon Ross 	bool stuck[I915_NUM_RINGS] = { 0 };
242647dc10d7SGordon Ross #define BUSY 1
242747dc10d7SGordon Ross #define KICK 5
242847dc10d7SGordon Ross #define HUNG 20
242947dc10d7SGordon Ross #define FIRE 30
243047dc10d7SGordon Ross 
243147dc10d7SGordon Ross 	if (!i915_enable_hangcheck)
243247dc10d7SGordon Ross 		return;
243347dc10d7SGordon Ross 
243447dc10d7SGordon Ross 	for_each_ring(ring, dev_priv, i) {
243547dc10d7SGordon Ross 		u32 seqno, acthd;
243647dc10d7SGordon Ross 		bool busy = true;
243747dc10d7SGordon Ross 
243847dc10d7SGordon Ross 		semaphore_clear_deadlocks(dev_priv);
243947dc10d7SGordon Ross 
244047dc10d7SGordon Ross 		seqno = ring->get_seqno(ring, false);
244147dc10d7SGordon Ross 		acthd = intel_ring_get_active_head(ring);
244247dc10d7SGordon Ross 
244347dc10d7SGordon Ross 		if (ring->hangcheck.seqno == seqno) {
244447dc10d7SGordon Ross 			if (ring_idle(ring, seqno)) {
244547dc10d7SGordon Ross 				if (mutex_is_locked(&ring->irq_queue.lock)) {
244647dc10d7SGordon Ross 					/* Issue a wake-up to catch stuck h/w. */
244747dc10d7SGordon Ross 					DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
244847dc10d7SGordon Ross 						  ring->name);
244947dc10d7SGordon Ross 					wake_up_all(&ring->irq_queue);
245047dc10d7SGordon Ross 					ring->hangcheck.score += HUNG;
245147dc10d7SGordon Ross 				} else
245247dc10d7SGordon Ross 					busy = false;
245347dc10d7SGordon Ross 			} else {
245447dc10d7SGordon Ross 				int score = 0;
245547dc10d7SGordon Ross 
245647dc10d7SGordon Ross 				/* We always increment the hangcheck score
245747dc10d7SGordon Ross 				 * if the ring is busy and still processing
245847dc10d7SGordon Ross 				 * the same request, so that no single request
245947dc10d7SGordon Ross 				 * can run indefinitely (such as a chain of
246047dc10d7SGordon Ross 				 * batches). The only time we do not increment
246147dc10d7SGordon Ross 				 * the hangcheck score on this ring, if this
246247dc10d7SGordon Ross 				 * ring is in a legitimate wait for another
246347dc10d7SGordon Ross 				 * ring. In that case the waiting ring is a
246447dc10d7SGordon Ross 				 * victim and we want to be sure we catch the
246547dc10d7SGordon Ross 				 * right culprit. Then every time we do kick
246647dc10d7SGordon Ross 				 * the ring, add a small increment to the
246747dc10d7SGordon Ross 				 * score so that we can catch a batch that is
246847dc10d7SGordon Ross 				 * being repeatedly kicked and so responsible
246947dc10d7SGordon Ross 				 * for stalling the machine.
247047dc10d7SGordon Ross 				 */
247147dc10d7SGordon Ross 				ring->hangcheck.action = ring_stuck(ring,
247247dc10d7SGordon Ross 								    acthd);
247347dc10d7SGordon Ross 
247447dc10d7SGordon Ross 				switch (ring->hangcheck.action) {
247547dc10d7SGordon Ross 				case wait:
247647dc10d7SGordon Ross 					score = 0;
247747dc10d7SGordon Ross 					break;
247847dc10d7SGordon Ross 				case active:
247947dc10d7SGordon Ross 					score = BUSY;
248047dc10d7SGordon Ross 					break;
248147dc10d7SGordon Ross 				case kick:
248247dc10d7SGordon Ross 					score = KICK;
248347dc10d7SGordon Ross 					break;
248447dc10d7SGordon Ross 				case hung:
248547dc10d7SGordon Ross 					score = HUNG;
248647dc10d7SGordon Ross 					stuck[i] = true;
248747dc10d7SGordon Ross 					break;
248847dc10d7SGordon Ross 				}
248947dc10d7SGordon Ross 				ring->hangcheck.score += score;
249047dc10d7SGordon Ross 			}
249147dc10d7SGordon Ross 		} else {
249247dc10d7SGordon Ross 			/* Gradually reduce the count so that we catch DoS
249347dc10d7SGordon Ross 			 * attempts across multiple batches.
249447dc10d7SGordon Ross 			 */
249547dc10d7SGordon Ross 			if (ring->hangcheck.score > 0)
249647dc10d7SGordon Ross 				ring->hangcheck.score--;
249747dc10d7SGordon Ross 		}
249847dc10d7SGordon Ross 
249947dc10d7SGordon Ross 		ring->hangcheck.seqno = seqno;
250047dc10d7SGordon Ross 		ring->hangcheck.acthd = acthd;
250147dc10d7SGordon Ross 		busy_count += busy;
250247dc10d7SGordon Ross 	}
250347dc10d7SGordon Ross 
250447dc10d7SGordon Ross 	for_each_ring(ring, dev_priv, i) {
250547dc10d7SGordon Ross 		if (ring->hangcheck.score > FIRE) {
250647dc10d7SGordon Ross 			DRM_ERROR("%s on %s\n",
250747dc10d7SGordon Ross 				  stuck[i] ? "stuck" : "no progress",
250847dc10d7SGordon Ross 				  ring->name);
250947dc10d7SGordon Ross 			rings_hung++;
251047dc10d7SGordon Ross 		}
251147dc10d7SGordon Ross 	}
251247dc10d7SGordon Ross 
251347dc10d7SGordon Ross 	if (rings_hung) {
251447dc10d7SGordon Ross 		i915_handle_error(dev, true);
251547dc10d7SGordon Ross 		return;
251647dc10d7SGordon Ross 	}
251747dc10d7SGordon Ross 
251847dc10d7SGordon Ross 	if (busy_count)
251947dc10d7SGordon Ross 		/* Reset timer case chip hangs without another request
252047dc10d7SGordon Ross 		 * being added */
252147dc10d7SGordon Ross 		mod_timer(&dev_priv->gpu_error.hangcheck_timer,
252247dc10d7SGordon Ross 			msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
252347dc10d7SGordon Ross }
252447dc10d7SGordon Ross 
ibx_irq_preinstall(struct drm_device * dev)252547dc10d7SGordon Ross static void ibx_irq_preinstall(struct drm_device *dev)
252647dc10d7SGordon Ross {
252747dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
252847dc10d7SGordon Ross 
252947dc10d7SGordon Ross 	if (HAS_PCH_NOP(dev))
253047dc10d7SGordon Ross 		return;
253147dc10d7SGordon Ross 
253247dc10d7SGordon Ross 	/* south display irq */
253347dc10d7SGordon Ross 	I915_WRITE(SDEIMR, 0xffffffff);
253447dc10d7SGordon Ross 	/*
253547dc10d7SGordon Ross 	 * SDEIER is also touched by the interrupt handler to work around missed
253647dc10d7SGordon Ross 	 * PCH interrupts. Hence we can't update it after the interrupt handler
253747dc10d7SGordon Ross 	 * is enabled - instead we unconditionally enable all PCH interrupt
253847dc10d7SGordon Ross 	 * sources here, but then only unmask them as needed with SDEIMR.
253947dc10d7SGordon Ross 	 */
254047dc10d7SGordon Ross 	I915_WRITE(SDEIER, 0xffffffff);
254147dc10d7SGordon Ross 	POSTING_READ(SDEIER);
254247dc10d7SGordon Ross }
254347dc10d7SGordon Ross 
254447dc10d7SGordon Ross /* drm_dma.h hooks
254547dc10d7SGordon Ross */
ironlake_irq_preinstall(struct drm_device * dev)254647dc10d7SGordon Ross static void ironlake_irq_preinstall(struct drm_device *dev)
254747dc10d7SGordon Ross {
254847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
254947dc10d7SGordon Ross 
255047dc10d7SGordon Ross 	atomic_set(&dev_priv->irq_received, 0);
255147dc10d7SGordon Ross 
255247dc10d7SGordon Ross 	I915_WRITE(HWSTAM, 0xeffe);
255347dc10d7SGordon Ross 
255447dc10d7SGordon Ross 	/* XXX hotplug from PCH */
255547dc10d7SGordon Ross 
255647dc10d7SGordon Ross 	I915_WRITE(DEIMR, 0xffffffff);
255747dc10d7SGordon Ross 	I915_WRITE(DEIER, 0x0);
255847dc10d7SGordon Ross 	POSTING_READ(DEIER);
255947dc10d7SGordon Ross 
256047dc10d7SGordon Ross 	/* and GT */
256147dc10d7SGordon Ross 	I915_WRITE(GTIMR, 0xffffffff);
256247dc10d7SGordon Ross 	I915_WRITE(GTIER, 0x0);
256347dc10d7SGordon Ross 	POSTING_READ(GTIER);
256447dc10d7SGordon Ross 
256547dc10d7SGordon Ross 	ibx_irq_preinstall(dev);
256647dc10d7SGordon Ross }
256747dc10d7SGordon Ross 
ivybridge_irq_preinstall(struct drm_device * dev)256847dc10d7SGordon Ross static void ivybridge_irq_preinstall(struct drm_device *dev)
256947dc10d7SGordon Ross {
257047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
257147dc10d7SGordon Ross 
257247dc10d7SGordon Ross 	atomic_set(&dev_priv->irq_received, 0);
257347dc10d7SGordon Ross 
257447dc10d7SGordon Ross 	I915_WRITE(HWSTAM, 0xeffe);
257547dc10d7SGordon Ross 
257647dc10d7SGordon Ross 	/* XXX hotplug from PCH */
257747dc10d7SGordon Ross 
257847dc10d7SGordon Ross 	I915_WRITE(DEIMR, 0xffffffff);
257947dc10d7SGordon Ross 	I915_WRITE(DEIER, 0x0);
258047dc10d7SGordon Ross 	POSTING_READ(DEIER);
258147dc10d7SGordon Ross 
258247dc10d7SGordon Ross 	/* and GT */
258347dc10d7SGordon Ross 	I915_WRITE(GTIMR, 0xffffffff);
258447dc10d7SGordon Ross 	I915_WRITE(GTIER, 0x0);
258547dc10d7SGordon Ross 	POSTING_READ(GTIER);
258647dc10d7SGordon Ross 
258747dc10d7SGordon Ross 	/* Power management */
258847dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIMR, 0xffffffff);
258947dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIER, 0x0);
259047dc10d7SGordon Ross 	POSTING_READ(GEN6_PMIER);
259147dc10d7SGordon Ross 
259247dc10d7SGordon Ross 	ibx_irq_preinstall(dev);
259347dc10d7SGordon Ross }
259447dc10d7SGordon Ross 
valleyview_irq_preinstall(struct drm_device * dev)259547dc10d7SGordon Ross static void valleyview_irq_preinstall(struct drm_device *dev)
259647dc10d7SGordon Ross {
259747dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
259847dc10d7SGordon Ross 	int pipe;
259947dc10d7SGordon Ross 
260047dc10d7SGordon Ross 	atomic_set(&dev_priv->irq_received, 0);
260147dc10d7SGordon Ross 
260247dc10d7SGordon Ross 	/* VLV magic */
260347dc10d7SGordon Ross 	I915_WRITE(VLV_IMR, 0);
260447dc10d7SGordon Ross 	I915_WRITE(RING_IMR(RENDER_RING_BASE), 0);
260547dc10d7SGordon Ross 	I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0);
260647dc10d7SGordon Ross 	I915_WRITE(RING_IMR(BLT_RING_BASE), 0);
260747dc10d7SGordon Ross 
260847dc10d7SGordon Ross 	/* and GT */
260947dc10d7SGordon Ross 	I915_WRITE(GTIIR, I915_READ(GTIIR));
261047dc10d7SGordon Ross 	I915_WRITE(GTIIR, I915_READ(GTIIR));
261147dc10d7SGordon Ross 	I915_WRITE(GTIMR, 0xffffffff);
261247dc10d7SGordon Ross 	I915_WRITE(GTIER, 0x0);
261347dc10d7SGordon Ross 	POSTING_READ(GTIER);
261447dc10d7SGordon Ross 
261547dc10d7SGordon Ross 	I915_WRITE(DPINVGTT, 0xff);
261647dc10d7SGordon Ross 
261747dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_EN, 0);
261847dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
261947dc10d7SGordon Ross 	for_each_pipe(pipe)
262047dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0xffff);
262147dc10d7SGordon Ross 	I915_WRITE(VLV_IIR, 0xffffffff);
262247dc10d7SGordon Ross 	I915_WRITE(VLV_IMR, 0xffffffff);
262347dc10d7SGordon Ross 	I915_WRITE(VLV_IER, 0x0);
262447dc10d7SGordon Ross 	POSTING_READ(VLV_IER);
262547dc10d7SGordon Ross }
262647dc10d7SGordon Ross 
ibx_hpd_irq_setup(struct drm_device * dev)262747dc10d7SGordon Ross static void ibx_hpd_irq_setup(struct drm_device *dev)
262847dc10d7SGordon Ross {
262947dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
263047dc10d7SGordon Ross 	struct drm_mode_config *mode_config = &dev->mode_config;
263147dc10d7SGordon Ross 	struct intel_encoder *intel_encoder;
263247dc10d7SGordon Ross 	u32 mask = ~I915_READ(SDEIMR);
263347dc10d7SGordon Ross 	u32 hotplug;
263447dc10d7SGordon Ross 
263547dc10d7SGordon Ross 	if (HAS_PCH_IBX(dev)) {
263647dc10d7SGordon Ross 		mask &= ~SDE_HOTPLUG_MASK;
263747dc10d7SGordon Ross 		list_for_each_entry(intel_encoder, struct intel_encoder, &mode_config->encoder_list, base.head)
263847dc10d7SGordon Ross 			if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
263947dc10d7SGordon Ross 				mask |= hpd_ibx[intel_encoder->hpd_pin];
264047dc10d7SGordon Ross 	} else {
264147dc10d7SGordon Ross 		mask &= ~SDE_HOTPLUG_MASK_CPT;
264247dc10d7SGordon Ross 		list_for_each_entry(intel_encoder, struct intel_encoder, &mode_config->encoder_list, base.head)
264347dc10d7SGordon Ross 			if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
264447dc10d7SGordon Ross 				mask |= hpd_cpt[intel_encoder->hpd_pin];
264547dc10d7SGordon Ross 	}
264647dc10d7SGordon Ross 
264747dc10d7SGordon Ross 	I915_WRITE(SDEIMR, ~mask);
264847dc10d7SGordon Ross 
264947dc10d7SGordon Ross 	/*
265047dc10d7SGordon Ross 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
265147dc10d7SGordon Ross 	 * duration to 2ms (which is the minimum in the Display Port spec)
265247dc10d7SGordon Ross 	 *
265347dc10d7SGordon Ross 	 * This register is the same on all known PCH chips.
265447dc10d7SGordon Ross 	 */
265547dc10d7SGordon Ross 	hotplug = I915_READ(PCH_PORT_HOTPLUG);
265647dc10d7SGordon Ross 	hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
265747dc10d7SGordon Ross 	hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
265847dc10d7SGordon Ross 	hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
265947dc10d7SGordon Ross 	hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
266047dc10d7SGordon Ross 	I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
266147dc10d7SGordon Ross }
266247dc10d7SGordon Ross 
ibx_irq_postinstall(struct drm_device * dev)266347dc10d7SGordon Ross static void ibx_irq_postinstall(struct drm_device *dev)
266447dc10d7SGordon Ross {
266547dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
266647dc10d7SGordon Ross 	u32 mask;
266747dc10d7SGordon Ross 
266847dc10d7SGordon Ross 	if (HAS_PCH_NOP(dev))
266947dc10d7SGordon Ross 		return;
267047dc10d7SGordon Ross 
267147dc10d7SGordon Ross 	if (HAS_PCH_IBX(dev)) {
267247dc10d7SGordon Ross 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_TRANSB_FIFO_UNDER |
267347dc10d7SGordon Ross 		       SDE_TRANSA_FIFO_UNDER | SDE_POISON;
267447dc10d7SGordon Ross 	} else {
267547dc10d7SGordon Ross 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT | SDE_ERROR_CPT;
267647dc10d7SGordon Ross 
267747dc10d7SGordon Ross 		I915_WRITE(SERR_INT, I915_READ(SERR_INT));
267847dc10d7SGordon Ross 	}
267947dc10d7SGordon Ross 
268047dc10d7SGordon Ross 	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
268147dc10d7SGordon Ross 	I915_WRITE(SDEIMR, ~mask);
268247dc10d7SGordon Ross }
268347dc10d7SGordon Ross 
ironlake_irq_postinstall(struct drm_device * dev)268447dc10d7SGordon Ross static int ironlake_irq_postinstall(struct drm_device *dev)
268547dc10d7SGordon Ross {
268647dc10d7SGordon Ross 	unsigned long irqflags;
268747dc10d7SGordon Ross 
268847dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
268947dc10d7SGordon Ross 	/* enable kind of interrupts always enabled */
269047dc10d7SGordon Ross 	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
269147dc10d7SGordon Ross 			   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
269247dc10d7SGordon Ross 			   DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN |
269347dc10d7SGordon Ross 			   DE_PIPEA_FIFO_UNDERRUN | DE_POISON;
269447dc10d7SGordon Ross 	u32 gt_irqs;
269547dc10d7SGordon Ross 
269647dc10d7SGordon Ross 	dev_priv->irq_mask = ~display_mask;
269747dc10d7SGordon Ross 
269847dc10d7SGordon Ross 	/* should always can generate irq */
269947dc10d7SGordon Ross 	I915_WRITE(DEIIR, I915_READ(DEIIR));
270047dc10d7SGordon Ross 	I915_WRITE(DEIMR, dev_priv->irq_mask);
270147dc10d7SGordon Ross 	I915_WRITE(DEIER, display_mask |
270247dc10d7SGordon Ross 			  DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT);
270347dc10d7SGordon Ross 
270447dc10d7SGordon Ross 	/* LINTED */
270547dc10d7SGordon Ross 	dev_priv->gt_irq_mask = ~0;
270647dc10d7SGordon Ross 
270747dc10d7SGordon Ross 	I915_WRITE(GTIIR, I915_READ(GTIIR));
270847dc10d7SGordon Ross 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
270947dc10d7SGordon Ross 
271047dc10d7SGordon Ross 	gt_irqs = GT_RENDER_USER_INTERRUPT;
271147dc10d7SGordon Ross 
271247dc10d7SGordon Ross 	if (IS_GEN6(dev))
271347dc10d7SGordon Ross 		gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
271447dc10d7SGordon Ross 	else
271547dc10d7SGordon Ross 		gt_irqs |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT |
271647dc10d7SGordon Ross 			   ILK_BSD_USER_INTERRUPT;
271747dc10d7SGordon Ross 
271847dc10d7SGordon Ross 	I915_WRITE(GTIER, gt_irqs);
271947dc10d7SGordon Ross 
272047dc10d7SGordon Ross 	ibx_irq_postinstall(dev);
272147dc10d7SGordon Ross 	POSTING_READ(GTIER);
272247dc10d7SGordon Ross 	POSTING_READ(DEIER);
272347dc10d7SGordon Ross 
272447dc10d7SGordon Ross 	if (IS_IRONLAKE_M(dev)) {
272547dc10d7SGordon Ross 		/* Enable PCU event interrupts
272647dc10d7SGordon Ross 		 *
272747dc10d7SGordon Ross 		 * spinlocking not required here for correctness since interrupt
272847dc10d7SGordon Ross 		 * setup is guaranteed to run in single-threaded context. But we
272947dc10d7SGordon Ross 		 * need it to make the assert_spin_locked happy. */
273047dc10d7SGordon Ross 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
273147dc10d7SGordon Ross 		ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
273247dc10d7SGordon Ross 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
273347dc10d7SGordon Ross 	}
273447dc10d7SGordon Ross 
273547dc10d7SGordon Ross 	return 0;
273647dc10d7SGordon Ross }
273747dc10d7SGordon Ross 
ivybridge_irq_postinstall(struct drm_device * dev)273847dc10d7SGordon Ross static int ivybridge_irq_postinstall(struct drm_device *dev)
273947dc10d7SGordon Ross {
274047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
274147dc10d7SGordon Ross 	/* enable kind of interrupts always enabled */
274247dc10d7SGordon Ross 	u32 display_mask =
274347dc10d7SGordon Ross 		DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | DE_PCH_EVENT_IVB |
274447dc10d7SGordon Ross 		DE_PLANEC_FLIP_DONE_IVB |
274547dc10d7SGordon Ross 		DE_PLANEB_FLIP_DONE_IVB |
274647dc10d7SGordon Ross 		DE_PLANEA_FLIP_DONE_IVB |
274747dc10d7SGordon Ross 		DE_AUX_CHANNEL_A_IVB |
274847dc10d7SGordon Ross 		DE_ERR_INT_IVB;
274947dc10d7SGordon Ross 	u32 pm_irqs = GEN6_PM_RPS_EVENTS;
275047dc10d7SGordon Ross 	u32 gt_irqs;
275147dc10d7SGordon Ross 
275247dc10d7SGordon Ross 	dev_priv->irq_mask = ~display_mask;
275347dc10d7SGordon Ross 
275447dc10d7SGordon Ross 	/* should always can generate irq */
275547dc10d7SGordon Ross 	I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
275647dc10d7SGordon Ross 	I915_WRITE(DEIIR, I915_READ(DEIIR));
275747dc10d7SGordon Ross 	I915_WRITE(DEIMR, dev_priv->irq_mask);
275847dc10d7SGordon Ross 	I915_WRITE(DEIER,
275947dc10d7SGordon Ross 		   display_mask |
276047dc10d7SGordon Ross 		   DE_PIPEC_VBLANK_IVB |
276147dc10d7SGordon Ross 		   DE_PIPEB_VBLANK_IVB |
276247dc10d7SGordon Ross 		   DE_PIPEA_VBLANK_IVB);
276347dc10d7SGordon Ross 	POSTING_READ(DEIER);
276447dc10d7SGordon Ross 
276547dc10d7SGordon Ross 	/* LINTED */
276647dc10d7SGordon Ross 	dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
276747dc10d7SGordon Ross 
276847dc10d7SGordon Ross 	I915_WRITE(GTIIR, I915_READ(GTIIR));
276947dc10d7SGordon Ross 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
277047dc10d7SGordon Ross 
277147dc10d7SGordon Ross 	gt_irqs = GT_RENDER_USER_INTERRUPT | GT_BSD_USER_INTERRUPT |
277247dc10d7SGordon Ross 		  GT_BLT_USER_INTERRUPT | GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
277347dc10d7SGordon Ross 	I915_WRITE(GTIER, gt_irqs);
277447dc10d7SGordon Ross 	POSTING_READ(GTIER);
277547dc10d7SGordon Ross 
277647dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
277747dc10d7SGordon Ross 	if (HAS_VEBOX(dev))
277847dc10d7SGordon Ross 		pm_irqs |= PM_VEBOX_USER_INTERRUPT |
277947dc10d7SGordon Ross 			PM_VEBOX_CS_ERROR_INTERRUPT;
278047dc10d7SGordon Ross 
278147dc10d7SGordon Ross 	/* Our enable/disable rps functions may touch these registers so
278247dc10d7SGordon Ross 	 * make sure to set a known state for only the non-RPS bits.
278347dc10d7SGordon Ross 	 * The RMW is extra paranoia since this should be called after being set
278447dc10d7SGordon Ross 	 * to a known state in preinstall.
278547dc10d7SGordon Ross 	 * */
278647dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIMR,
278747dc10d7SGordon Ross 		   (I915_READ(GEN6_PMIMR) | ~GEN6_PM_RPS_EVENTS) & ~pm_irqs);
278847dc10d7SGordon Ross 	I915_WRITE(GEN6_PMIER,
278947dc10d7SGordon Ross 		   (I915_READ(GEN6_PMIER) & GEN6_PM_RPS_EVENTS) | pm_irqs);
279047dc10d7SGordon Ross 	POSTING_READ(GEN6_PMIER);
279147dc10d7SGordon Ross 
279247dc10d7SGordon Ross 	ibx_irq_postinstall(dev);
279347dc10d7SGordon Ross 
279447dc10d7SGordon Ross 	return 0;
279547dc10d7SGordon Ross }
279647dc10d7SGordon Ross 
valleyview_irq_postinstall(struct drm_device * dev)279747dc10d7SGordon Ross static int valleyview_irq_postinstall(struct drm_device *dev)
279847dc10d7SGordon Ross {
279947dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
280047dc10d7SGordon Ross 	u32 gt_irqs;
280147dc10d7SGordon Ross 	u32 enable_mask;
280247dc10d7SGordon Ross 	u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;
280347dc10d7SGordon Ross 
280447dc10d7SGordon Ross 	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
280547dc10d7SGordon Ross 	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
280647dc10d7SGordon Ross 		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
280747dc10d7SGordon Ross 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
280847dc10d7SGordon Ross 		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
280947dc10d7SGordon Ross 
281047dc10d7SGordon Ross 	/*
281147dc10d7SGordon Ross 	 *Leave vblank interrupts masked initially.  enable/disable will
281247dc10d7SGordon Ross 	 * toggle them based on usage.
281347dc10d7SGordon Ross 	 */
281447dc10d7SGordon Ross 	dev_priv->irq_mask = (~enable_mask) |
281547dc10d7SGordon Ross 		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
281647dc10d7SGordon Ross 		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
281747dc10d7SGordon Ross 
281847dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_EN, 0);
281947dc10d7SGordon Ross 	POSTING_READ(PORT_HOTPLUG_EN);
282047dc10d7SGordon Ross 
282147dc10d7SGordon Ross 	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
282247dc10d7SGordon Ross 	I915_WRITE(VLV_IER, enable_mask);
282347dc10d7SGordon Ross 	I915_WRITE(VLV_IIR, 0xffffffff);
282447dc10d7SGordon Ross 	I915_WRITE(PIPESTAT(0), 0xffff);
282547dc10d7SGordon Ross 	I915_WRITE(PIPESTAT(1), 0xffff);
282647dc10d7SGordon Ross 	POSTING_READ(VLV_IER);
282747dc10d7SGordon Ross 
282847dc10d7SGordon Ross 	i915_enable_pipestat(dev_priv, 0, pipestat_enable);
282947dc10d7SGordon Ross 	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
283047dc10d7SGordon Ross 	i915_enable_pipestat(dev_priv, 1, pipestat_enable);
283147dc10d7SGordon Ross 
283247dc10d7SGordon Ross 	I915_WRITE(VLV_IIR, 0xffffffff);
283347dc10d7SGordon Ross 	I915_WRITE(VLV_IIR, 0xffffffff);
283447dc10d7SGordon Ross 
283547dc10d7SGordon Ross 	I915_WRITE(GTIIR, I915_READ(GTIIR));
283647dc10d7SGordon Ross 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
283747dc10d7SGordon Ross 
283847dc10d7SGordon Ross 	gt_irqs = GT_RENDER_USER_INTERRUPT | GT_BSD_USER_INTERRUPT |
283947dc10d7SGordon Ross 		GT_BLT_USER_INTERRUPT;
284047dc10d7SGordon Ross 	I915_WRITE(GTIER, gt_irqs);
284147dc10d7SGordon Ross 	POSTING_READ(GTIER);
284247dc10d7SGordon Ross 
284347dc10d7SGordon Ross 	/* ack & enable invalid PTE error interrupts */
284447dc10d7SGordon Ross #if 0 /* FIXME: add support to irq handler for checking these bits */
284547dc10d7SGordon Ross 	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
284647dc10d7SGordon Ross 	I915_WRITE(DPINVGTT, DPINVGTT_EN_MASK);
284747dc10d7SGordon Ross #endif
284847dc10d7SGordon Ross 
284947dc10d7SGordon Ross 	I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
285047dc10d7SGordon Ross 
285147dc10d7SGordon Ross 	return 0;
285247dc10d7SGordon Ross }
285347dc10d7SGordon Ross 
valleyview_irq_uninstall(struct drm_device * dev)285447dc10d7SGordon Ross static void valleyview_irq_uninstall(struct drm_device *dev)
285547dc10d7SGordon Ross {
285647dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
285747dc10d7SGordon Ross 	int pipe;
285847dc10d7SGordon Ross 
285947dc10d7SGordon Ross 	if (!dev_priv)
286047dc10d7SGordon Ross 		return;
286147dc10d7SGordon Ross 
286247dc10d7SGordon Ross 	del_timer_sync(&dev_priv->hotplug_reenable_timer);
286347dc10d7SGordon Ross 
286447dc10d7SGordon Ross 	for_each_pipe(pipe)
286547dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0xffff);
286647dc10d7SGordon Ross 
286747dc10d7SGordon Ross 	I915_WRITE(HWSTAM, 0xffffffff);
286847dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_EN, 0);
286947dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
287047dc10d7SGordon Ross 	for_each_pipe(pipe)
287147dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0xffff);
287247dc10d7SGordon Ross 	I915_WRITE(VLV_IIR, 0xffffffff);
287347dc10d7SGordon Ross 	I915_WRITE(VLV_IMR, 0xffffffff);
287447dc10d7SGordon Ross 	I915_WRITE(VLV_IER, 0x0);
287547dc10d7SGordon Ross 	POSTING_READ(VLV_IER);
287647dc10d7SGordon Ross }
287747dc10d7SGordon Ross 
ironlake_irq_uninstall(struct drm_device * dev)287847dc10d7SGordon Ross static void ironlake_irq_uninstall(struct drm_device *dev)
287947dc10d7SGordon Ross {
288047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
288147dc10d7SGordon Ross 
288247dc10d7SGordon Ross 	if (!dev_priv)
288347dc10d7SGordon Ross 		return;
288447dc10d7SGordon Ross 
288547dc10d7SGordon Ross 	del_timer_sync(&dev_priv->hotplug_reenable_timer);
288647dc10d7SGordon Ross 
288747dc10d7SGordon Ross 	I915_WRITE(HWSTAM, 0xffffffff);
288847dc10d7SGordon Ross 
288947dc10d7SGordon Ross 	I915_WRITE(DEIMR, 0xffffffff);
289047dc10d7SGordon Ross 	I915_WRITE(DEIER, 0x0);
289147dc10d7SGordon Ross 	I915_WRITE(DEIIR, I915_READ(DEIIR));
289247dc10d7SGordon Ross 	if (IS_GEN7(dev))
289347dc10d7SGordon Ross 		I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
289447dc10d7SGordon Ross 
289547dc10d7SGordon Ross 	I915_WRITE(GTIMR, 0xffffffff);
289647dc10d7SGordon Ross 	I915_WRITE(GTIER, 0x0);
289747dc10d7SGordon Ross 	I915_WRITE(GTIIR, I915_READ(GTIIR));
289847dc10d7SGordon Ross 
289947dc10d7SGordon Ross 	if (HAS_PCH_NOP(dev))
290047dc10d7SGordon Ross 		return;
290147dc10d7SGordon Ross 
290247dc10d7SGordon Ross 	I915_WRITE(SDEIMR, 0xffffffff);
290347dc10d7SGordon Ross 	I915_WRITE(SDEIER, 0x0);
290447dc10d7SGordon Ross 	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
290547dc10d7SGordon Ross 	if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
290647dc10d7SGordon Ross 		I915_WRITE(SERR_INT, I915_READ(SERR_INT));
290747dc10d7SGordon Ross }
290847dc10d7SGordon Ross 
i8xx_irq_preinstall(struct drm_device * dev)290947dc10d7SGordon Ross static void i8xx_irq_preinstall(struct drm_device * dev)
291047dc10d7SGordon Ross {
291147dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
291247dc10d7SGordon Ross 	int pipe;
291347dc10d7SGordon Ross 
291447dc10d7SGordon Ross 	atomic_set(&dev_priv->irq_received, 0);
291547dc10d7SGordon Ross 
291647dc10d7SGordon Ross 	for_each_pipe(pipe)
291747dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0);
291847dc10d7SGordon Ross 	I915_WRITE16(IMR, 0xffff);
291947dc10d7SGordon Ross 	I915_WRITE16(IER, 0x0);
292047dc10d7SGordon Ross 	POSTING_READ16(IER);
292147dc10d7SGordon Ross }
292247dc10d7SGordon Ross 
i8xx_irq_postinstall(struct drm_device * dev)292347dc10d7SGordon Ross static int i8xx_irq_postinstall(struct drm_device *dev)
292447dc10d7SGordon Ross {
292547dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
292647dc10d7SGordon Ross 
292747dc10d7SGordon Ross 	I915_WRITE16(EMR,
292847dc10d7SGordon Ross 		     ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
292947dc10d7SGordon Ross 
293047dc10d7SGordon Ross 	/* Unmask the interrupts that we always want on. */
293147dc10d7SGordon Ross 	/* LINTED */
293247dc10d7SGordon Ross 	dev_priv->irq_mask =
293347dc10d7SGordon Ross 		~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
293447dc10d7SGordon Ross 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
293547dc10d7SGordon Ross 		  I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
293647dc10d7SGordon Ross 		  I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
293747dc10d7SGordon Ross 		  I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
293847dc10d7SGordon Ross 	I915_WRITE16(IMR, dev_priv->irq_mask);
293947dc10d7SGordon Ross 
294047dc10d7SGordon Ross 	I915_WRITE16(IER,
294147dc10d7SGordon Ross 		     I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
294247dc10d7SGordon Ross 		     I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
294347dc10d7SGordon Ross 		     I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
294447dc10d7SGordon Ross 		     I915_USER_INTERRUPT);
294547dc10d7SGordon Ross 	POSTING_READ16(IER);
294647dc10d7SGordon Ross 
294747dc10d7SGordon Ross 	return 0;
294847dc10d7SGordon Ross }
294947dc10d7SGordon Ross 
295047dc10d7SGordon Ross /*
295147dc10d7SGordon Ross  * Returns true when a page flip has completed.
295247dc10d7SGordon Ross  */
i8xx_handle_vblank(struct drm_device * dev,int pipe,u16 iir)295347dc10d7SGordon Ross static bool i8xx_handle_vblank(struct drm_device *dev,
295447dc10d7SGordon Ross 			       int pipe, u16 iir)
295547dc10d7SGordon Ross {
295647dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = dev->dev_private;
295747dc10d7SGordon Ross 	u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
295847dc10d7SGordon Ross 
295947dc10d7SGordon Ross 	if (!drm_handle_vblank(dev, pipe))
296047dc10d7SGordon Ross 		return false;
296147dc10d7SGordon Ross 
296247dc10d7SGordon Ross 	if ((iir & flip_pending) == 0)
296347dc10d7SGordon Ross 		return false;
296447dc10d7SGordon Ross 
296547dc10d7SGordon Ross 	intel_prepare_page_flip(dev, pipe);
296647dc10d7SGordon Ross 
296747dc10d7SGordon Ross 	/* We detect FlipDone by looking for the change in PendingFlip from '1'
296847dc10d7SGordon Ross 	 * to '0' on the following vblank, i.e. IIR has the Pendingflip
296947dc10d7SGordon Ross 	 * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
297047dc10d7SGordon Ross 	 * the flip is completed (no longer pending). Since this doesn't raise
297147dc10d7SGordon Ross 	 * an interrupt per se, we watch for the change at vblank.
297247dc10d7SGordon Ross 	 */
297347dc10d7SGordon Ross 	if (I915_READ16(ISR) & flip_pending)
297447dc10d7SGordon Ross 		return false;
297547dc10d7SGordon Ross 
297647dc10d7SGordon Ross 	intel_finish_page_flip(dev, pipe);
297747dc10d7SGordon Ross 
297847dc10d7SGordon Ross 	return true;
297947dc10d7SGordon Ross }
298047dc10d7SGordon Ross 
i8xx_irq_handler(DRM_IRQ_ARGS)298147dc10d7SGordon Ross static irqreturn_t i8xx_irq_handler(DRM_IRQ_ARGS)
298247dc10d7SGordon Ross {
298347dc10d7SGordon Ross 	/* LINTED */
298447dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *) arg;
298547dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
298647dc10d7SGordon Ross 	u16 iir, new_iir;
298747dc10d7SGordon Ross 	u32 pipe_stats[2] = { 0 };
298847dc10d7SGordon Ross 	unsigned long irqflags;
298947dc10d7SGordon Ross 	int pipe;
299047dc10d7SGordon Ross 	u16 flip_mask =
299147dc10d7SGordon Ross 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
299247dc10d7SGordon Ross 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
299347dc10d7SGordon Ross 
299447dc10d7SGordon Ross 	atomic_inc(&dev_priv->irq_received);
299547dc10d7SGordon Ross 
299647dc10d7SGordon Ross 	iir = I915_READ16(IIR);
299747dc10d7SGordon Ross 	if (iir == 0)
299847dc10d7SGordon Ross 		return IRQ_NONE;
299947dc10d7SGordon Ross 
300047dc10d7SGordon Ross 	while (iir & ~flip_mask) {
300147dc10d7SGordon Ross 		/* Can't rely on pipestat interrupt bit in iir as it might
300247dc10d7SGordon Ross 		 * have been cleared after the pipestat interrupt was received.
300347dc10d7SGordon Ross 		 * It doesn't set the bit in iir again, but it still produces
300447dc10d7SGordon Ross 		 * interrupts (for non-MSI).
300547dc10d7SGordon Ross 		 */
300647dc10d7SGordon Ross 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
300747dc10d7SGordon Ross 		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
300847dc10d7SGordon Ross 			i915_handle_error(dev, false);
300947dc10d7SGordon Ross 
301047dc10d7SGordon Ross 		for_each_pipe(pipe) {
301147dc10d7SGordon Ross 			int reg = PIPESTAT(pipe);
301247dc10d7SGordon Ross 			pipe_stats[pipe] = I915_READ(reg);
301347dc10d7SGordon Ross 
301447dc10d7SGordon Ross 			/*
301547dc10d7SGordon Ross 			 * Clear the PIPE*STAT regs before the IIR
301647dc10d7SGordon Ross 			 */
301747dc10d7SGordon Ross 			if (pipe_stats[pipe] & 0x8000ffff) {
301847dc10d7SGordon Ross 				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
301947dc10d7SGordon Ross 					DRM_DEBUG_DRIVER("pipe %c underrun\n",
302047dc10d7SGordon Ross 							 pipe_name(pipe));
302147dc10d7SGordon Ross 				I915_WRITE(reg, pipe_stats[pipe]);
302247dc10d7SGordon Ross 			}
302347dc10d7SGordon Ross 		}
302447dc10d7SGordon Ross 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
302547dc10d7SGordon Ross 
302647dc10d7SGordon Ross 		I915_WRITE16(IIR, iir & ~flip_mask);
302747dc10d7SGordon Ross 		new_iir = I915_READ16(IIR); /* Flush posted writes */
302847dc10d7SGordon Ross 
302947dc10d7SGordon Ross 		i915_update_dri1_breadcrumb(dev);
303047dc10d7SGordon Ross 
303147dc10d7SGordon Ross 		if (iir & I915_USER_INTERRUPT)
303247dc10d7SGordon Ross 			notify_ring(dev, &dev_priv->ring[RCS]);
303347dc10d7SGordon Ross 
303447dc10d7SGordon Ross 		if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS &&
303547dc10d7SGordon Ross 		    i8xx_handle_vblank(dev, 0, iir))
303647dc10d7SGordon Ross 			flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(0);
303747dc10d7SGordon Ross 
303847dc10d7SGordon Ross 		if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS &&
303947dc10d7SGordon Ross 		    i8xx_handle_vblank(dev, 1, iir))
304047dc10d7SGordon Ross 			flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(1);
304147dc10d7SGordon Ross 
304247dc10d7SGordon Ross 		iir = new_iir;
304347dc10d7SGordon Ross 	}
304447dc10d7SGordon Ross 
304547dc10d7SGordon Ross 	return IRQ_HANDLED;
304647dc10d7SGordon Ross }
304747dc10d7SGordon Ross 
i8xx_irq_uninstall(struct drm_device * dev)304847dc10d7SGordon Ross static void i8xx_irq_uninstall(struct drm_device * dev)
304947dc10d7SGordon Ross {
305047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
305147dc10d7SGordon Ross 	int pipe;
305247dc10d7SGordon Ross 
305347dc10d7SGordon Ross 	for_each_pipe(pipe) {
305447dc10d7SGordon Ross 		/* Clear enable bits; then clear status bits */
305547dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0);
305647dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
305747dc10d7SGordon Ross 	}
305847dc10d7SGordon Ross 	I915_WRITE16(IMR, 0xffff);
305947dc10d7SGordon Ross 	I915_WRITE16(IER, 0x0);
306047dc10d7SGordon Ross 	I915_WRITE16(IIR, I915_READ16(IIR));
306147dc10d7SGordon Ross }
306247dc10d7SGordon Ross 
i915_irq_preinstall(struct drm_device * dev)306347dc10d7SGordon Ross static void i915_irq_preinstall(struct drm_device * dev)
306447dc10d7SGordon Ross {
306547dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
306647dc10d7SGordon Ross 	int pipe;
306747dc10d7SGordon Ross 
306847dc10d7SGordon Ross 	atomic_set(&dev_priv->irq_received, 0);
306947dc10d7SGordon Ross 
307047dc10d7SGordon Ross 	if (I915_HAS_HOTPLUG(dev)) {
307147dc10d7SGordon Ross 		I915_WRITE(PORT_HOTPLUG_EN, 0);
307247dc10d7SGordon Ross 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
307347dc10d7SGordon Ross 	}
307447dc10d7SGordon Ross 
307547dc10d7SGordon Ross 	I915_WRITE16(HWSTAM, 0xeffe);
307647dc10d7SGordon Ross 	for_each_pipe(pipe)
307747dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0);
307847dc10d7SGordon Ross 	I915_WRITE(IMR, 0xffffffff);
307947dc10d7SGordon Ross 	I915_WRITE(IER, 0x0);
308047dc10d7SGordon Ross 	POSTING_READ(IER);
308147dc10d7SGordon Ross }
308247dc10d7SGordon Ross 
i915_irq_postinstall(struct drm_device * dev)308347dc10d7SGordon Ross static int i915_irq_postinstall(struct drm_device *dev)
308447dc10d7SGordon Ross {
308547dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
308647dc10d7SGordon Ross 	u32 enable_mask;
308747dc10d7SGordon Ross 
308847dc10d7SGordon Ross 	I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
308947dc10d7SGordon Ross 
309047dc10d7SGordon Ross 	/* Unmask the interrupts that we always want on. */
309147dc10d7SGordon Ross 	/* LINTED */
309247dc10d7SGordon Ross 	dev_priv->irq_mask =
309347dc10d7SGordon Ross 		~(I915_ASLE_INTERRUPT |
309447dc10d7SGordon Ross 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
309547dc10d7SGordon Ross 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
309647dc10d7SGordon Ross 		  I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
309747dc10d7SGordon Ross 		  I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
309847dc10d7SGordon Ross 		  I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
309947dc10d7SGordon Ross 
310047dc10d7SGordon Ross 	enable_mask =
310147dc10d7SGordon Ross 		I915_ASLE_INTERRUPT |
310247dc10d7SGordon Ross 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
310347dc10d7SGordon Ross 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
310447dc10d7SGordon Ross 		I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
310547dc10d7SGordon Ross 		I915_USER_INTERRUPT;
310647dc10d7SGordon Ross 
310747dc10d7SGordon Ross 	if (I915_HAS_HOTPLUG(dev)) {
310847dc10d7SGordon Ross 		I915_WRITE(PORT_HOTPLUG_EN, 0);
310947dc10d7SGordon Ross 		POSTING_READ(PORT_HOTPLUG_EN);
311047dc10d7SGordon Ross 
311147dc10d7SGordon Ross 		/* Enable in IER... */
311247dc10d7SGordon Ross 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
311347dc10d7SGordon Ross 		/* and unmask in IMR */
311447dc10d7SGordon Ross 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
311547dc10d7SGordon Ross 	}
311647dc10d7SGordon Ross 
311747dc10d7SGordon Ross 	I915_WRITE(IMR, dev_priv->irq_mask);
311847dc10d7SGordon Ross 	I915_WRITE(IER, enable_mask);
311947dc10d7SGordon Ross 	POSTING_READ(IER);
312047dc10d7SGordon Ross 
312147dc10d7SGordon Ross 
312247dc10d7SGordon Ross 	return 0;
312347dc10d7SGordon Ross }
312447dc10d7SGordon Ross 
312547dc10d7SGordon Ross /*
312647dc10d7SGordon Ross  * Returns true when a page flip has completed.
312747dc10d7SGordon Ross  */
i915_handle_vblank(struct drm_device * dev,int plane,int pipe,u32 iir)312847dc10d7SGordon Ross static bool i915_handle_vblank(struct drm_device *dev,
312947dc10d7SGordon Ross 			       int plane, int pipe, u32 iir)
313047dc10d7SGordon Ross {
313147dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = dev->dev_private;
313247dc10d7SGordon Ross 	u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
313347dc10d7SGordon Ross 
313447dc10d7SGordon Ross 	if (!drm_handle_vblank(dev, pipe))
313547dc10d7SGordon Ross 		return false;
313647dc10d7SGordon Ross 
313747dc10d7SGordon Ross 	if ((iir & flip_pending) == 0)
313847dc10d7SGordon Ross 		return false;
313947dc10d7SGordon Ross 
314047dc10d7SGordon Ross 	intel_prepare_page_flip(dev, plane);
314147dc10d7SGordon Ross 
314247dc10d7SGordon Ross 	/* We detect FlipDone by looking for the change in PendingFlip from '1'
314347dc10d7SGordon Ross 	 * to '0' on the following vblank, i.e. IIR has the Pendingflip
314447dc10d7SGordon Ross 	 * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
314547dc10d7SGordon Ross 	 * the flip is completed (no longer pending). Since this doesn't raise
314647dc10d7SGordon Ross 	 * an interrupt per se, we watch for the change at vblank.
314747dc10d7SGordon Ross 	 */
314847dc10d7SGordon Ross 	if (I915_READ(ISR) & flip_pending)
314947dc10d7SGordon Ross 		return false;
315047dc10d7SGordon Ross 
315147dc10d7SGordon Ross 	intel_finish_page_flip(dev, pipe);
315247dc10d7SGordon Ross 
315347dc10d7SGordon Ross 	return true;
315447dc10d7SGordon Ross }
315547dc10d7SGordon Ross 
i915_irq_handler(DRM_IRQ_ARGS)315647dc10d7SGordon Ross static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
315747dc10d7SGordon Ross {
315847dc10d7SGordon Ross 	/* LINTED */
315947dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *) arg;
316047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
316147dc10d7SGordon Ross 	u32 iir, new_iir, pipe_stats[I915_MAX_PIPES] = { 0 };
316247dc10d7SGordon Ross 	unsigned long irqflags;
316347dc10d7SGordon Ross 	u32 flip_mask =
316447dc10d7SGordon Ross 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
316547dc10d7SGordon Ross 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
316647dc10d7SGordon Ross 	int pipe, ret = IRQ_NONE;
316747dc10d7SGordon Ross 
316847dc10d7SGordon Ross 	atomic_inc(&dev_priv->irq_received);
316947dc10d7SGordon Ross 
317047dc10d7SGordon Ross 	iir = I915_READ(IIR);
317147dc10d7SGordon Ross 	do {
317247dc10d7SGordon Ross 		bool irq_received = (iir & ~flip_mask) != 0;
317347dc10d7SGordon Ross 
317447dc10d7SGordon Ross 		/* Can't rely on pipestat interrupt bit in iir as it might
317547dc10d7SGordon Ross 		 * have been cleared after the pipestat interrupt was received.
317647dc10d7SGordon Ross 		 * It doesn't set the bit in iir again, but it still produces
317747dc10d7SGordon Ross 		 * interrupts (for non-MSI).
317847dc10d7SGordon Ross 		 */
317947dc10d7SGordon Ross 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
318047dc10d7SGordon Ross 		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
318147dc10d7SGordon Ross 			i915_handle_error(dev, false);
318247dc10d7SGordon Ross 
318347dc10d7SGordon Ross 		for_each_pipe(pipe) {
318447dc10d7SGordon Ross 			int reg = PIPESTAT(pipe);
318547dc10d7SGordon Ross 			pipe_stats[pipe] = I915_READ(reg);
318647dc10d7SGordon Ross 
318747dc10d7SGordon Ross 			/* Clear the PIPE*STAT regs before the IIR */
318847dc10d7SGordon Ross 			if (pipe_stats[pipe] & 0x8000ffff) {
318947dc10d7SGordon Ross 				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
319047dc10d7SGordon Ross 					DRM_DEBUG_DRIVER("pipe %c underrun\n",
319147dc10d7SGordon Ross 							 pipe_name(pipe));
319247dc10d7SGordon Ross 				I915_WRITE(reg, pipe_stats[pipe]);
319347dc10d7SGordon Ross 				irq_received = true;
319447dc10d7SGordon Ross 			}
319547dc10d7SGordon Ross 		}
319647dc10d7SGordon Ross 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
319747dc10d7SGordon Ross 
319847dc10d7SGordon Ross 		if (!irq_received)
319947dc10d7SGordon Ross 			break;
320047dc10d7SGordon Ross 
320147dc10d7SGordon Ross 		/* Consume port.  Then clear IIR or we'll miss events */
320247dc10d7SGordon Ross 		if ((I915_HAS_HOTPLUG(dev)) &&
320347dc10d7SGordon Ross 		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
320447dc10d7SGordon Ross 			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
320547dc10d7SGordon Ross 			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
320647dc10d7SGordon Ross 
320747dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
320847dc10d7SGordon Ross 				  hotplug_status);
320947dc10d7SGordon Ross 
321047dc10d7SGordon Ross 			intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
321147dc10d7SGordon Ross 
321247dc10d7SGordon Ross 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
321347dc10d7SGordon Ross 			POSTING_READ(PORT_HOTPLUG_STAT);
321447dc10d7SGordon Ross 		}
321547dc10d7SGordon Ross 
321647dc10d7SGordon Ross 		I915_WRITE(IIR, iir & ~flip_mask);
321747dc10d7SGordon Ross 		new_iir = I915_READ(IIR); /* Flush posted writes */
321847dc10d7SGordon Ross 
321947dc10d7SGordon Ross 		if (iir & I915_USER_INTERRUPT)
322047dc10d7SGordon Ross 			notify_ring(dev, &dev_priv->ring[RCS]);
322147dc10d7SGordon Ross 
322247dc10d7SGordon Ross 		for_each_pipe(pipe) {
322347dc10d7SGordon Ross 			int plane = pipe;
322447dc10d7SGordon Ross 			if (IS_MOBILE(dev))
322547dc10d7SGordon Ross 				plane = !plane;
322647dc10d7SGordon Ross 
322747dc10d7SGordon Ross 			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
322847dc10d7SGordon Ross 			    i915_handle_vblank(dev, plane, pipe, iir))
322947dc10d7SGordon Ross 				flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
323047dc10d7SGordon Ross 
323147dc10d7SGordon Ross 		}
323247dc10d7SGordon Ross 
323347dc10d7SGordon Ross 
323447dc10d7SGordon Ross 		/* With MSI, interrupts are only generated when iir
323547dc10d7SGordon Ross 		 * transitions from zero to nonzero.  If another bit got
323647dc10d7SGordon Ross 		 * set while we were handling the existing iir bits, then
323747dc10d7SGordon Ross 		 * we would never get another interrupt.
323847dc10d7SGordon Ross 		 *
323947dc10d7SGordon Ross 		 * This is fine on non-MSI as well, as if we hit this path
324047dc10d7SGordon Ross 		 * we avoid exiting the interrupt handler only to generate
324147dc10d7SGordon Ross 		 * another one.
324247dc10d7SGordon Ross 		 *
324347dc10d7SGordon Ross 		 * Note that for MSI this could cause a stray interrupt report
324447dc10d7SGordon Ross 		 * if an interrupt landed in the time between writing IIR and
324547dc10d7SGordon Ross 		 * the posting read.  This should be rare enough to never
324647dc10d7SGordon Ross 		 * trigger the 99% of 100,000 interrupts test for disabling
324747dc10d7SGordon Ross 		 * stray interrupts.
324847dc10d7SGordon Ross 		 */
324947dc10d7SGordon Ross 		ret = IRQ_HANDLED;
325047dc10d7SGordon Ross 		iir = new_iir;
325147dc10d7SGordon Ross 	} while (iir & ~flip_mask);
325247dc10d7SGordon Ross 
325347dc10d7SGordon Ross 	i915_update_dri1_breadcrumb(dev);
325447dc10d7SGordon Ross 
325547dc10d7SGordon Ross 	return ret;
325647dc10d7SGordon Ross }
325747dc10d7SGordon Ross 
i915_irq_uninstall(struct drm_device * dev)325847dc10d7SGordon Ross static void i915_irq_uninstall(struct drm_device * dev)
325947dc10d7SGordon Ross {
326047dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
326147dc10d7SGordon Ross 	int pipe;
326247dc10d7SGordon Ross 
326347dc10d7SGordon Ross 	del_timer_sync(&dev_priv->hotplug_reenable_timer);
326447dc10d7SGordon Ross 
326547dc10d7SGordon Ross 	if (I915_HAS_HOTPLUG(dev)) {
326647dc10d7SGordon Ross 		I915_WRITE(PORT_HOTPLUG_EN, 0);
326747dc10d7SGordon Ross 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
326847dc10d7SGordon Ross 	}
326947dc10d7SGordon Ross 
327047dc10d7SGordon Ross 	I915_WRITE16(HWSTAM, 0xffff);
327147dc10d7SGordon Ross 	for_each_pipe(pipe) {
327247dc10d7SGordon Ross 		/* Clear enable bits; then clear status bits */
327347dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0);
327447dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
327547dc10d7SGordon Ross 	}
327647dc10d7SGordon Ross 	I915_WRITE(IMR, 0xffffffff);
327747dc10d7SGordon Ross 	I915_WRITE(IER, 0x0);
327847dc10d7SGordon Ross 
327947dc10d7SGordon Ross 	I915_WRITE(IIR, I915_READ(IIR));
328047dc10d7SGordon Ross }
328147dc10d7SGordon Ross 
i965_irq_preinstall(struct drm_device * dev)328247dc10d7SGordon Ross static void i965_irq_preinstall(struct drm_device * dev)
328347dc10d7SGordon Ross {
328447dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
328547dc10d7SGordon Ross 	int pipe;
328647dc10d7SGordon Ross 
328747dc10d7SGordon Ross 	atomic_set(&dev_priv->irq_received, 0);
328847dc10d7SGordon Ross 
328947dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_EN, 0);
329047dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
329147dc10d7SGordon Ross 
329247dc10d7SGordon Ross 	I915_WRITE(HWSTAM, 0xeffe);
329347dc10d7SGordon Ross 	for_each_pipe(pipe)
329447dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0);
329547dc10d7SGordon Ross 	I915_WRITE(IMR, 0xffffffff);
329647dc10d7SGordon Ross 	I915_WRITE(IER, 0x0);
329747dc10d7SGordon Ross 	POSTING_READ(IER);
329847dc10d7SGordon Ross }
329947dc10d7SGordon Ross 
i965_irq_postinstall(struct drm_device * dev)330047dc10d7SGordon Ross static int i965_irq_postinstall(struct drm_device *dev)
330147dc10d7SGordon Ross {
330247dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
330347dc10d7SGordon Ross 	u32 enable_mask;
330447dc10d7SGordon Ross 	u32 error_mask;
330547dc10d7SGordon Ross 
330647dc10d7SGordon Ross 	/* Unmask the interrupts that we always want on. */
330747dc10d7SGordon Ross 	/* LINTED */
330847dc10d7SGordon Ross 	dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
330947dc10d7SGordon Ross 			       I915_DISPLAY_PORT_INTERRUPT |
331047dc10d7SGordon Ross 			       I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
331147dc10d7SGordon Ross 			       I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
331247dc10d7SGordon Ross 			       I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
331347dc10d7SGordon Ross 			       I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
331447dc10d7SGordon Ross 			       I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
331547dc10d7SGordon Ross 
331647dc10d7SGordon Ross 	enable_mask = ~dev_priv->irq_mask;
331747dc10d7SGordon Ross 	enable_mask &= ~(I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
331847dc10d7SGordon Ross 			 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT);
331947dc10d7SGordon Ross 	enable_mask |= I915_USER_INTERRUPT;
332047dc10d7SGordon Ross 
332147dc10d7SGordon Ross 	if (IS_G4X(dev))
332247dc10d7SGordon Ross 		enable_mask |= I915_BSD_USER_INTERRUPT;
332347dc10d7SGordon Ross 
332447dc10d7SGordon Ross 	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
332547dc10d7SGordon Ross 
332647dc10d7SGordon Ross 	/*
332747dc10d7SGordon Ross 	 * Enable some error detection, note the instruction error mask
332847dc10d7SGordon Ross 	 * bit is reserved, so we leave it masked.
332947dc10d7SGordon Ross 	 */
333047dc10d7SGordon Ross 	if (IS_G4X(dev)) {
333147dc10d7SGordon Ross 		/* LINTED */
333247dc10d7SGordon Ross 		error_mask = ~(GM45_ERROR_PAGE_TABLE |
333347dc10d7SGordon Ross 			       GM45_ERROR_MEM_PRIV |
333447dc10d7SGordon Ross 			       GM45_ERROR_CP_PRIV |
333547dc10d7SGordon Ross 			       I915_ERROR_MEMORY_REFRESH);
333647dc10d7SGordon Ross 	} else {
333747dc10d7SGordon Ross 		/* LINTED */
333847dc10d7SGordon Ross 		error_mask = ~(I915_ERROR_PAGE_TABLE |
333947dc10d7SGordon Ross 			       I915_ERROR_MEMORY_REFRESH);
334047dc10d7SGordon Ross 	}
334147dc10d7SGordon Ross 	I915_WRITE(EMR, error_mask);
334247dc10d7SGordon Ross 
334347dc10d7SGordon Ross 	I915_WRITE(IMR, dev_priv->irq_mask);
334447dc10d7SGordon Ross 	I915_WRITE(IER, enable_mask);
334547dc10d7SGordon Ross 	POSTING_READ(IER);
334647dc10d7SGordon Ross 
334747dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_EN, 0);
334847dc10d7SGordon Ross 	POSTING_READ(PORT_HOTPLUG_EN);
334947dc10d7SGordon Ross 
335047dc10d7SGordon Ross 
335147dc10d7SGordon Ross 	return 0;
335247dc10d7SGordon Ross }
335347dc10d7SGordon Ross 
i915_hpd_irq_setup(struct drm_device * dev)335447dc10d7SGordon Ross static void i915_hpd_irq_setup(struct drm_device *dev)
335547dc10d7SGordon Ross {
335647dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
335747dc10d7SGordon Ross 	struct drm_mode_config *mode_config = &dev->mode_config;
335847dc10d7SGordon Ross 	struct intel_encoder *intel_encoder;
335947dc10d7SGordon Ross 	u32 hotplug_en;
336047dc10d7SGordon Ross 
336147dc10d7SGordon Ross 	assert_spin_locked(&dev_priv->irq_lock);
336247dc10d7SGordon Ross 
336347dc10d7SGordon Ross 	if (I915_HAS_HOTPLUG(dev)) {
336447dc10d7SGordon Ross 		hotplug_en = I915_READ(PORT_HOTPLUG_EN);
336547dc10d7SGordon Ross 		hotplug_en &= ~HOTPLUG_INT_EN_MASK;
336647dc10d7SGordon Ross 		/* Note HDMI and DP share hotplug bits */
336747dc10d7SGordon Ross 		/* enable bits are the same for all generations */
336847dc10d7SGordon Ross 		list_for_each_entry(intel_encoder, struct intel_encoder, &mode_config->encoder_list, base.head)
336947dc10d7SGordon Ross 			if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
337047dc10d7SGordon Ross 				hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
337147dc10d7SGordon Ross 		/* Programming the CRT detection parameters tends
337247dc10d7SGordon Ross 		   to generate a spurious hotplug event about three
337347dc10d7SGordon Ross 		   seconds later.  So just do it once.
337447dc10d7SGordon Ross 		*/
337547dc10d7SGordon Ross 		if (IS_G4X(dev))
337647dc10d7SGordon Ross 			hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
337747dc10d7SGordon Ross 		hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
337847dc10d7SGordon Ross 		hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
337947dc10d7SGordon Ross 
338047dc10d7SGordon Ross 		/* Ignore TV since it's buggy */
338147dc10d7SGordon Ross 		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
338247dc10d7SGordon Ross 	}
338347dc10d7SGordon Ross }
338447dc10d7SGordon Ross 
i965_irq_handler(DRM_IRQ_ARGS)338547dc10d7SGordon Ross static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
338647dc10d7SGordon Ross {
338747dc10d7SGordon Ross 	/* LINTED */
338847dc10d7SGordon Ross 	struct drm_device *dev = (struct drm_device *) arg;
338947dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
339047dc10d7SGordon Ross 	u32 iir, new_iir;
339147dc10d7SGordon Ross 	u32 pipe_stats[I915_MAX_PIPES] = { 0 };
339247dc10d7SGordon Ross 	unsigned long irqflags;
339347dc10d7SGordon Ross 	int irq_received;
339447dc10d7SGordon Ross 	int ret = IRQ_NONE, pipe;
339547dc10d7SGordon Ross 	u32 flip_mask =
339647dc10d7SGordon Ross 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
339747dc10d7SGordon Ross 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
339847dc10d7SGordon Ross 
339947dc10d7SGordon Ross 	atomic_inc(&dev_priv->irq_received);
340047dc10d7SGordon Ross 
340147dc10d7SGordon Ross 	iir = I915_READ(IIR);
340247dc10d7SGordon Ross 
340347dc10d7SGordon Ross 	for (;;) {
340447dc10d7SGordon Ross 
340547dc10d7SGordon Ross 		irq_received = (iir & ~flip_mask) != 0;
340647dc10d7SGordon Ross 
340747dc10d7SGordon Ross 		/* Can't rely on pipestat interrupt bit in iir as it might
340847dc10d7SGordon Ross 		 * have been cleared after the pipestat interrupt was received.
340947dc10d7SGordon Ross 		 * It doesn't set the bit in iir again, but it still produces
341047dc10d7SGordon Ross 		 * interrupts (for non-MSI).
341147dc10d7SGordon Ross 		 */
341247dc10d7SGordon Ross 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
341347dc10d7SGordon Ross 		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
341447dc10d7SGordon Ross 			i915_handle_error(dev, false);
341547dc10d7SGordon Ross 
341647dc10d7SGordon Ross 		for_each_pipe(pipe) {
341747dc10d7SGordon Ross 			int reg = PIPESTAT(pipe);
341847dc10d7SGordon Ross 			pipe_stats[pipe] = I915_READ(reg);
341947dc10d7SGordon Ross 
342047dc10d7SGordon Ross 			/*
342147dc10d7SGordon Ross 			 * Clear the PIPE*STAT regs before the IIR
342247dc10d7SGordon Ross 			 */
342347dc10d7SGordon Ross 			if (pipe_stats[pipe] & 0x8000ffff) {
342447dc10d7SGordon Ross 				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
342547dc10d7SGordon Ross 					DRM_DEBUG_DRIVER("pipe %c underrun\n",
342647dc10d7SGordon Ross 							 pipe_name(pipe));
342747dc10d7SGordon Ross 				I915_WRITE(reg, pipe_stats[pipe]);
342847dc10d7SGordon Ross 				irq_received = 1;
342947dc10d7SGordon Ross 			}
343047dc10d7SGordon Ross 		}
343147dc10d7SGordon Ross 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
343247dc10d7SGordon Ross 
343347dc10d7SGordon Ross 		if (!irq_received)
343447dc10d7SGordon Ross 			break;
343547dc10d7SGordon Ross 
343647dc10d7SGordon Ross 		ret = IRQ_HANDLED;
343747dc10d7SGordon Ross 
343847dc10d7SGordon Ross 		/* Consume port.  Then clear IIR or we'll miss events */
343947dc10d7SGordon Ross 		if (iir & I915_DISPLAY_PORT_INTERRUPT) {
344047dc10d7SGordon Ross 			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
344147dc10d7SGordon Ross 			u32 hotplug_trigger = hotplug_status & (IS_G4X(dev) ?
344247dc10d7SGordon Ross 								  HOTPLUG_INT_STATUS_G4X :
344347dc10d7SGordon Ross 								  HOTPLUG_INT_STATUS_I915);
344447dc10d7SGordon Ross 
344547dc10d7SGordon Ross 			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
344647dc10d7SGordon Ross 				  hotplug_status);
344747dc10d7SGordon Ross 
344847dc10d7SGordon Ross 			intel_hpd_irq_handler(dev, hotplug_trigger,
344947dc10d7SGordon Ross 					      IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915);
345047dc10d7SGordon Ross 
345147dc10d7SGordon Ross 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
345247dc10d7SGordon Ross 			I915_READ(PORT_HOTPLUG_STAT);
345347dc10d7SGordon Ross 		}
345447dc10d7SGordon Ross 
345547dc10d7SGordon Ross 		I915_WRITE(IIR, iir & ~flip_mask);
345647dc10d7SGordon Ross 		new_iir = I915_READ(IIR); /* Flush posted writes */
345747dc10d7SGordon Ross 
345847dc10d7SGordon Ross 		if (iir & I915_USER_INTERRUPT)
345947dc10d7SGordon Ross 			notify_ring(dev, &dev_priv->ring[RCS]);
346047dc10d7SGordon Ross 		if (iir & I915_BSD_USER_INTERRUPT)
346147dc10d7SGordon Ross 			notify_ring(dev, &dev_priv->ring[VCS]);
346247dc10d7SGordon Ross 
346347dc10d7SGordon Ross 		for_each_pipe(pipe) {
346447dc10d7SGordon Ross 			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
346547dc10d7SGordon Ross 			    i915_handle_vblank(dev, pipe, pipe, iir))
346647dc10d7SGordon Ross 				flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
346747dc10d7SGordon Ross 
346847dc10d7SGordon Ross 		}
346947dc10d7SGordon Ross 
347047dc10d7SGordon Ross 
347147dc10d7SGordon Ross 
347247dc10d7SGordon Ross 		/* With MSI, interrupts are only generated when iir
347347dc10d7SGordon Ross 		 * transitions from zero to nonzero.  If another bit got
347447dc10d7SGordon Ross 		 * set while we were handling the existing iir bits, then
347547dc10d7SGordon Ross 		 * we would never get another interrupt.
347647dc10d7SGordon Ross 		 *
347747dc10d7SGordon Ross 		 * This is fine on non-MSI as well, as if we hit this path
347847dc10d7SGordon Ross 		 * we avoid exiting the interrupt handler only to generate
347947dc10d7SGordon Ross 		 * another one.
348047dc10d7SGordon Ross 		 *
348147dc10d7SGordon Ross 		 * Note that for MSI this could cause a stray interrupt report
348247dc10d7SGordon Ross 		 * if an interrupt landed in the time between writing IIR and
348347dc10d7SGordon Ross 		 * the posting read.  This should be rare enough to never
348447dc10d7SGordon Ross 		 * trigger the 99% of 100,000 interrupts test for disabling
348547dc10d7SGordon Ross 		 * stray interrupts.
348647dc10d7SGordon Ross 		 */
348747dc10d7SGordon Ross 		iir = new_iir;
348847dc10d7SGordon Ross 	}
348947dc10d7SGordon Ross 
349047dc10d7SGordon Ross 	i915_update_dri1_breadcrumb(dev);
349147dc10d7SGordon Ross 
349247dc10d7SGordon Ross 	return ret;
349347dc10d7SGordon Ross }
349447dc10d7SGordon Ross 
i965_irq_uninstall(struct drm_device * dev)349547dc10d7SGordon Ross static void i965_irq_uninstall(struct drm_device * dev)
349647dc10d7SGordon Ross {
349747dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
349847dc10d7SGordon Ross 	int pipe;
349947dc10d7SGordon Ross 
350047dc10d7SGordon Ross 	if (!dev_priv)
350147dc10d7SGordon Ross 		return;
350247dc10d7SGordon Ross 
350347dc10d7SGordon Ross 	del_timer_sync(&dev_priv->hotplug_reenable_timer);
350447dc10d7SGordon Ross 
350547dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_EN, 0);
350647dc10d7SGordon Ross 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
350747dc10d7SGordon Ross 
350847dc10d7SGordon Ross 	I915_WRITE(HWSTAM, 0xffffffff);
350947dc10d7SGordon Ross 	for_each_pipe(pipe)
351047dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe), 0);
351147dc10d7SGordon Ross 	I915_WRITE(IMR, 0xffffffff);
351247dc10d7SGordon Ross 	I915_WRITE(IER, 0x0);
351347dc10d7SGordon Ross 
351447dc10d7SGordon Ross 	for_each_pipe(pipe)
351547dc10d7SGordon Ross 		I915_WRITE(PIPESTAT(pipe),
351647dc10d7SGordon Ross 			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
351747dc10d7SGordon Ross 	I915_WRITE(IIR, I915_READ(IIR));
351847dc10d7SGordon Ross }
351947dc10d7SGordon Ross 
i915_reenable_hotplug_timer_func(void * data)352047dc10d7SGordon Ross static void i915_reenable_hotplug_timer_func(void* data)
352147dc10d7SGordon Ross {
352247dc10d7SGordon Ross 	drm_i915_private_t *dev_priv = (drm_i915_private_t *)data;
352347dc10d7SGordon Ross 	struct drm_device *dev = dev_priv->dev;
352447dc10d7SGordon Ross 	struct drm_mode_config *mode_config = &dev->mode_config;
352547dc10d7SGordon Ross 	unsigned long irqflags;
352647dc10d7SGordon Ross 	int i;
352747dc10d7SGordon Ross 
352847dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
352947dc10d7SGordon Ross 	for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
353047dc10d7SGordon Ross 		struct drm_connector *connector;
353147dc10d7SGordon Ross 
353247dc10d7SGordon Ross 		if (dev_priv->hpd_stats[i].hpd_mark != HPD_DISABLED)
353347dc10d7SGordon Ross 			continue;
353447dc10d7SGordon Ross 
353547dc10d7SGordon Ross 		dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
353647dc10d7SGordon Ross 
353747dc10d7SGordon Ross 		list_for_each_entry(connector, struct drm_connector, &mode_config->connector_list, head) {
353847dc10d7SGordon Ross 			struct intel_connector *intel_connector = to_intel_connector(connector);
353947dc10d7SGordon Ross 
354047dc10d7SGordon Ross 			if (intel_connector->encoder->hpd_pin == i) {
354147dc10d7SGordon Ross 				if (connector->polled != intel_connector->polled)
354247dc10d7SGordon Ross 					DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
354347dc10d7SGordon Ross 							 drm_get_connector_name(connector));
354447dc10d7SGordon Ross 				connector->polled = intel_connector->polled;
354547dc10d7SGordon Ross 				if (!connector->polled)
354647dc10d7SGordon Ross 					connector->polled = DRM_CONNECTOR_POLL_HPD;
354747dc10d7SGordon Ross 			}
354847dc10d7SGordon Ross 		}
354947dc10d7SGordon Ross 	}
355047dc10d7SGordon Ross 	if (dev_priv->display.hpd_irq_setup)
355147dc10d7SGordon Ross 		dev_priv->display.hpd_irq_setup(dev);
355247dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
355347dc10d7SGordon Ross }
355447dc10d7SGordon Ross 
intel_irq_init(struct drm_device * dev)355547dc10d7SGordon Ross void intel_irq_init(struct drm_device *dev)
355647dc10d7SGordon Ross {
355747dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
355847dc10d7SGordon Ross 
355947dc10d7SGordon Ross 	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
356047dc10d7SGordon Ross 	INIT_WORK(&dev_priv->gpu_error.work, i915_error_work_func);
356147dc10d7SGordon Ross 	INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
356247dc10d7SGordon Ross 	INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
356347dc10d7SGordon Ross 
356447dc10d7SGordon Ross 	init_timer(&dev_priv->gpu_error.hangcheck_timer);
356547dc10d7SGordon Ross 	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
356647dc10d7SGordon Ross 		    i915_hangcheck_elapsed,
356747dc10d7SGordon Ross 		    (void *) dev);
356847dc10d7SGordon Ross 	init_timer(&dev_priv->hotplug_reenable_timer);
356947dc10d7SGordon Ross 	setup_timer(&dev_priv->hotplug_reenable_timer, i915_reenable_hotplug_timer_func,
357047dc10d7SGordon Ross 		    (void *) dev_priv);
357147dc10d7SGordon Ross 
357247dc10d7SGordon Ross 
357347dc10d7SGordon Ross 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
357447dc10d7SGordon Ross 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
357547dc10d7SGordon Ross 	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
357647dc10d7SGordon Ross 		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
357747dc10d7SGordon Ross 		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
357847dc10d7SGordon Ross 	}
357947dc10d7SGordon Ross 
358047dc10d7SGordon Ross 	if (drm_core_check_feature(dev, DRIVER_MODESET))
358147dc10d7SGordon Ross 		dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
358247dc10d7SGordon Ross 	else
358347dc10d7SGordon Ross 		dev->driver->get_vblank_timestamp = NULL;
358447dc10d7SGordon Ross 	dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
358547dc10d7SGordon Ross 
358647dc10d7SGordon Ross 	if (IS_VALLEYVIEW(dev)) {
358747dc10d7SGordon Ross 		dev->driver->irq_handler = valleyview_irq_handler;
358847dc10d7SGordon Ross 		dev->driver->irq_preinstall = valleyview_irq_preinstall;
358947dc10d7SGordon Ross 		dev->driver->irq_postinstall = valleyview_irq_postinstall;
359047dc10d7SGordon Ross 		dev->driver->irq_uninstall = valleyview_irq_uninstall;
359147dc10d7SGordon Ross 		dev->driver->enable_vblank = valleyview_enable_vblank;
359247dc10d7SGordon Ross 		dev->driver->disable_vblank = valleyview_disable_vblank;
359347dc10d7SGordon Ross 		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
359447dc10d7SGordon Ross 	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
359547dc10d7SGordon Ross 		/* Share pre & uninstall handlers with ILK/SNB */
359647dc10d7SGordon Ross 		dev->driver->irq_handler = ivybridge_irq_handler;
359747dc10d7SGordon Ross 		dev->driver->irq_preinstall = ivybridge_irq_preinstall;
359847dc10d7SGordon Ross 		dev->driver->irq_postinstall = ivybridge_irq_postinstall;
359947dc10d7SGordon Ross 		dev->driver->irq_uninstall = ironlake_irq_uninstall;
360047dc10d7SGordon Ross 		dev->driver->enable_vblank = ivybridge_enable_vblank;
360147dc10d7SGordon Ross 		dev->driver->disable_vblank = ivybridge_disable_vblank;
360247dc10d7SGordon Ross 		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
360347dc10d7SGordon Ross 	} else if (HAS_PCH_SPLIT(dev)) {
360447dc10d7SGordon Ross 		dev->driver->irq_handler = ironlake_irq_handler;
360547dc10d7SGordon Ross 		dev->driver->irq_preinstall = ironlake_irq_preinstall;
360647dc10d7SGordon Ross 		dev->driver->irq_postinstall = ironlake_irq_postinstall;
360747dc10d7SGordon Ross 		dev->driver->irq_uninstall = ironlake_irq_uninstall;
360847dc10d7SGordon Ross 		dev->driver->enable_vblank = ironlake_enable_vblank;
360947dc10d7SGordon Ross 		dev->driver->disable_vblank = ironlake_disable_vblank;
361047dc10d7SGordon Ross 		dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
361147dc10d7SGordon Ross 	} else {
361247dc10d7SGordon Ross 		if (INTEL_INFO(dev)->gen == 2) {
361347dc10d7SGordon Ross 			dev->driver->irq_preinstall = i8xx_irq_preinstall;
361447dc10d7SGordon Ross 			dev->driver->irq_postinstall = i8xx_irq_postinstall;
361547dc10d7SGordon Ross 			dev->driver->irq_handler = i8xx_irq_handler;
361647dc10d7SGordon Ross 			dev->driver->irq_uninstall = i8xx_irq_uninstall;
361747dc10d7SGordon Ross 		} else if (INTEL_INFO(dev)->gen == 3) {
361847dc10d7SGordon Ross 			dev->driver->irq_preinstall = i915_irq_preinstall;
361947dc10d7SGordon Ross 			dev->driver->irq_postinstall = i915_irq_postinstall;
362047dc10d7SGordon Ross 			dev->driver->irq_uninstall = i915_irq_uninstall;
362147dc10d7SGordon Ross 			dev->driver->irq_handler = i915_irq_handler;
362247dc10d7SGordon Ross 			dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
362347dc10d7SGordon Ross 		} else {
362447dc10d7SGordon Ross 			dev->driver->irq_preinstall = i965_irq_preinstall;
362547dc10d7SGordon Ross 			dev->driver->irq_postinstall = i965_irq_postinstall;
362647dc10d7SGordon Ross 			dev->driver->irq_uninstall = i965_irq_uninstall;
362747dc10d7SGordon Ross 			dev->driver->irq_handler = i965_irq_handler;
362847dc10d7SGordon Ross 			dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
362947dc10d7SGordon Ross 		}
363047dc10d7SGordon Ross 		dev->driver->enable_vblank = i915_enable_vblank;
363147dc10d7SGordon Ross 		dev->driver->disable_vblank = i915_disable_vblank;
363247dc10d7SGordon Ross 	}
363347dc10d7SGordon Ross }
363447dc10d7SGordon Ross 
intel_hpd_init(struct drm_device * dev)363547dc10d7SGordon Ross void intel_hpd_init(struct drm_device *dev)
363647dc10d7SGordon Ross {
363747dc10d7SGordon Ross 	struct drm_i915_private *dev_priv = dev->dev_private;
363847dc10d7SGordon Ross 	struct drm_mode_config *mode_config = &dev->mode_config;
363947dc10d7SGordon Ross 	struct drm_connector *connector;
364047dc10d7SGordon Ross 	unsigned long irqflags;
364147dc10d7SGordon Ross 	int i;
364247dc10d7SGordon Ross 
364347dc10d7SGordon Ross 	for (i = 1; i < HPD_NUM_PINS; i++) {
364447dc10d7SGordon Ross 		dev_priv->hpd_stats[i].hpd_cnt = 0;
364547dc10d7SGordon Ross 		dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
364647dc10d7SGordon Ross 	}
364747dc10d7SGordon Ross 	list_for_each_entry(connector, struct drm_connector, &mode_config->connector_list, head) {
364847dc10d7SGordon Ross 		struct intel_connector *intel_connector = to_intel_connector(connector);
364947dc10d7SGordon Ross 		connector->polled = intel_connector->polled;
365047dc10d7SGordon Ross 		if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
365147dc10d7SGordon Ross 			connector->polled = DRM_CONNECTOR_POLL_HPD;
365247dc10d7SGordon Ross 	}
365347dc10d7SGordon Ross 
365447dc10d7SGordon Ross 	/* Interrupt setup is already guaranteed to be single-threaded, this is
365547dc10d7SGordon Ross 	 * just to make the assert_spin_locked checks happy. */
365647dc10d7SGordon Ross 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
365747dc10d7SGordon Ross 	if (dev_priv->display.hpd_irq_setup)
365847dc10d7SGordon Ross 		dev_priv->display.hpd_irq_setup(dev);
365947dc10d7SGordon Ross 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
366047dc10d7SGordon Ross }
3661