Commit a0a6dd0b authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

via: Try to improve command-buffer chaining.

Bump driver date and patchlevel.
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent bc07dc7f
...@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS) ...@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS)
break; break;
case VIA_DMA_INITIALIZED: case VIA_DMA_INITIALIZED:
retcode = (dev_priv->ring.virtual_start != NULL) ? retcode = (dev_priv->ring.virtual_start != NULL) ?
0 : DRM_ERR(EFAULT); 0 : DRM_ERR(EFAULT);
break; break;
default: default:
retcode = DRM_ERR(EINVAL); retcode = DRM_ERR(EINVAL);
...@@ -432,56 +432,32 @@ static int via_hook_segment(drm_via_private_t * dev_priv, ...@@ -432,56 +432,32 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
{ {
int paused, count; int paused, count;
volatile uint32_t *paused_at = dev_priv->last_pause_ptr; volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
uint32_t reader,ptr;
paused = 0;
via_flush_write_combine(); via_flush_write_combine();
while (!*(via_get_dma(dev_priv) - 1)) ;
*dev_priv->last_pause_ptr = pause_addr_lo; *dev_priv->last_pause_ptr = pause_addr_lo;
via_flush_write_combine(); via_flush_write_combine();
reader = *(dev_priv->hw_addr_ptr);
/* ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
* The below statement is inserted to really force the flush. dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
* Not sure it is needed.
*/
while (!*dev_priv->last_pause_ptr) ;
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
while (!*dev_priv->last_pause_ptr) ;
paused = 0; if ((ptr - reader) <= dev_priv->dma_diff ) {
count = 20; count = 10000000;
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
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 (paused && !no_pci_fire) { if (paused && !no_pci_fire) {
uint32_t rgtr, ptr; reader = *(dev_priv->hw_addr_ptr);
uint32_t ptr_low; if ((ptr - reader) == dev_priv->dma_diff) {
count = 1000000; /*
while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) * There is a concern that these writes may stall the PCI bus
&& count--) ; * 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_TRANSET, (HC_ParaType_PreCR << 16));
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
...@@ -494,6 +470,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv, ...@@ -494,6 +470,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
static int via_wait_idle(drm_via_private_t * dev_priv) static int via_wait_idle(drm_via_private_t * dev_priv)
{ {
int count = 10000000; int count = 10000000;
while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
while (count-- && (VIA_READ(VIA_REG_STATUS) & while (count-- && (VIA_READ(VIA_REG_STATUS) &
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
VIA_3D_ENG_BUSY))) ; VIA_3D_ENG_BUSY))) ;
...@@ -537,6 +516,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) ...@@ -537,6 +516,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
uint32_t end_addr, end_addr_lo; uint32_t end_addr, end_addr_lo;
uint32_t command; uint32_t command;
uint32_t agp_base; uint32_t agp_base;
uint32_t ptr;
uint32_t reader;
int count;
dev_priv->dma_low = 0; dev_priv->dma_low = 0;
...@@ -554,7 +536,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) ...@@ -554,7 +536,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
&pause_addr_hi, &pause_addr_lo, 1) - 1; &pause_addr_hi, &pause_addr_lo, 1) - 1;
via_flush_write_combine(); 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_TRANSET, (HC_ParaType_PreCR << 16));
VIA_WRITE(VIA_REG_TRANSPACE, command); VIA_WRITE(VIA_REG_TRANSPACE, command);
...@@ -566,6 +548,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) ...@@ -566,6 +548,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
DRM_WRITEMEMORYBARRIER(); DRM_WRITEMEMORYBARRIER();
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
VIA_READ(VIA_REG_TRANSPACE); 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) static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
...@@ -592,7 +592,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) ...@@ -592,7 +592,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
uint32_t pause_addr_lo, pause_addr_hi; uint32_t pause_addr_lo, pause_addr_hi;
uint32_t jump_addr_lo, jump_addr_hi; uint32_t jump_addr_lo, jump_addr_hi;
volatile uint32_t *last_pause_ptr; 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; agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
...@@ -619,31 +618,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) ...@@ -619,31 +618,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
&pause_addr_lo, 0); &pause_addr_lo, 0);
*last_pause_ptr = pause_addr_lo; *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_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
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);
} }
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
{ {
via_cmdbuf_jump(dev_priv); via_cmdbuf_jump(dev_priv);
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#define DRIVER_NAME "via" #define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro" #define DRIVER_DESC "VIA Unichrome / Pro"
#define DRIVER_DATE "20061227" #define DRIVER_DATE "20070202"
#define DRIVER_MAJOR 2 #define DRIVER_MAJOR 2
#define DRIVER_MINOR 11 #define DRIVER_MINOR 11
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 1
#include "via_verifier.h" #include "via_verifier.h"
...@@ -93,6 +93,7 @@ typedef struct drm_via_private { ...@@ -93,6 +93,7 @@ typedef struct drm_via_private {
unsigned long vram_offset; unsigned long vram_offset;
unsigned long agp_offset; unsigned long agp_offset;
drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
uint32_t dma_diff;
} drm_via_private_t; } drm_via_private_t;
enum via_family { enum via_family {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment