diff options
Diffstat (limited to 'shared-core/i915_irq.c')
| -rw-r--r-- | shared-core/i915_irq.c | 366 | 
1 files changed, 163 insertions, 203 deletions
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 2d355688..28fa35fd 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -35,6 +35,33 @@  #define MAX_NOPID ((u32)~0) +/* + * These are the interrupts used by the driver + */ +#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ +				    I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ +				    I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) + +static inline void +i915_enable_irq(struct drm_i915_private *dev_priv, uint32_t mask) +{ +	if ((dev_priv->irq_mask_reg & mask) != 0) { +		dev_priv->irq_mask_reg &= ~mask; +		I915_WRITE(IMR, dev_priv->irq_mask_reg); +		(void) I915_READ(IMR); +	} +} + +static inline void +i915_disable_irq(struct drm_i915_private *dev_priv, uint32_t mask) +{ +	if ((dev_priv->irq_mask_reg & mask) != mask) { +		dev_priv->irq_mask_reg |= mask; +		I915_WRITE(IMR, dev_priv->irq_mask_reg); +		(void) I915_READ(IMR); +	} +} +  /**   * i915_get_pipe - return the the pipe associated with a given plane   * @dev: DRM device @@ -165,11 +192,11 @@ static void i915_vblank_tasklet(struct drm_device *dev)  	u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);  	RING_LOCALS; -	if (sarea_priv->front_tiled) { +	if (IS_I965G(dev) && sarea_priv->front_tiled) {  		cmd |= XY_SRC_COPY_BLT_DST_TILED;  		dst_pitch >>= 2;  	} -	if (sarea_priv->back_tiled) { +	if (IS_I965G(dev) && sarea_priv->back_tiled) {  		cmd |= XY_SRC_COPY_BLT_SRC_TILED;  		src_pitch >>= 2;  	} @@ -367,28 +394,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)  		drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);  	}  } -#if 0 -static int i915_in_vblank(struct drm_device *dev, int pipe) -{ -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -	unsigned long pipedsl, vblank, vtotal; -	unsigned long vbl_start, vbl_end, cur_line; - -	pipedsl = pipe ? PIPEBDSL : PIPEADSL; -	vblank = pipe ? VBLANK_B : VBLANK_A; -	vtotal = pipe ? VTOTAL_B : VTOTAL_A; - -	vbl_start = I915_READ(vblank) & VBLANK_START_MASK; -	vbl_end = (I915_READ(vblank) >> VBLANK_END_SHIFT) & VBLANK_END_MASK; - -	cur_line = I915_READ(pipedsl); -	if (cur_line >= vbl_start) -		return 1; - -	return 0; -} -#endif  u32 i915_get_vblank_counter(struct drm_device *dev, int plane)  {  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; @@ -422,30 +428,17 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)  	count = (high1 << 8) | low; -	/* -	 * If we're in the middle of the vblank period, the -	 * above regs won't have been updated yet, so return -	 * an incremented count to stay accurate -	 */ -#if 0 -	if (i915_in_vblank(dev, pipe)) -		count++; -#endif -	/* count may be reset by other driver(e.g. 2D driver),  -	   we have no way to know if it is wrapped or resetted  -	   when count is zero. do a rough guess. -	*/ -	if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2) -		dev->last_vblank[pipe] = 0;  -	  	return count;  }  static struct drm_device *hotplug_dev; -/* - * This code is called in a more safe envirmoent to handle the hotplugs. - * Add code here for hotplug love to userspace. +/** + * Handler for user interrupts in process context (able to sleep, do VFS + * operations, etc. + * + * If another IRQ comes in while we're in this handler, it will still get put + * on the queue again to be rerun when we finish.   */  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)  static void i915_hotplug_work_func(void *work) @@ -485,7 +478,6 @@ static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat)  	if (stat & SDVOC_HOTPLUG_INT_STATUS) {  		DRM_DEBUG("sDVOC event\n");  	} -  	queue_work(dev_priv->wq, &hotplug);  	return 0; @@ -497,30 +489,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  	struct drm_i915_master_private *master_priv;  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	u32 iir; -	u32 pipea_stats = 0, pipeb_stats, tvdac; +	u32 pipea_stats = 0, pipeb_stats = 0, tvdac;  	int hotplug = 0;  	int vblank = 0; -	/* On i8xx/i915 hw the IIR and IER are 16bit on i9xx its 32bit */ -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -		iir = I915_READ(IIR); -	else -		iir = I915_READ16(IIR); - -	iir &= (dev_priv->irq_enable_reg | I915_USER_INTERRUPT); - -#if 0 -	DRM_DEBUG("flag=%08x\n", iir); -#endif +	if (dev->pdev->msi_enabled) +		I915_WRITE(IMR, ~0); +	iir = I915_READ(IIR); +	atomic_inc(&dev_priv->irq_received);  	if (iir == 0) { -#if 0 -		DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n", -			   iir, -			   I915_READ(IMR), -			   I915_READ(IER), -			   I915_READ(PIPEASTAT), -			   I915_READ(PIPEBSTAT)); -#endif +		if (dev->pdev->msi_enabled) { +			I915_WRITE(IMR, dev_priv->irq_mask_reg); +			(void) I915_READ(IMR); +		}  		return IRQ_NONE;  	} @@ -530,46 +511,29 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  	 */  	if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {  		pipea_stats = I915_READ(PIPEASTAT); -		if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| -				   PIPE_VBLANK_INTERRUPT_STATUS)) -		{ -			vblank++; -			drm_handle_vblank(dev, i915_get_plane(dev, 0)); -		} - -		/* This is a global event, and not a pipe A event */ -		if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS) -			hotplug = 1; - -		if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) { -			hotplug = 1; -			/* Toggle hotplug detection to clear hotplug status */ -			tvdac = I915_READ(TV_DAC); -			I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN); -			I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN); -		} -  		I915_WRITE(PIPEASTAT, pipea_stats);  	}  	if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {  		pipeb_stats = I915_READ(PIPEBSTAT); -		if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| -				   PIPE_VBLANK_INTERRUPT_STATUS)) -		{ -			vblank++; -			drm_handle_vblank(dev, i915_get_plane(dev, 1)); -		}  		I915_WRITE(PIPEBSTAT, pipeb_stats);  	} -	/* Clear the generated interrupt */ -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { -		I915_WRITE(IIR, iir); -		(void) I915_READ(IIR); -	} else { -		I915_WRITE16(IIR, iir); -		(void) I915_READ16(IIR); +	I915_WRITE(IIR, iir); +	if (dev->pdev->msi_enabled) +		I915_WRITE(IMR, dev_priv->irq_mask_reg); +	(void) I915_READ(IIR); /* Flush posted writes */ + +	/* This is a global event, and not a pipe A event */ +	if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS) +		hotplug = 1; + +	if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) { +		hotplug = 1; +		/* Toggle hotplug detection to clear hotplug status */ +		tvdac = I915_READ(TV_DAC); +		I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN); +		I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN);  	}  	if (dev->primary->master) { @@ -577,13 +541,41 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  		master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);  	} +#ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) +	if ((iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) && +	    (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE)) +		opregion_asle_intr(dev); +	if (iir & I915_ASLE_INTERRUPT) +		opregion_asle_intr(dev); +#endif +#endif +  	if (iir & I915_USER_INTERRUPT) { +		dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);  		DRM_WAKEUP(&dev_priv->irq_queue);  #ifdef I915_HAVE_FENCE  		i915_fence_handler(dev);  #endif  	} +	if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| +			   PIPE_VBLANK_INTERRUPT_STATUS)) { +		vblank++; +		drm_handle_vblank(dev, i915_get_plane(dev, 0)); +	} + +	/* The vblank interrupt gets enabled even if we didn't ask for +	   it, so make sure it's shut down again */ +	if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)) +		pipeb_stats &= ~(I915_VBLANK_INTERRUPT_ENABLE); + +	if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| +			   PIPE_VBLANK_INTERRUPT_STATUS)) { +		vblank++; +		drm_handle_vblank(dev, i915_get_plane(dev, 1)); +	} +  	if (vblank) {  		if (dev_priv->swaps_pending > 0)  			drm_locked_tasklet(dev, i915_vblank_tasklet); @@ -635,15 +627,9 @@ void i915_user_irq_on(struct drm_device *dev)  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	DRM_SPINLOCK(&dev_priv->user_irq_lock); -	if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ -		dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; -		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -			I915_WRITE(IER, dev_priv->irq_enable_reg); -		else -			I915_WRITE16(IER, dev_priv->irq_enable_reg); -	} +	if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)) +		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);  	DRM_SPINUNLOCK(&dev_priv->user_irq_lock); -  }  void i915_user_irq_off(struct drm_device *dev) @@ -651,28 +637,38 @@ void i915_user_irq_off(struct drm_device *dev)  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	DRM_SPINLOCK(&dev_priv->user_irq_lock); -	if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { -		//		dev_priv->irq_enable_reg &= ~I915_USER_INTERRUPT; -		//		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -		//			I915_WRITE(IER, dev_priv->irq_enable_reg); -		//		else -		//			I915_WRITE16(IER, dev_priv->irq_enable_reg); -	} +	BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); +	if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) +		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);  	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);  } -static int i915_wait_irq(struct drm_device * dev, int irq_nr) +int i915_wait_irq(struct drm_device * dev, int irq_nr)  {  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	struct drm_i915_master_private *master_priv;  	int ret = 0; +	if (!dev_priv) { +		DRM_ERROR("called with no initialization\n"); +		return -EINVAL; +	} +  	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,  		  READ_BREADCRUMB(dev_priv)); -	if (READ_BREADCRUMB(dev_priv) >= irq_nr) +	master_priv = dev->primary->master->driver_priv; + +	if (!master_priv) { +		DRM_ERROR("no master priv?\n"); +		return -EINVAL; +	} + +	if (READ_BREADCRUMB(dev_priv) >= irq_nr) { +		master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);  		return 0; +	}  	i915_user_irq_on(dev);  	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, @@ -684,10 +680,8 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)  			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);  	} -	if (dev->primary->master) { -		master_priv = dev->primary->master->driver_priv; +	if (READ_BREADCRUMB(dev_priv) >= irq_nr)  		master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); -	}  	return ret;  } @@ -739,16 +733,17 @@ int i915_enable_vblank(struct drm_device *dev, int plane)  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	int pipe = i915_get_pipe(dev, plane);  	u32	pipestat_reg = 0; +	u32	mask_reg = 0;  	u32	pipestat;  	switch (pipe) {  	case 0:  		pipestat_reg = PIPEASTAT; -		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; +		mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;  		break;  	case 1:  		pipestat_reg = PIPEBSTAT; -		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; +		mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;  		break;  	default:  		DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", @@ -774,12 +769,9 @@ int i915_enable_vblank(struct drm_device *dev, int plane)  			     PIPE_VBLANK_INTERRUPT_STATUS);  		I915_WRITE(pipestat_reg, pipestat);  	} - -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -		I915_WRITE(IER, dev_priv->irq_enable_reg); -	else -		I915_WRITE16(IER, dev_priv->irq_enable_reg); - +	DRM_SPINLOCK(&dev_priv->user_irq_lock); +	i915_enable_irq(dev_priv, mask_reg); +	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);  	return 0;  } @@ -789,16 +781,17 @@ void i915_disable_vblank(struct drm_device *dev, int plane)  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	int pipe = i915_get_pipe(dev, plane);  	u32	pipestat_reg = 0; +	u32	mask_reg = 0;  	u32	pipestat;  	switch (pipe) {  	case 0:  		pipestat_reg = PIPEASTAT; -		dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; +		mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;  		break;  	case 1:  		pipestat_reg = PIPEBSTAT; -		dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; +		mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;  		break;  	default:  		DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", @@ -806,13 +799,11 @@ void i915_disable_vblank(struct drm_device *dev, int plane)  		break;  	} -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -		I915_WRITE(IER, dev_priv->irq_enable_reg); -	else -		I915_WRITE16(IER, dev_priv->irq_enable_reg); +	DRM_SPINLOCK(&dev_priv->user_irq_lock); +	i915_disable_irq(dev_priv, mask_reg); +	DRM_SPINUNLOCK(&dev_priv->user_irq_lock); -	if (pipestat_reg) -	{ +	if (pipestat_reg) {  		pipestat = I915_READ (pipestat_reg);  		pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |  			      PIPE_VBLANK_INTERRUPT_ENABLE); @@ -822,6 +813,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane)  		pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |  			     PIPE_VBLANK_INTERRUPT_STATUS);  		I915_WRITE(pipestat_reg, pipestat); +		(void) I915_READ(pipestat_reg);  	}  } @@ -829,15 +821,15 @@ void i915_enable_interrupt (struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;  	struct drm_connector *o; - -	dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; +	 +	dev_priv->irq_mask_reg &= ~0;  	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {  		if (dev->mode_config.num_connector) -			dev_priv->irq_enable_reg |= I915_DISPLAY_PORT_INTERRUPT; +			dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;  	} else {  		if (dev->mode_config.num_connector) -			dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; +			dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;  		/* Enable global interrupts for hotplug - not a pipeA event */  		I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) | @@ -847,7 +839,8 @@ void i915_enable_interrupt (struct drm_device *dev)  			   PIPE_HOTPLUG_INTERRUPT_STATUS);  	} -	if (dev_priv->irq_enable_reg & (I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)) { +	if (!(dev_priv->irq_mask_reg & I915_DISPLAY_PORT_INTERRUPT) || +	    !(dev_priv->irq_mask_reg & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)) {  		u32 temp = 0;  		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { @@ -891,11 +884,11 @@ void i915_enable_interrupt (struct drm_device *dev)  		}  	} -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -		I915_WRITE(IER, dev_priv->irq_enable_reg); -	else -		I915_WRITE16(IER, dev_priv->irq_enable_reg); - +#ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) +	opregion_enable_asle(dev); +#endif +#endif  	dev_priv->irq_enabled = 1;  } @@ -905,20 +898,12 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,  			 struct drm_file *file_priv)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	struct drm_i915_vblank_pipe *pipe = data;  	if (!dev_priv) {  		DRM_ERROR("called with no initialization\n");  		return -EINVAL;  	} -	if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { -		DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe); -		return -EINVAL; -	} - -	dev_priv->vblank_pipe = pipe->pipe; -  	return 0;  } @@ -927,17 +912,15 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct drm_i915_vblank_pipe *pipe = data; -	u16 flag; +	u32 flag = 0;  	if (!dev_priv) {  		DRM_ERROR("called with no initialization\n");  		return -EINVAL;  	} -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) -		flag = I915_READ(IER); -	else -		flag = I915_READ16(IER); +	if (dev_priv->irq_enabled) +	    flag = ~dev_priv->irq_mask_reg;  	pipe->pipe = 0;  	if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) @@ -1010,7 +993,13 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  	DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); -	drm_update_vblank_count(dev, pipe); +	/* +	 * We take the ref here and put it when the swap actually completes +	 * in the tasklet. +	 */ +	ret = drm_vblank_get(dev, pipe); +	if (ret) +		return ret;  	curseq = drm_vblank_count(dev, pipe);  	if (seqtype == _DRM_VBLANK_RELATIVE) @@ -1021,6 +1010,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  			swap->sequence = curseq + 1;  		} else {  			DRM_DEBUG("Missed target sequence\n"); +			drm_vblank_put(dev, pipe);  			return -EINVAL;  		}  	} @@ -1042,6 +1032,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  				    irqflags);  				DRM_DEBUG("Invalid drawable ID %d\n",  					  swap->drawable); +				drm_vblank_put(dev, pipe);  				return -EINVAL;  			} @@ -1049,6 +1040,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  			DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); +			drm_vblank_put(dev, pipe);  			return 0;  		}  	} @@ -1072,6 +1064,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  	if (dev_priv->swaps_pending >= 100) {  		DRM_DEBUG("Too many swaps queued\n"); +		drm_vblank_put(dev, pipe);  		return -EBUSY;  	} @@ -1079,17 +1072,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  	if (!vbl_swap) {  		DRM_ERROR("Failed to allocate memory to queue swap\n"); +		drm_vblank_put(dev, pipe);  		return -ENOMEM;  	}  	DRM_DEBUG("\n"); -	ret = drm_vblank_get(dev, pipe); -	if (ret) { -		drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); -		return ret; -	} -  	vbl_swap->drw_id = swap->drawable;  	vbl_swap->plane = plane;  	vbl_swap->sequence = swap->sequence; @@ -1113,33 +1101,16 @@ int i915_vblank_swap(struct drm_device *dev, void *data,  */  void i915_driver_irq_preinstall(struct drm_device * dev)  { -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; -	u32 tmp; - -	tmp = I915_READ(PIPEASTAT); -	I915_WRITE(PIPEASTAT, tmp); -	tmp = I915_READ(PIPEBSTAT); -	I915_WRITE(PIPEBSTAT, tmp); - +	struct drm_i915_private *dev_priv = dev->dev_private;  	I915_WRITE16(HWSTAM, 0xeffe); -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { -		I915_WRITE(IMR, 0x0); -		I915_WRITE(IER, 0x0); -		tmp = I915_READ(IIR); -		I915_WRITE(IIR, tmp); -	} else { -		I915_WRITE16(IMR, 0x0); -		I915_WRITE16(IER, 0x0); -		tmp = I915_READ16(IIR); -		I915_WRITE16(IIR, tmp); -	} - +	I915_WRITE16(IMR, 0x0); +	I915_WRITE16(IER, 0x0);  }  int i915_driver_irq_postinstall(struct drm_device * dev)  { -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; +	struct drm_i915_private *dev_priv = dev->dev_private;  	int ret, num_pipes = 2;  	DRM_SPININIT(&dev_priv->swaps_lock, "swap"); @@ -1148,16 +1119,13 @@ int i915_driver_irq_postinstall(struct drm_device * dev)  	DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");  	dev_priv->user_irq_refcount = 0; -	dev_priv->irq_enable_reg = 0; +	dev_priv->irq_mask_reg = ~0;  	ret = drm_vblank_init(dev, num_pipes);  	if (ret)  		return ret; -	ret = drm_hotplug_init(dev); -	if (ret) -		return ret; - +	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;  	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */  	i915_enable_interrupt(dev); @@ -1173,31 +1141,23 @@ int i915_driver_irq_postinstall(struct drm_device * dev)  void i915_driver_irq_uninstall(struct drm_device * dev)  { -	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; +	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 temp;  	if (!dev_priv)  		return; +	dev_priv->vblank_pipe = 0; +  	dev_priv->irq_enabled = 0; +	I915_WRITE(HWSTAM, 0xffffffff); +	I915_WRITE(IMR, 0xffffffff); +	I915_WRITE(IER, 0x0);  	temp = I915_READ(PIPEASTAT);  	I915_WRITE(PIPEASTAT, temp);  	temp = I915_READ(PIPEBSTAT);  	I915_WRITE(PIPEBSTAT, temp); -	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { -		I915_WRITE(HWSTAM, 0xffffffff); -		I915_WRITE(IMR, 0xffffffff); -		I915_WRITE(IER, 0x0); - -		temp = I915_READ(IIR); -		I915_WRITE(IIR, temp); -	} else { -		I915_WRITE16(HWSTAM, 0xffff); -		I915_WRITE16(IMR, 0xffff); -		I915_WRITE16(IER, 0x0); - -		temp = I915_READ16(IIR); -		I915_WRITE16(IIR, temp); -	} +	temp = I915_READ(IIR); +	I915_WRITE(IIR, temp);  }  | 
