via: Try to improve command-buffer chaining.

Bump driver date and patchlevel.

Signed-off-by: Dave Airlie <airlied@linux.ie>
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index c0539c6..7635e85 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -252,7 +252,7 @@
 		break;
 	case VIA_DMA_INITIALIZED:
 		retcode = (dev_priv->ring.virtual_start != NULL) ?
-		    0 : DRM_ERR(EFAULT);
+			0 : DRM_ERR(EFAULT);
 		break;
 	default:
 		retcode = DRM_ERR(EINVAL);
@@ -432,56 +432,32 @@
 {
 	int paused, count;
 	volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
-
-	via_flush_write_combine();
-	while (!*(via_get_dma(dev_priv) - 1)) ;
-	*dev_priv->last_pause_ptr = pause_addr_lo;
-	via_flush_write_combine();
-
-	/*
-	 * The below statement is inserted to really force the flush.
-	 * Not sure it is needed.
-	 */
-
-	while (!*dev_priv->last_pause_ptr) ;
-	dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
-	while (!*dev_priv->last_pause_ptr) ;
+	uint32_t reader,ptr;
 
 	paused = 0;
-	count = 20;
+	via_flush_write_combine();
+	*dev_priv->last_pause_ptr = pause_addr_lo;
+	via_flush_write_combine();
+	reader = *(dev_priv->hw_addr_ptr);
+	ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
+		dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+	dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
 
-	while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ;
-	if ((count <= 8) && (count >= 0)) {
-		uint32_t rgtr, ptr;
-		rgtr = *(dev_priv->hw_addr_ptr);
-		ptr = ((volatile char *)dev_priv->last_pause_ptr -
-		      dev_priv->dma_ptr) + dev_priv->dma_offset +
-		      (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
-		if (rgtr <= ptr) {
-			DRM_ERROR
-			    ("Command regulator\npaused at count %d, address %x, "
-			     "while current pause address is %x.\n"
-			     "Please mail this message to "
-			     "<unichrome-devel@lists.sourceforge.net>\n", count,
-			     rgtr, ptr);
-		}
+	if ((ptr - reader) <= dev_priv->dma_diff ) {
+		count = 10000000;
+		while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
 	}
 
 	if (paused && !no_pci_fire) {
-		uint32_t rgtr, ptr;
-		uint32_t ptr_low;
+		reader = *(dev_priv->hw_addr_ptr);
+		if ((ptr - reader) == dev_priv->dma_diff) {
 
-		count = 1000000;
-		while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
-		       && count--) ;
+			/*
+			 * There is a concern that these writes may stall the PCI bus
+			 * if the GPU is not idle. However, idling the GPU first
+			 * doesn't make a difference.
+			 */
 
-		rgtr = *(dev_priv->hw_addr_ptr);
-		ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
-		    dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
-		ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
-		    ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0;
-		if (rgtr <= ptr && rgtr >= ptr_low) {
 			VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
 			VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
 			VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
@@ -494,6 +470,9 @@
 static int via_wait_idle(drm_via_private_t * dev_priv)
 {
 	int count = 10000000;
+
+	while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
+
 	while (count-- && (VIA_READ(VIA_REG_STATUS) &
 			   (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
 			    VIA_3D_ENG_BUSY))) ;
@@ -537,6 +516,9 @@
 	uint32_t end_addr, end_addr_lo;
 	uint32_t command;
 	uint32_t agp_base;
+	uint32_t ptr;
+	uint32_t reader;
+	int count;
 
 	dev_priv->dma_low = 0;
 
@@ -554,7 +536,7 @@
 			  &pause_addr_hi, &pause_addr_lo, 1) - 1;
 
 	via_flush_write_combine();
-	while (!*dev_priv->last_pause_ptr) ;
+	while(! *dev_priv->last_pause_ptr);
 
 	VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
 	VIA_WRITE(VIA_REG_TRANSPACE, command);
@@ -566,6 +548,24 @@
 	DRM_WRITEMEMORYBARRIER();
 	VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
 	VIA_READ(VIA_REG_TRANSPACE);
+
+	dev_priv->dma_diff = 0;
+
+	count = 10000000;
+	while (!(VIA_READ(0x41c) & 0x80000000) && count--);
+
+	reader = *(dev_priv->hw_addr_ptr);
+	ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+	    dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+	/*
+	 * This is the difference between where we tell the
+	 * command reader to pause and where it actually pauses.
+	 * This differs between hw implementation so we need to
+	 * detect it.
+	 */
+
+	dev_priv->dma_diff = ptr - reader;
 }
 
 static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
@@ -592,7 +592,6 @@
 	uint32_t pause_addr_lo, pause_addr_hi;
 	uint32_t jump_addr_lo, jump_addr_hi;
 	volatile uint32_t *last_pause_ptr;
-	uint32_t dma_low_save1, dma_low_save2;
 
 	agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
 	via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
@@ -619,31 +618,11 @@
 		      &pause_addr_lo, 0);
 
 	*last_pause_ptr = pause_addr_lo;
-	dma_low_save1 = dev_priv->dma_low;
 
-	/*
-	 * Now, set a trap that will pause the regulator if it tries to rerun the old
-	 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
-	 * and reissues the jump command over PCI, while the regulator has already taken the jump
-	 * and actually paused at the current buffer end).
-	 * There appears to be no other way to detect this condition, since the hw_addr_pointer
-	 * does not seem to get updated immediately when a jump occurs.
-	 */
-
-	last_pause_ptr =
-	    via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-			  &pause_addr_lo, 0) - 1;
-	via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-		      &pause_addr_lo, 0);
-	*last_pause_ptr = pause_addr_lo;
-
-	dma_low_save2 = dev_priv->dma_low;
-	dev_priv->dma_low = dma_low_save1;
-	via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
-	dev_priv->dma_low = dma_low_save2;
-	via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+	via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
 }
 
+
 static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
 {
 	via_cmdbuf_jump(dev_priv);
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index 8b8778d..b46ca8e6 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -29,11 +29,11 @@
 
 #define DRIVER_NAME		"via"
 #define DRIVER_DESC		"VIA Unichrome / Pro"
-#define DRIVER_DATE		"20061227"
+#define DRIVER_DATE		"20070202"
 
 #define DRIVER_MAJOR		2
 #define DRIVER_MINOR		11
-#define DRIVER_PATCHLEVEL	0
+#define DRIVER_PATCHLEVEL	1
 
 #include "via_verifier.h"
 
@@ -93,6 +93,7 @@
 	unsigned long vram_offset;
 	unsigned long agp_offset;
 	drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
+	uint32_t dma_diff;
 } drm_via_private_t;
 
 enum via_family {