[prev in list] [next in list] [prev in thread] [next in thread] 

List:       dri-patches
Subject:    drm: Branch 'modesetting-101' - 16 commits
From:       alanh () kemper ! freedesktop ! org (Alan Hourihane)
Date:       2008-03-12 10:19:11
Message-ID: 20080312101911.5B52710096 () kemper ! freedesktop ! org
[Download RAW message or body]

 linux-core/drmP.h          |    4 -
 linux-core/drm_bo.c        |   70 +++++++++++++------
 linux-core/drm_bo_move.c   |    3 
 linux-core/drm_fence.c     |    4 -
 linux-core/drm_memory.c    |   51 ++++++++++++--
 linux-core/drm_proc.c      |   14 +++
 linux-core/drm_ttm.c       |   12 +--
 shared-core/i915_dma.c     |   21 ++---
 shared-core/i915_drv.h     |   51 ++++++++++++--
 shared-core/i915_irq.c     |  163 +++++++++++++++++++++++++++------------------
 shared-core/nouveau_fifo.c |   50 ++++++++-----
 shared-core/nouveau_mem.c  |   28 +++++++
 shared-core/nv04_mc.c      |   13 ---
 shared-core/radeon_state.c |    6 +
 14 files changed, 335 insertions(+), 155 deletions(-)

New commits:
commit b6dc381fabb199e70dc681e44e31452af8536313
Merge: 7f04dd0... 2a618e5...
Author: Alan Hourihane <alanh@tungstengraphics.com>
Date:   Wed Mar 12 10:18:33 2008 +0000

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into \
modesetting-101  
    Conflicts:
    
    	shared-core/i915_dma.c
    	shared-core/i915_drv.h
    	shared-core/i915_irq.c

diff --cc shared-core/i915_drv.h
index fb85593,3bc39e2..64faac9
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@@ -69,9 -69,10 +69,10 @@@
  
  #ifdef I915_HAVE_BUFFER
  #define I915_MAX_VALIDATE_BUFFERS 4096
+ struct drm_i915_validate_buffer;
  #endif
  
 -typedef struct _drm_i915_ring_buffer {
 +struct drm_i915_ring_buffer {
  	int tail_mask;
  	unsigned long Start;
  	unsigned long End;
@@@ -153,7 -142,7 +154,8 @@@ struct drm_i915_private 
  	void *agp_iomap;
  	unsigned int max_validate_buffers;
  	struct mutex cmdbuf_mutex;
 +	size_t stolen_base;
+ 	struct drm_i915_validate_buffer *val_bufs;
  #endif
  
  	DRM_SPINTYPE swaps_lock;
@@@ -573,63 -528,32 +588,91 @@@ extern int i915_wait_ring(struct drm_de
  #define PIPE_PIXEL_MASK         0x00ffffff
  #define PIPE_PIXEL_SHIFT        0
  
 +#define GPIOA			0x5010
 +#define GPIOB			0x5014
 +#define GPIOC			0x5018
 +#define GPIOD			0x501c
 +#define GPIOE			0x5020
 +#define GPIOF			0x5024
 +#define GPIOG			0x5028
 +#define GPIOH			0x502c
 +# define GPIO_CLOCK_DIR_MASK		(1 << 0)
 +# define GPIO_CLOCK_DIR_IN		(0 << 1)
 +# define GPIO_CLOCK_DIR_OUT		(1 << 1)
 +# define GPIO_CLOCK_VAL_MASK		(1 << 2)
 +# define GPIO_CLOCK_VAL_OUT		(1 << 3)
 +# define GPIO_CLOCK_VAL_IN		(1 << 4)
 +# define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5)
 +# define GPIO_DATA_DIR_MASK		(1 << 8)
 +# define GPIO_DATA_DIR_IN		(0 << 9)
 +# define GPIO_DATA_DIR_OUT		(1 << 9)
 +# define GPIO_DATA_VAL_MASK		(1 << 10)
 +# define GPIO_DATA_VAL_OUT		(1 << 11)
 +# define GPIO_DATA_VAL_IN		(1 << 12)
 +# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
 +
 +/* p317, 319
 + */
 +#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
 +#define VCLK2_VCO_N        0x600a
 +#define VCLK2_VCO_DIV_SEL  0x6012
 +
 +#define VCLK_DIVISOR_VGA0   0x6000
 +#define VCLK_DIVISOR_VGA1   0x6004
 +#define VCLK_POST_DIV	    0x6010
 +/** Selects a post divisor of 4 instead of 2. */
 +# define VGA1_PD_P2_DIV_4	(1 << 15)
 +/** Overrides the p2 post divisor field */
 +# define VGA1_PD_P1_DIV_2	(1 << 13)
 +# define VGA1_PD_P1_SHIFT	8
 +/** P1 value is 2 greater than this field */
 +# define VGA1_PD_P1_MASK	(0x1f << 8)
 +/** Selects a post divisor of 4 instead of 2. */
 +# define VGA0_PD_P2_DIV_4	(1 << 7)
 +/** Overrides the p2 post divisor field */
 +# define VGA0_PD_P1_DIV_2	(1 << 5)
 +# define VGA0_PD_P1_SHIFT	0
 +/** P1 value is 2 greater than this field */
 +# define VGA0_PD_P1_MASK	(0x1f << 0)
 +
 +#define POST_DIV_SELECT        0x70
 +#define POST_DIV_1             0x00
 +#define POST_DIV_2             0x10
 +#define POST_DIV_4             0x20
 +#define POST_DIV_8             0x30
 +#define POST_DIV_16            0x40
 +#define POST_DIV_32            0x50
 +#define VCO_LOOP_DIV_BY_4M     0x00
 +#define VCO_LOOP_DIV_BY_16M    0x04
 +
+ #define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
+ #define I915_CRC_ERROR_ENABLE			(1UL<<29)
+ #define I915_CRC_DONE_ENABLE			(1UL<<28)
+ #define I915_GMBUS_EVENT_ENABLE			(1UL<<27)
++#define I915_HOTPLUG_INTERRUPT_ENABLE		(1UL<<26)
+ #define I915_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
+ #define I915_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
+ #define I915_DPST_EVENT_ENABLE			(1UL<<23)
+ #define I915_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
+ #define I915_ODD_FIELD_INTERRUPT_ENABLE		(1UL<<21)
+ #define I915_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+ #define I915_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18)	/* 965 or later */
+ #define I915_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
+ #define I915_OVERLAY_UPDATED_ENABLE		(1UL<<16)
+ #define I915_CRC_ERROR_INTERRUPT_STATUS		(1UL<<13)
+ #define I915_CRC_DONE_INTERRUPT_STATUS		(1UL<<12)
+ #define I915_GMBUS_INTERRUPT_STATUS		(1UL<<11)
++#define I915_HOTPLUG_INTERRUPT_STATUS		(1UL<<10)
+ #define I915_VSYNC_INTERRUPT_STATUS		(1UL<<9)
+ #define I915_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
+ #define I915_DPST_EVENT_STATUS			(1UL<<7)
+ #define I915_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+ #define I915_ODD_FIELD_INTERRUPT_STATUS		(1UL<<5)
+ #define I915_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+ #define I915_START_VBLANK_INTERRUPT_STATUS	(1UL<<2)	/* 965 or later */
+ #define I915_VBLANK_INTERRUPT_STATUS		(1UL<<1)
+ #define I915_OVERLAY_UPDATED_STATUS		(1UL<<0)
+ 
  #define SRX_INDEX		0x3c4
  #define SRX_DATA		0x3c5
  #define SR01			1
diff --cc shared-core/i915_irq.c
index 558693f,a9b67a9..abd8a7d
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@@ -30,16 -30,7 +30,8 @@@
  #include "drm.h"
  #include "i915_drm.h"
  #include "i915_drv.h"
- 
 +#include "intel_drv.h"
  
- #define USER_INT_FLAG (1<<1)
- #define EVENT_PIPEB_FLAG (1<<4)
- #define VSYNC_PIPEB_FLAG (1<<5)
- #define EVENT_PIPEA_FLAG (1<<6)
- #define VSYNC_PIPEA_FLAG (1<<7)
- #define HOTPLUG_FLAG (1 << 17)
- 
  #define MAX_NOPID ((u32)~0)
  
  /**
@@@ -573,75 -415,57 +565,80 @@@ static int i915_run_hotplug_tasklet(str
  irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
  {
  	struct drm_device *dev = (struct drm_device *) arg;
 -	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +	struct drm_i915_master_private *master_priv;
 +	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- 	u32 temp = 0;
+ 	u32 iir;
  	u32 pipea_stats, pipeb_stats;
 +	int hotplug = 0;
+ 	int vblank = 0;
  
 -	iir = I915_READ(I915REG_INT_IDENTITY_R);
 +	/* On i8xx/i915 hw the IIR and IER are 16bit on i9xx its 32bit */
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
- 		temp = I915_READ(I915REG_INT_IDENTITY_R);
++		iir = I915_READ(I915REG_INT_IDENTITY_R);
 +	else
- 		temp = I915_READ16(I915REG_INT_IDENTITY_R);
++		iir = I915_READ16(I915REG_INT_IDENTITY_R);
 +
- 	temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
++	iir &= (dev_priv->irq_enable_reg | I915_USER_INTERRUPT);
 +
- 	if (temp == 0)
+ #if 0
+ 	DRM_DEBUG("flag=%08x\n", iir);
+ #endif
+ 	if (iir == 0) {
+ 		DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
+ 			   iir,
+ 			   I915_READ(I915REG_INT_MASK_R),
+ 			   I915_READ(I915REG_INT_ENABLE_R),
+ 			   I915_READ(I915REG_PIPEASTAT),
+ 			   I915_READ(I915REG_PIPEBSTAT));
  		return IRQ_NONE;
- 
- 	pipea_stats = I915_READ(I915REG_PIPEASTAT);
- 	pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+ 	}
  
  	/*
  	 * Clear the PIPE(A|B)STAT regs before the IIR otherwise
  	 * we may get extra interrupts.
  	 */
- 	if (temp & VSYNC_PIPEA_FLAG) {
- 		drm_handle_vblank(dev, i915_get_plane(dev, 0));
- 
- 		pipea_stats |= I915_VBLANK_INTERRUPT_ENABLE |
- 			       I915_VBLANK_CLEAR;
- 	}
- 
- 	if (temp & VSYNC_PIPEB_FLAG) {
- 		drm_handle_vblank(dev, i915_get_plane(dev, 1));
- 
- 		pipeb_stats |= I915_VBLANK_INTERRUPT_ENABLE |
- 			       I915_VBLANK_CLEAR;
- 	}
+ 	if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+ 		pipea_stats = I915_READ(I915REG_PIPEASTAT);
+ 		if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+ 				   I915_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 (temp & EVENT_PIPEA_FLAG) {
- 		if (pipea_stats & I915_HOTPLUG_CLEAR)
++		/* This is a global event, and not a pipe A event */
++		if (pipea_stats & I915_HOTPLUG_INTERRUPT_STATUS)
 +			hotplug = 1;
 +
- 		pipea_stats |= I915_HOTPLUG_INTERRUPT_ENABLE |
- 			       I915_HOTPLUG_CLEAR;
- 
+ 		I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
  	}
 +
- 	I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
- 	(void) I915_READ(I915REG_PIPEASTAT);
- 	I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
- 	(void) I915_READ(I915REG_PIPEBSTAT);
+ 	if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+ 		pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+ 		if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+ 				   I915_VBLANK_INTERRUPT_STATUS))
+ 		{
+ 			vblank++;
+ 			drm_handle_vblank(dev, i915_get_plane(dev, 1));
+ 		}
+ 		I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
+ 	}
  
 -	if (dev_priv->sarea_priv)
 -	    dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 +	/* Clear the generated interrupt */
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
- 		I915_WRITE(I915REG_INT_IDENTITY_R, temp);
++		I915_WRITE(I915REG_INT_IDENTITY_R, iir);
 +		(void) I915_READ(I915REG_INT_IDENTITY_R);
 +	} else {
- 		I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
++		I915_WRITE16(I915REG_INT_IDENTITY_R, iir);
 +		(void) I915_READ16(I915REG_INT_IDENTITY_R);
 +	}
  
- 
 -	I915_WRITE(I915REG_INT_IDENTITY_R, iir);
 -	(void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
 +	if (dev->primary->master) {
 +		master_priv = dev->primary->master->driver_priv;
 +		master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 +	}
  
- 	if (temp & USER_INT_FLAG) {
+ 	if (iir & I915_USER_INTERRUPT) {
  		DRM_WAKEUP(&dev_priv->irq_queue);
  #ifdef I915_HAVE_FENCE
  		i915_fence_handler(dev);
@@@ -653,22 -477,6 +650,22 @@@
  			drm_locked_tasklet(dev, i915_vblank_tasklet);
  	}
  
- 	if ((temp & HOTPLUG_FLAG) || hotplug) {
++	if ((iir & I915_DISPLAY_PORT_INTERRUPT) || hotplug) {
 +		u32 temp2 = 0;
 +
 +		DRM_INFO("Hotplug event received\n");
 +
 +		if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev)) {
 +			temp2 |= SDVOB_HOTPLUG_INT_STATUS |
 +				 SDVOC_HOTPLUG_INT_STATUS;
 +		} else {
 +			temp2 = I915_READ(PORT_HOTPLUG_STAT);
 +
 +			I915_WRITE(PORT_HOTPLUG_STAT, temp2);
 +		}
 +		i915_run_hotplug_tasklet(dev, temp2);
 +	}
 +
  	return IRQ_HANDLED;
  }
  
@@@ -691,33 -499,23 +688,33 @@@ int i915_emit_irq(struct drm_device *de
  	return dev_priv->counter;
  }
  
 -void i915_user_irq_on(drm_i915_private_t *dev_priv)
 +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 |= USER_INT_FLAG;
+ 		dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
 -		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
 +			I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +		else
 +			I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
  	}
  	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
  
  }
 -
 -void i915_user_irq_off(drm_i915_private_t *dev_priv)
 +		
 +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 &= ~USER_INT_FLAG;
 -		//		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++		//		dev_priv->irq_enable_reg &= ~I915_USER_INTERRUPT;
 +		//		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
 +		//			I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +		//		else
 +		//			I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
  	}
  	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
  }
@@@ -797,15 -592,19 +794,19 @@@ int i915_irq_wait(struct drm_device *de
  
  int i915_enable_vblank(struct drm_device *dev, int plane)
  {
 -	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +	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	pipestat;
+ 
  	switch (pipe) {
  	case 0:
- 		dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
+ 		pipestat_reg = I915REG_PIPEASTAT;
+ 		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
  		break;
  	case 1:
- 		dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
+ 		pipestat_reg = I915REG_PIPEBSTAT;
+ 		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
  		break;
  	default:
  		DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
@@@ -813,18 -612,35 +814,40 @@@
  		break;
  	}
  
+ 	if (pipestat_reg)
+ 	{
+ 		pipestat = I915_READ (pipestat_reg);
+ 		/*
+ 		 * Older chips didn't have the start vblank interrupt,
+ 		 * but 
+ 		 */
+ 		if (IS_I965G (dev))
+ 			pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
+ 		else
+ 			pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
+ 		/*
+ 		 * Clear any pending status
+ 		 */
+ 		pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+ 			     I915_VBLANK_INTERRUPT_STATUS);
+ 		I915_WRITE(pipestat_reg, pipestat);
+ 	}
 -	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
 +		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +	else
 +		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +
+ 
  	return 0;
  }
  
  void i915_disable_vblank(struct drm_device *dev, int plane)
  {
 -	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +	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	pipestat;
  
  	switch (pipe) {
  	case 0:
@@@ -839,76 -657,28 +864,89 @@@
  		break;
  	}
  
 -	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
 +		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +	else
 +		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++
+ 	if (pipestat_reg)
+ 	{
+ 		pipestat = I915_READ (pipestat_reg);
+ 		pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
+ 			      I915_VBLANK_INTERRUPT_ENABLE);
+ 		/*
+ 		 * Clear any pending status
+ 		 */
+ 		pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+ 			     I915_VBLANK_INTERRUPT_STATUS);
+ 		I915_WRITE(pipestat_reg, pipestat);
+ 	}
  }
  
 -static void i915_enable_interrupt (struct drm_device *dev)
 +void i915_enable_interrupt (struct drm_device *dev)
  {
 -	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -	
 +	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +	struct drm_output *o;
 +
- 	dev_priv->irq_enable_reg |= USER_INT_FLAG;
+ 	dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
  
 -	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
 +		if (dev->mode_config.num_output)
- 			dev_priv->irq_enable_reg |= HOTPLUG_FLAG;
++			dev_priv->irq_enable_reg |= I915_DISPLAY_PORT_INTERRUPT;
 +	} else {
 +		if (dev->mode_config.num_output)
- 			dev_priv->irq_enable_reg |= EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG;
++			dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
 +
 +		/* Enable global interrupts for hotplug - not a pipeA event */
 +		I915_WRITE(I915REG_PIPEASTAT, I915_READ(I915REG_PIPEASTAT) | \
I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR);  +	}
 +
- 	if (dev_priv->irq_enable_reg & (HOTPLUG_FLAG | EVENT_PIPEA_FLAG | \
EVENT_PIPEB_FLAG)) { ++	if (dev_priv->irq_enable_reg & (I915_DISPLAY_PORT_INTERRUPT | \
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)) {  +		u32 temp = 0;
 +
 +		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
 +			temp = I915_READ(PORT_HOTPLUG_EN);
 +
 +			/* Activate the CRT */
 +			temp |= CRT_HOTPLUG_INT_EN;
 +		}
 +
 +		if (IS_I9XX(dev)) {
 +			/* SDVOB */
 +			o = intel_sdvo_find(dev, 1);
 +			if (o && intel_sdvo_supports_hotplug(o)) {
 +				intel_sdvo_set_hotplug(o, 1);
 +				temp |= SDVOB_HOTPLUG_INT_EN;
 +			}
 +
 +			/* SDVOC */
 +			o = intel_sdvo_find(dev, 0);
 +			if (o && intel_sdvo_supports_hotplug(o)) {
 +				intel_sdvo_set_hotplug(o, 1);
 +				temp |= SDVOC_HOTPLUG_INT_EN;
 +			}
 +
 +			I915_WRITE(SDVOB, I915_READ(SDVOB) | SDVO_INTERRUPT_ENABLE);
 +			I915_WRITE(SDVOC, I915_READ(SDVOC) | SDVO_INTERRUPT_ENABLE);
 +		} else {
 +			/* DVO ???? */
 +		}
 +
 +		if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
 +			I915_WRITE(PORT_HOTPLUG_EN, temp);
 +
 +			DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN));
 +			DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT));
 +
 +			I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 +		}
 +	}
 +
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
 +		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +	else
 +		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +
  	dev_priv->irq_enabled = 1;
  }
  
@@@ -947,15 -717,11 +985,15 @@@ int i915_vblank_pipe_get(struct drm_dev
  		return -EINVAL;
  	}
  
 -	flag = I915_READ(I915REG_INT_ENABLE_R);
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
 +		flag = I915_READ(I915REG_INT_ENABLE_R);
 +	else
 +		flag = I915_READ16(I915REG_INT_ENABLE_R);
 +
  	pipe->pipe = 0;
- 	if (flag & VSYNC_PIPEA_FLAG)
+ 	if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
  		pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
- 	if (flag & VSYNC_PIPEB_FLAG)
+ 	if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
  		pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
  
  	return 0;
@@@ -1126,19 -885,11 +1164,17 @@@ int i915_vblank_swap(struct drm_device 
  */
  void i915_driver_irq_preinstall(struct drm_device * dev)
  {
 -	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
  
- 	I915_WRITE(I915REG_PIPEASTAT, 0xffff);
- 	I915_WRITE(I915REG_PIPEBSTAT, 0xffff);
  	I915_WRITE16(I915REG_HWSTAM, 0xeffe);
 -	I915_WRITE16(I915REG_INT_MASK_R, 0x0);
 -	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
 +		I915_WRITE(I915REG_INT_MASK_R, 0x0);
 +		I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
 +	} else {
 +		I915_WRITE16(I915REG_INT_MASK_R, 0x0);
 +		I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 +	}
 +
  }
  
  int i915_driver_irq_postinstall(struct drm_device * dev)
@@@ -1184,23 -931,14 +1220,24 @@@ void i915_driver_irq_uninstall(struct d
  		return;
  
  	dev_priv->irq_enabled = 0;
 -	I915_WRITE(I915REG_HWSTAM, 0xffffffff);
 -	I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
 -	I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
  
- 
- 	I915_WRITE(I915REG_PIPEASTAT, 0xffff);
- 	I915_WRITE(I915REG_PIPEBSTAT, 0xffff);
+ 	temp = I915_READ(I915REG_PIPEASTAT);
+ 	I915_WRITE(I915REG_PIPEASTAT, temp);
+ 	temp = I915_READ(I915REG_PIPEBSTAT);
+ 	I915_WRITE(I915REG_PIPEBSTAT, temp);
 -	temp = I915_READ(I915REG_INT_IDENTITY_R);
 -	I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 +	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
 +		I915_WRITE(I915REG_HWSTAM, 0xffffffff);
 +		I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
 +		I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
 +
 +		temp = I915_READ(I915REG_INT_IDENTITY_R);
 +		I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 +	} else {
 +		I915_WRITE16(I915REG_HWSTAM, 0xffff);
 +		I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
 +		I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 +
 +		temp = I915_READ16(I915REG_INT_IDENTITY_R);
 +		I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
 +	}
  }
commit 2a618e5a7f6d26fe85e7d931d0ef08d9f18b1b7c
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:36:40 2008 +0100

    Bug # 14712
    Disable page saving for GPU read-only TTMs.

diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index cc80b13..e991254 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -299,13 +299,13 @@ int drm_ttm_populate(struct drm_ttm *ttm)
 		return 0;
 
 	be = ttm->be;
-	if (ttm->page_flags & DRM_TTM_PAGE_WRITE) {
-		for (i = 0; i < ttm->num_pages; ++i) {
-			page = drm_ttm_get_page(ttm, i);
-			if (!page)
-				return -ENOMEM;
-		}
+
+	for (i = 0; i < ttm->num_pages; ++i) {
+		page = drm_ttm_get_page(ttm, i);
+		if (!page)
+			return -ENOMEM;
 	}
+
 	be->func->populate(be, ttm->num_pages, ttm->pages, ttm->dummy_read_page);
 	ttm->state = ttm_unbound;
 	return 0;
commit 5bebcd7a0b548b29a9859b2949b06662968cc868
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:19:36 2008 +0100

    Dont allow !sysadmin clients to alter the memory type of
    NO_EVICT buffers.

diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 2e21004..a94bd8a 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -979,6 +979,20 @@ static int drm_bo_modify_proposed_flags (struct \
drm_buffer_object *bo,  return -EPERM;
 	}
 
+	if (likely(new_mask & DRM_BO_MASK_MEM) &&
+	    (bo->mem.flags & DRM_BO_FLAG_NO_EVICT) &&
+	    !DRM_SUSER(DRM_CURPROC)) {
+		if (likely(bo->mem.flags & new_flags & new_mask &
+			   DRM_BO_MASK_MEM))
+			new_flags = (new_flags & ~DRM_BO_MASK_MEM) |
+				(bo->mem.flags & DRM_BO_MASK_MEM);
+		else {
+			DRM_ERROR("Incompatible memory type specification "
+				  "for NO_EVICT buffer.\n");
+			return -EPERM;
+		}
+	}
+
 	if ((new_flags & DRM_BO_FLAG_NO_MOVE)) {
 		DRM_ERROR("DRM_BO_FLAG_NO_MOVE is not properly implemented yet.\n");
 		return -EPERM;
commit 88be276a427124cc545a7d89b137e4ae6dd79acb
Author: Alan Hourihane <alanh@tungstengraphics.com>
Date:   Thu Jan 17 13:04:42 2008 +0000

    Fix for debug memory routines

diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c
index 1a6c48d..12e0141 100644
--- a/linux-core/drm_memory.c
+++ b/linux-core/drm_memory.c
@@ -326,7 +326,12 @@ static void *agp_remap(unsigned long offset, unsigned long size,
 	return NULL;
 }
 #endif				/* agp */
-
+#else
+static void *agp_remap(unsigned long offset, unsigned long size,
+		       struct drm_device * dev)
+{
+	return NULL;
+}
 #endif				/* debug_memory */
 
 void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
commit 32625774072f905d15024cc40ce7fd364d9ee4cd
Author: Alan Hourihane <alanh@tungstengraphics.com>
Date:   Thu Jan 17 13:04:23 2008 +0000

    Add error message

diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index 9d80327..0ca0c40 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -520,8 +520,10 @@ int drm_fence_object_create(struct drm_device *dev, uint32_t \
fence_class,  struct drm_fence_manager *fm = &dev->fm;
 
 	fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
-	if (!fence)
+	if (!fence) {
+		DRM_ERROR("Out of memory creating fence object\n");
 		return -ENOMEM;
+	}
 	ret = drm_fence_object_init(dev, fence_class, type, flags, fence);
 	if (ret) {
 		drm_fence_usage_deref_unlocked(&fence);
commit c0a1cd052ac44d1b342fa3f26afe1bd21d92b194
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Thu Jan 17 13:10:36 2008 +0100

    Add an emergency pinnable memory quota for root-only processes.

diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 1fea807..2f76f3d 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -1001,8 +1001,10 @@ extern int drm_unbind_agp(DRM_AGP_MEM * handle);
 extern void drm_free_memctl(size_t size);
 extern int drm_alloc_memctl(size_t size);
 extern void drm_query_memctl(uint64_t *cur_used,
+			     uint64_t *emer_used,
 			     uint64_t *low_threshold,
-			     uint64_t *high_threshold);
+			     uint64_t *high_threshold,
+			     uint64_t *emer_threshold);
 extern void drm_init_memctl(size_t low_threshold,
 			    size_t high_threshold,
 			    size_t unit_size);
diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c
index 402a680..1a6c48d 100644
--- a/linux-core/drm_memory.c
+++ b/linux-core/drm_memory.c
@@ -39,8 +39,10 @@
 static struct {
 	spinlock_t lock;
 	uint64_t cur_used;
+	uint64_t emer_used;
 	uint64_t low_threshold;
 	uint64_t high_threshold;
+	uint64_t emer_threshold;
 } drm_memctl = {
 	.lock = SPIN_LOCK_UNLOCKED
 };
@@ -59,14 +61,30 @@ static inline size_t drm_size_align(size_t size)
 
 int drm_alloc_memctl(size_t size)
 {
-	int ret;
+	int ret = 0;
 	unsigned long a_size = drm_size_align(size);
+	unsigned long new_used = drm_memctl.cur_used + a_size;
 
 	spin_lock(&drm_memctl.lock);
-	ret = ((drm_memctl.cur_used + a_size) > drm_memctl.high_threshold) ?
-		-ENOMEM : 0;
-	if (!ret)
-		drm_memctl.cur_used += a_size;
+	if (unlikely(new_used > drm_memctl.high_threshold)) {
+		if (!DRM_SUSER(DRM_CURPROC) ||
+		    (new_used + drm_memctl.emer_used > drm_memctl.emer_threshold) ||
+		    (a_size > 2*PAGE_SIZE)) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		/*
+		 * Allow small root-only allocations, even if the
+		 * high threshold is exceeded.
+		 */
+
+		new_used -= drm_memctl.high_threshold;
+		drm_memctl.emer_used += new_used;
+		a_size -= new_used;
+	}
+	drm_memctl.cur_used += a_size;
+out:
 	spin_unlock(&drm_memctl.lock);
 	return ret;
 }
@@ -77,19 +95,30 @@ void drm_free_memctl(size_t size)
 	unsigned long a_size = drm_size_align(size);
 
 	spin_lock(&drm_memctl.lock);
+	if (likely(a_size >= drm_memctl.emer_used)) {
+		a_size -= drm_memctl.emer_used;
+		drm_memctl.emer_used = 0;
+	} else {
+		drm_memctl.emer_used -= a_size;
+		a_size = 0;
+	}
 	drm_memctl.cur_used -= a_size;
 	spin_unlock(&drm_memctl.lock);
 }
 EXPORT_SYMBOL(drm_free_memctl);
 
 void drm_query_memctl(uint64_t *cur_used,
+		      uint64_t *emer_used,
 		      uint64_t *low_threshold,
-		      uint64_t *high_threshold)
+		      uint64_t *high_threshold,
+		      uint64_t *emer_threshold)
 {
 	spin_lock(&drm_memctl.lock);
 	*cur_used = drm_memctl.cur_used;
+	*emer_used = drm_memctl.emer_used;
 	*low_threshold = drm_memctl.low_threshold;
 	*high_threshold = drm_memctl.high_threshold;
+	*emer_threshold = drm_memctl.emer_threshold;
 	spin_unlock(&drm_memctl.lock);
 }
 EXPORT_SYMBOL(drm_query_memctl);
@@ -99,9 +128,12 @@ void drm_init_memctl(size_t p_low_threshold,
 		     size_t unit_size)
 {
 	spin_lock(&drm_memctl.lock);
+	drm_memctl.emer_used = 0;
 	drm_memctl.cur_used = 0;
 	drm_memctl.low_threshold = p_low_threshold * unit_size;
 	drm_memctl.high_threshold = p_high_threshold * unit_size;
+	drm_memctl.emer_threshold = (drm_memctl.high_threshold >> 4) +
+		drm_memctl.high_threshold;
 	spin_unlock(&drm_memctl.lock);
 }
 
diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c
index 67afee8..42da5c6 100644
--- a/linux-core/drm_proc.c
+++ b/linux-core/drm_proc.c
@@ -445,9 +445,10 @@ static int drm__objects_info(char *buf, char **start, off_t \
offset, int request,  struct drm_buffer_manager *bm = &dev->bm;
 	struct drm_fence_manager *fm = &dev->fm;
 	uint64_t used_mem;
+	uint64_t used_emer;
 	uint64_t low_mem;
 	uint64_t high_mem;
-
+	uint64_t emer_mem;
 
 	if (offset > DRM_PROC_LIMIT) {
 		*eof = 1;
@@ -476,7 +477,7 @@ static int drm__objects_info(char *buf, char **start, off_t \
offset, int request,  DRM_PROC_PRINT("Buffer objects are not supported by this \
driver.\n");  }
 
-	drm_query_memctl(&used_mem, &low_mem, &high_mem);
+	drm_query_memctl(&used_mem, &used_emer, &low_mem, &high_mem, &emer_mem);
 
 	if (used_mem > 16*PAGE_SIZE) {
 		DRM_PROC_PRINT("Used object memory is %lu pages.\n",
@@ -485,10 +486,19 @@ static int drm__objects_info(char *buf, char **start, off_t \
offset, int request,  DRM_PROC_PRINT("Used object memory is %lu bytes.\n",
 			       (unsigned long) used_mem);
 	}
+	if (used_emer > 16*PAGE_SIZE) {
+		DRM_PROC_PRINT("Used emergency memory is %lu pages.\n",
+			       (unsigned long) (used_emer >> PAGE_SHIFT));
+	} else {
+		DRM_PROC_PRINT("Used emergency memory is %lu bytes.\n\n",
+			       (unsigned long) used_emer);
+	}
 	DRM_PROC_PRINT("Soft object memory usage threshold is %lu pages.\n",
 		       (unsigned long) (low_mem >> PAGE_SHIFT));
 	DRM_PROC_PRINT("Hard object memory usage threshold is %lu pages.\n",
 		       (unsigned long) (high_mem >> PAGE_SHIFT));
+	DRM_PROC_PRINT("Emergency root only memory usage threshold is %lu pages.\n",
+		       (unsigned long) (emer_mem >> PAGE_SHIFT));
 
 	DRM_PROC_PRINT("\n");
 
commit 7bcce66a1d5c93ff9b9f20d45d5b2c33c8ca8da9
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:07:56 2008 +0100

    Fix kernel crash when we hit OOM conditions.
    (Alan Hourihane)

diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 51cd175..2e21004 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -789,6 +789,11 @@ static int drm_bo_mem_force_space(struct drm_device *dev,
 	}
 
 	node = drm_mm_get_block(node, num_pages, mem->page_alignment);
+	if (unlikely(!node)) {
+		mutex_unlock(&dev->struct_mutex);
+		return -ENOMEM;
+	}
+
 	mutex_unlock(&dev->struct_mutex);
 	mem->mm_node = node;
 	mem->mem_type = mem_type;
@@ -1482,6 +1487,9 @@ static int drm_buffer_object_validate(struct drm_buffer_object \
*bo,  if (ret) {
 			if (ret != -EAGAIN)
 				DRM_ERROR("Failed moving buffer.\n");
+			if (ret == -ENOMEM)
+				DRM_ERROR("Out of aperture space or "
+					  "DRM memory quota.\n");
 			return ret;
 		}
 	}
@@ -2747,7 +2755,7 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
 	list->file_offset_node = drm_mm_search_free(&dev->offset_manager,
 						    bo->mem.num_pages, 0, 0);
 
-	if (!list->file_offset_node) {
+	if (unlikely(!list->file_offset_node)) {
 		drm_bo_takedown_vm_locked(bo);
 		return -ENOMEM;
 	}
@@ -2755,6 +2763,11 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object \
*bo)  list->file_offset_node = drm_mm_get_block(list->file_offset_node,
 						  bo->mem.num_pages, 0);
 
+	if (unlikely(!list->file_offset_node)) {
+		drm_bo_takedown_vm_locked(bo);
+		return -ENOMEM;
+	}
+		
 	list->hash.key = list->file_offset_node->start;
 	if (drm_ht_insert_item(&dev->map_hash, &list->hash)) {
 		drm_bo_takedown_vm_locked(bo);
commit f1a681ebe5573c2ec7806ba4cb754314baef6935
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:02:09 2008 +0100

    Avoid duplicate calls to drm_ttm_bind in some cases.

diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index fd3cf9d..51cd175 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -208,36 +208,35 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo,
 			if (ret)
 				goto out_err;
 		}
-	}
-
-	if ((bo->mem.mem_type == DRM_BO_MEM_LOCAL) && bo->ttm == NULL) {
-
-		struct drm_bo_mem_reg *old_mem = &bo->mem;
-		uint64_t save_flags = old_mem->flags;
-		uint64_t save_proposed_flags = old_mem->proposed_flags;
-
-		*old_mem = *mem;
-		mem->mm_node = NULL;
-		old_mem->proposed_flags = save_proposed_flags;
-		DRM_FLAG_MASKED(save_flags, mem->flags, DRM_BO_MASK_MEMTYPE);
 
-	} else if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
-		   !(new_man->flags & _DRM_FLAG_MEMTYPE_FIXED)) {
+		if (bo->mem.mem_type == DRM_BO_MEM_LOCAL) {
+			
+			struct drm_bo_mem_reg *old_mem = &bo->mem;
+			uint64_t save_flags = old_mem->flags;
+			uint64_t save_proposed_flags = old_mem->proposed_flags;
+			
+			*old_mem = *mem;
+			mem->mm_node = NULL;
+			old_mem->proposed_flags = save_proposed_flags;
+			DRM_FLAG_MASKED(save_flags, mem->flags,
+					DRM_BO_MASK_MEMTYPE);
+			goto moved;
+		}
+		
+	}
 
+	if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
+	    !(new_man->flags & _DRM_FLAG_MEMTYPE_FIXED))		
 		ret = drm_bo_move_ttm(bo, evict, no_wait, mem);
-
-	} else if (dev->driver->bo_driver->move) {
+	else if (dev->driver->bo_driver->move) 
 		ret = dev->driver->bo_driver->move(bo, evict, no_wait, mem);
-
-	} else {
-
+	else
 		ret = drm_bo_move_memcpy(bo, evict, no_wait, mem);
 
-	}
-
 	if (ret)
 		goto out_err;
 
+moved:
 	if (old_is_pci || new_is_pci)
 		drm_bo_vm_post_move(bo);
 
commit fa1d88e3b2de843f33c9d77c9d95db762a950a14
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 09:56:06 2008 +0100

    Make sure other TTM memory types than TT is really unbound when evicted.

diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index 30e0f43..21673da 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -42,7 +42,6 @@ static void drm_bo_free_old_node(struct drm_buffer_object *bo)
 	if (old_mem->mm_node && (old_mem->mm_node != bo->pinned_node)) {
 		mutex_lock(&bo->dev->struct_mutex);
 		drm_mm_put_block(old_mem->mm_node);
-		old_mem->mm_node = NULL;
 		mutex_unlock(&bo->dev->struct_mutex);
 	}
 	old_mem->mm_node = NULL;
@@ -57,7 +56,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo,
 	uint64_t save_proposed_flags = old_mem->proposed_flags;
 	int ret;
 
-	if (old_mem->mem_type == DRM_BO_MEM_TT) {
+	if (old_mem->mem_type != DRM_BO_MEM_LOCAL) {
 		if (evict)
 			drm_ttm_evict(ttm);
 		else
commit 8a18d123f55a7fb11ce333f0b1095020918b8616
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Thu Feb 28 09:08:52 2008 +0100

    Avoid large kmallocs.

diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 7d247f9..f6df74a 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -1181,7 +1181,6 @@ static int i915_handle_copyback(struct drm_device *dev,
 			buffers++;
 		}
 	}
-
 	return err;
 }
 
@@ -1272,7 +1271,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 	struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
 	int num_buffers;
 	int ret;
-	struct drm_i915_validate_buffer *buffers;
 
 	if (!dev_priv->allow_batchbuffer) {
 		DRM_ERROR("Batchbuffer ioctl disabled\n");
@@ -1288,7 +1286,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 	if (exec_buf->num_buffers > dev_priv->max_validate_buffers)
 		return -EINVAL;
 
-
 	ret = drm_bo_read_lock(&dev->bm.bm_lock);
 	if (ret)
 		return ret;
@@ -1306,8 +1303,12 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 
 	num_buffers = exec_buf->num_buffers;
 
-	buffers = drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), \
                DRM_MEM_DRIVER);
-	if (!buffers) {
+	if (!dev_priv->val_bufs) {
+		dev_priv->val_bufs =
+			vmalloc(sizeof(struct drm_i915_validate_buffer)*
+				dev_priv->max_validate_buffers);
+	}
+	if (!dev_priv->val_bufs) {
 		drm_bo_read_unlock(&dev->bm.bm_lock);
 		mutex_unlock(&dev_priv->cmdbuf_mutex);
 		return -ENOMEM;
@@ -1315,7 +1316,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 
 	/* validate buffer list + fixup relocations */
 	ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list,
-					buffers, &num_buffers);
+					dev_priv->val_bufs, &num_buffers);
 	if (ret)
 		goto out_err0;
 
@@ -1324,7 +1325,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 	drm_agp_chipset_flush(dev);
 
 	/* submit buffer */
-	batch->start = buffers[num_buffers-1].buffer->offset;
+	batch->start = dev_priv->val_bufs[num_buffers-1].buffer->offset;
 
 	DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n",
 		  batch->start, batch->used, batch->num_cliprects);
@@ -1341,13 +1342,11 @@ static int i915_execbuffer(struct drm_device *dev, void \
*data,  out_err0:
 
 	/* handle errors */
-	ret = i915_handle_copyback(dev, buffers, num_buffers, ret);
+	ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret);
 	mutex_lock(&dev->struct_mutex);
-	i915_dereference_buffers_locked(buffers, num_buffers);
+	i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers);
 	mutex_unlock(&dev->struct_mutex);
 
-	drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), \
                DRM_MEM_DRIVER);
-
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
 	drm_bo_read_unlock(&dev->bm.bm_lock);
 	return ret;
@@ -1618,6 +1617,13 @@ void i915_driver_lastclose(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
+#ifdef I915_HAVE_BUFFER
+	if (dev_priv->val_bufs) {
+		vfree(dev_priv->val_bufs);
+		dev_priv->val_bufs = NULL;
+	}
+#endif
+
 	if (drm_getsarea(dev) && dev_priv->sarea_priv)
 		i915_do_cleanup_pageflip(dev);
 	if (dev_priv->agp_heap)
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 570fc4d..3bc39e2 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -69,6 +69,7 @@
 
 #ifdef I915_HAVE_BUFFER
 #define I915_MAX_VALIDATE_BUFFERS 4096
+struct drm_i915_validate_buffer;
 #endif
 
 typedef struct _drm_i915_ring_buffer {
@@ -141,6 +142,7 @@ typedef struct drm_i915_private {
 	void *agp_iomap;
 	unsigned int max_validate_buffers;
 	struct mutex cmdbuf_mutex;
+	struct drm_i915_validate_buffer *val_bufs;
 #endif
 
 	DRM_SPINTYPE swaps_lock;
commit f13936f7fc4d4932d5c511ccec29f1c4d24dc2dc
Author: Stuart Bennett <sb476@cam.ac.uk>
Date:   Tue Mar 11 00:33:58 2008 +0000

    nouveau: move AGP reset to mem_init_agp
    
    Also, power cycle PGRAPH when resetting AGP -- it seems to fix problems \
encountered by p0g on nv25

diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c
index 80b2990..4e80ca4 100644
--- a/shared-core/nouveau_mem.c
+++ b/shared-core/nouveau_mem.c
@@ -300,6 +300,32 @@ uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
 	return 0;
 }
 
+static void nouveau_mem_reset_agp(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable;
+
+	saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1);
+	saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19);
+
+	/* clear busmaster bit */
+	NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
+	/* clear SBA and AGP bits */
+	NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
+
+	/* power cycle pgraph, if enabled */
+	pmc_enable = NV_READ(NV03_PMC_ENABLE);
+	if (pmc_enable & NV_PMC_ENABLE_PGRAPH) {
+		NV_WRITE(NV03_PMC_ENABLE, pmc_enable & ~NV_PMC_ENABLE_PGRAPH);
+		NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
+				NV_PMC_ENABLE_PGRAPH);
+	}
+
+	/* and restore (gives effect of resetting AGP) */
+	NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
+	NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
+}
+
 static int
 nouveau_mem_init_agp(struct drm_device *dev, int ttm)
 {
@@ -308,6 +334,8 @@ nouveau_mem_init_agp(struct drm_device *dev, int ttm)
 	struct drm_agp_mode mode;
 	int ret;
 
+	nouveau_mem_reset_agp(dev);
+
 	ret = drm_agp_acquire(dev);
 	if (ret) {
 		DRM_ERROR("Unable to acquire AGP: %d\n", ret);
diff --git a/shared-core/nv04_mc.c b/shared-core/nv04_mc.c
index 766f3a3..24c1f7b 100644
--- a/shared-core/nv04_mc.c
+++ b/shared-core/nv04_mc.c
@@ -7,25 +7,12 @@ int
 nv04_mc_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t saved_pci_nv_1, saved_pci_nv_19;
-
-	saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1);
-	saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19);
-
-	/* clear busmaster bit */
-	NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~(0x00000001 << 2));
-	/* clear SBA and AGP bits */
-	NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
 
 	/* Power up everything, resetting each individual unit will
 	 * be done later if needed.
 	 */
 	NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
 
-	/* and restore (gives effect of resetting AGP) */
-	NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
-	NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
-
 	return 0;
 }
 
commit 07ba3b7193f1a50c3ef0509f9e37dab41457f81b
Author: Dave Airlie <airlied@linux.ie>
Date:   Mon Mar 10 18:30:17 2008 +1000

    remove unneeded load call

diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index 6584f51..c68adba 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -157,11 +157,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct \
pci_dev *pdev,  }
 	}
 
-	if (dev->driver->load)
-		if ((retcode = dev->driver->load(dev, ent->driver_data)))
-			goto error_out_unreg;
-
-
 	retcode = drm_ctxbitmap_init(dev);
 	if (retcode) {
 		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
commit 2848f048616c2c97f02701386ee73137a1307e2c
Author: Keith Packard <keithp@keithp.com>
Date:   Thu Jan 24 11:46:45 2008 -0800

    Switch from PIPE_VBLANK to PIPE_EVENT interrupts.
    
    My 965GM gets interrupts stuck when using the old PIPE_VBLANK interrupt.
    Switch to the PIPE_EVENT interrupt mechanism, and set the PIPE*STAT
    registers to use START_VBLANK on 965 and VBLANK on previous chips.

diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 4d3ac0a..570fc4d 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -466,10 +466,23 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const \
char *caller);  
 /* Interrupt bits:
  */
-#define USER_INT_FLAG    (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
+#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)
+#define I915_DISPLAY_PORT_INTERRUPT			(1<<17)
+#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15)
+#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT	(1<<14)
+#define I915_HWB_OOM_INTERRUPT				(1<<13) /* binner out of memory */
+#define I915_SYNC_STATUS_INTERRUPT			(1<<12)
+#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT	(1<<11)
+#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT	(1<<10)
+#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT	(1<<9)
+#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT	(1<<8)
+#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT		(1<<7)
+#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT		(1<<6)
+#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT		(1<<5)
+#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT		(1<<4)
+#define I915_DEBUG_INTERRUPT				(1<<2)
+#define I915_USER_INTERRUPT				(1<<1)
+
 
 #define I915REG_HWSTAM		0x02098
 #define I915REG_INT_IDENTITY_R	0x020a4
@@ -513,8 +526,31 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const \
char *caller);  #define PIPE_PIXEL_MASK         0x00ffffff
 #define PIPE_PIXEL_SHIFT        0
 
-#define I915_VBLANK_INTERRUPT_ENABLE	(1UL<<17)
-#define I915_VBLANK_CLEAR		(1UL<<1)
+#define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
+#define I915_CRC_ERROR_ENABLE			(1UL<<29)
+#define I915_CRC_DONE_ENABLE			(1UL<<28)
+#define I915_GMBUS_EVENT_ENABLE			(1UL<<27)
+#define I915_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
+#define I915_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
+#define I915_DPST_EVENT_ENABLE			(1UL<<23)
+#define I915_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
+#define I915_ODD_FIELD_INTERRUPT_ENABLE		(1UL<<21)
+#define I915_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+#define I915_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18)	/* 965 or later */
+#define I915_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
+#define I915_OVERLAY_UPDATED_ENABLE		(1UL<<16)
+#define I915_CRC_ERROR_INTERRUPT_STATUS		(1UL<<13)
+#define I915_CRC_DONE_INTERRUPT_STATUS		(1UL<<12)
+#define I915_GMBUS_INTERRUPT_STATUS		(1UL<<11)
+#define I915_VSYNC_INTERRUPT_STATUS		(1UL<<9)
+#define I915_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
+#define I915_DPST_EVENT_STATUS			(1UL<<7)
+#define I915_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+#define I915_ODD_FIELD_INTERRUPT_STATUS		(1UL<<5)
+#define I915_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+#define I915_START_VBLANK_INTERRUPT_STATUS	(1UL<<2)	/* 965 or later */
+#define I915_VBLANK_INTERRUPT_STATUS		(1UL<<1)
+#define I915_OVERLAY_UPDATED_STATUS		(1UL<<0)
 
 #define SRX_INDEX		0x3c4
 #define SRX_DATA		0x3c5
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index 126f037..a9b67a9 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -31,10 +31,6 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#define USER_INT_FLAG (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-
 #define MAX_NOPID ((u32)~0)
 
 /**
@@ -420,55 +416,63 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
+	u32 iir;
 	u32 pipea_stats, pipeb_stats;
+	int vblank = 0;
 
-	pipea_stats = I915_READ(I915REG_PIPEASTAT);
-	pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
-
-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
-
+	iir = I915_READ(I915REG_INT_IDENTITY_R);
 #if 0
-	DRM_DEBUG("flag=%08x\n", temp);
+	DRM_DEBUG("flag=%08x\n", iir);
 #endif
-	if (temp == 0)
+	if (iir == 0) {
+		DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
+			   iir,
+			   I915_READ(I915REG_INT_MASK_R),
+			   I915_READ(I915REG_INT_ENABLE_R),
+			   I915_READ(I915REG_PIPEASTAT),
+			   I915_READ(I915REG_PIPEBSTAT));
 		return IRQ_NONE;
+	}
 
 	/*
 	 * Clear the PIPE(A|B)STAT regs before the IIR otherwise
 	 * we may get extra interrupts.
 	 */
-	if (temp & VSYNC_PIPEA_FLAG) {
-		drm_handle_vblank(dev, i915_get_plane(dev, 0));
-		I915_WRITE(I915REG_PIPEASTAT,
-			   pipea_stats | I915_VBLANK_INTERRUPT_ENABLE |
-			   I915_VBLANK_CLEAR);
-	}
-	if (temp & VSYNC_PIPEB_FLAG) {
-		drm_handle_vblank(dev, i915_get_plane(dev, 1));
-		I915_WRITE(I915REG_PIPEBSTAT,
-			   pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE |
-			   I915_VBLANK_CLEAR);
+	if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+		pipea_stats = I915_READ(I915REG_PIPEASTAT);
+		if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+				   I915_VBLANK_INTERRUPT_STATUS))
+		{
+			vblank++;
+			drm_handle_vblank(dev, i915_get_plane(dev, 0));
+		}
+		I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
+	}
+	if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+		pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+		if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
+				   I915_VBLANK_INTERRUPT_STATUS))
+		{
+			vblank++;
+			drm_handle_vblank(dev, i915_get_plane(dev, 1));
+		}
+		I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
 	}
 
-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-	(void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */
-
-	temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG |
-		 VSYNC_PIPEB_FLAG);
-
 	if (dev_priv->sarea_priv)
-		dev_priv->sarea_priv->last_dispatch =
-			READ_BREADCRUMB(dev_priv);
+	    dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
+	I915_WRITE(I915REG_INT_IDENTITY_R, iir);
+	(void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
 
-	if (temp & USER_INT_FLAG) {
+	if (iir & I915_USER_INTERRUPT) {
 		DRM_WAKEUP(&dev_priv->irq_queue);
 #ifdef I915_HAVE_FENCE
 		i915_fence_handler(dev);
 #endif
 	}
 
-	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
+	if (vblank) {
 		if (dev_priv->swaps_pending > 0)
 			drm_locked_tasklet(dev, i915_vblank_tasklet);
 	}
@@ -499,8 +503,8 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv)
 {
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
 	if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
-		dev_priv->irq_enable_reg |= USER_INT_FLAG;
-		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+		dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
+		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 	}
 	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 
@@ -511,7 +515,7 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv)
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
 	if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
 		//		dev_priv->irq_enable_reg &= ~USER_INT_FLAG;
-		//		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+		//		I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 	}
 	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 }
@@ -590,13 +594,17 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe = i915_get_pipe(dev, plane);
+	u32	pipestat_reg = 0;
+	u32	pipestat;
 
 	switch (pipe) {
 	case 0:
-		dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
+		pipestat_reg = I915REG_PIPEASTAT;
+		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
 		break;
 	case 1:
-		dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
+		pipestat_reg = I915REG_PIPEBSTAT;
+		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
 		break;
 	default:
 		DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
@@ -604,7 +612,25 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
 		break;
 	}
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	if (pipestat_reg)
+	{
+		pipestat = I915_READ (pipestat_reg);
+		/*
+		 * Older chips didn't have the start vblank interrupt,
+		 * but 
+		 */
+		if (IS_I965G (dev))
+			pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
+		else
+			pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
+		/*
+		 * Clear any pending status
+		 */
+		pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+			     I915_VBLANK_INTERRUPT_STATUS);
+		I915_WRITE(pipestat_reg, pipestat);
+	}
+	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 
 	return 0;
 }
@@ -613,13 +639,17 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe = i915_get_pipe(dev, plane);
+	u32	pipestat_reg = 0;
+	u32	pipestat;
 
 	switch (pipe) {
 	case 0:
-		dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG;
+		pipestat_reg = I915REG_PIPEASTAT;
+		dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
 		break;
 	case 1:
-		dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG;
+		pipestat_reg = I915REG_PIPEBSTAT;
+		dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
 		break;
 	default:
 		DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
@@ -627,16 +657,28 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
 		break;
 	}
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	if (pipestat_reg)
+	{
+		pipestat = I915_READ (pipestat_reg);
+		pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
+			      I915_VBLANK_INTERRUPT_ENABLE);
+		/*
+		 * Clear any pending status
+		 */
+		pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
+			     I915_VBLANK_INTERRUPT_STATUS);
+		I915_WRITE(pipestat_reg, pipestat);
+	}
 }
 
 static void i915_enable_interrupt (struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	
-	dev_priv->irq_enable_reg |= USER_INT_FLAG;
+	dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 	dev_priv->irq_enabled = 1;
 }
 
@@ -677,9 +719,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 
 	flag = I915_READ(I915REG_INT_ENABLE_R);
 	pipe->pipe = 0;
-	if (flag & VSYNC_PIPEA_FLAG)
+	if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
 		pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-	if (flag & VSYNC_PIPEB_FLAG)
+	if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
 		pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
 
 	return 0;
@@ -883,16 +925,20 @@ int i915_driver_irq_postinstall(struct drm_device * dev)
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
+	u32 temp;
 
 	if (!dev_priv)
 		return;
 
 	dev_priv->irq_enabled = 0;
-	I915_WRITE16(I915REG_HWSTAM, 0xffff);
-	I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
-	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-
-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+	I915_WRITE(I915REG_HWSTAM, 0xffffffff);
+	I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
+	I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
+
+	temp = I915_READ(I915REG_PIPEASTAT);
+	I915_WRITE(I915REG_PIPEASTAT, temp);
+	temp = I915_READ(I915REG_PIPEBSTAT);
+	I915_WRITE(I915REG_PIPEBSTAT, temp);
+	temp = I915_READ(I915REG_INT_IDENTITY_R);
+	I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 }
commit ce3733572e4eea6d9adb167d8fccac745455445b
Author: Dave Airlie <airlied@linux.ie>
Date:   Sat Mar 8 08:30:03 2008 +1000

    drm/radeon: check sarea_priv exists

diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index 70651d7..8489549 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -3126,12 +3126,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void \
*data, struct drm_fil  DRM_DEBUG("color tiling disabled\n");
 			dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
 			dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
-			dev_priv->sarea_priv->tiling_enabled = 0;
+			if (dev_priv->sarea_priv)
+				dev_priv->sarea_priv->tiling_enabled = 0;
 		} else if (sp->value == 1) {
 			DRM_DEBUG("color tiling enabled\n");
 			dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
 			dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
-			dev_priv->sarea_priv->tiling_enabled = 1;
+			if (dev_priv->sarea_priv)
+				dev_priv->sarea_priv->tiling_enabled = 1;
 		}
 		break;
 	case RADEON_SETPARAM_PCIGART_LOCATION:
commit 1ccccbd4ce3463edb459eb193feb572938fce19e
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Fri Mar 7 15:08:59 2008 +1100

    nouveau: redo channel idle detection
    
    Will hopefully work a bit better than previous code, which depended on
    knowing the channel's most recent PUT value.  Some chips always return
    0 on reading these regs, and currently userspace is the only other entity
    which knows the value.

diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 8e93207..d8fda27 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -390,6 +390,34 @@ nouveau_fifo_alloc(struct drm_device *dev, struct \
nouveau_channel **chan_ret,  return 0;
 }
 
+static int
+nouveau_channel_idle(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
+	uint32_t caches;
+	int idle;
+
+	caches = NV_READ(NV03_PFIFO_CACHES);
+	NV_WRITE(NV03_PFIFO_CACHES, caches & ~1);
+
+	if (engine->fifo.channel_id(dev) != chan->id) {
+		struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
+
+		if (INSTANCE_RD(ramfc, 0) != INSTANCE_RD(ramfc, 1))
+			idle = 0;
+		else
+			idle = 1;
+	} else {
+		idle = (NV_READ(NV04_PFIFO_CACHE1_DMA_GET) ==
+			NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
+	}
+
+	NV_WRITE(NV03_PFIFO_CACHES, caches);
+	return idle;
+}
+
 /* stops a fifo */
 void nouveau_fifo_free(struct nouveau_channel *chan)
 {
@@ -400,22 +428,9 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 
 	DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id);
 
-	/* Disable channel switching, if this channel isn't currenly
-	 * active re-enable it if there's still pending commands.
-	 * We really should do a manual context switch here, but I'm
-	 * not sure I trust our ability to do this reliably yet..
-	 */
-	NV_WRITE(NV03_PFIFO_CACHES, 0);
-	if (engine->fifo.channel_id(dev) != chan->id &&
-	    NV_READ(chan->get) != NV_READ(chan->put)) {
-		NV_WRITE(NV03_PFIFO_CACHES, 1);
-	}
-
 	/* Give the channel a chance to idle, wait 2s (hopefully) */
 	t_start = engine->timer.read(dev);
-	while (NV_READ(chan->get) != NV_READ(chan->put) ||
-	       NV_READ(NV03_PFIFO_CACHE1_GET) !=
-	       NV_READ(NV03_PFIFO_CACHE1_PUT)) {
+	while (!nouveau_channel_idle(chan)) {
 		if (engine->timer.read(dev) - t_start > 2000000000ULL) {
 			DRM_ERROR("Failed to idle channel %d before destroy."
 				  "Prepare for strangeness..\n", chan->id);
commit cd924de02927a091c517b0ac6b9cd8f065ce448c
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Fri Mar 7 14:38:05 2008 +1100

    nouveau: don't touch NV_USER regs on channel destroy.
    
    Not only was this entirely pointless, it actually causes my NV30GL to
    die randomly when channels are destroyed.

diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 056cb6d..8e93207 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -433,13 +433,6 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 	NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
 	NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
 
-	/* stop the fifo, otherwise it could be running and
-	 * it will crash when removing gpu objects
-	 *XXX: from real-world evidence, absolutely useless..
-	 */
-	NV_WRITE(chan->get, chan->pushbuf_base);
-	NV_WRITE(chan->put, chan->pushbuf_base);
-
 	// FIXME XXX needs more code
 
 	engine->fifo.destroy_context(chan);

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
--
_______________________________________________
Dri-patches mailing list
Dri-patches@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-patches


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic