Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

via: Try to improve command-buffer chaining.



Bump driver date and patchlevel.

Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent bc07dc7f
Loading
Loading
Loading
Loading
+43 −64
Original line number Diff line number Diff line
@@ -432,56 +432,32 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
{
	int paused, count;
	volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
	uint32_t reader,ptr;

	paused = 0;
	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) ;
	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 (!*dev_priv->last_pause_ptr) ;

	paused = 0;
	count = 20;

	if ((ptr - reader) <= dev_priv->dma_diff ) {
		count = 10000000;
		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) {
		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--) ;

		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;
			/*
			 * 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.
			 */

		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_hook_segment(drm_via_private_t * dev_priv,
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 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
	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;

@@ -566,6 +548,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
	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 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
	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 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
		      &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);
}


static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
{
	via_cmdbuf_jump(dev_priv);
+3 −2
Original line number Diff line number Diff line
@@ -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 @@ typedef struct drm_via_private {
	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 {