diff options
| author | Thomas Hellstrom <unichrome@shipmail.org> | 2005-01-27 22:48:47 +0000 | 
|---|---|---|
| committer | Thomas Hellstrom <unichrome@shipmail.org> | 2005-01-27 22:48:47 +0000 | 
| commit | cd9ef39c769202f161619ee7a95674371c57cd48 (patch) | |
| tree | 85e034ddc5c57fc72f7cb4f97b453c89e942fea8 | |
| parent | 77045dc51672715115f179c099dfb8d7b4d304d4 (diff) | |
Fixed multiple devices DMA bug. Fixed PCI path FIRE command detection
| -rw-r--r-- | shared-core/via_dma.c | 32 | ||||
| -rw-r--r-- | shared-core/via_drv.h | 10 | ||||
| -rw-r--r-- | shared-core/via_verifier.c | 8 | ||||
| -rw-r--r-- | shared/via.h | 4 | ||||
| -rw-r--r-- | shared/via_dma.c | 32 | ||||
| -rw-r--r-- | shared/via_drv.h | 6 | ||||
| -rw-r--r-- | shared/via_verifier.c | 8 | 
7 files changed, 70 insertions, 30 deletions
| diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c index 22cbcd28..3edefd76 100644 --- a/shared-core/via_dma.c +++ b/shared-core/via_dma.c @@ -37,7 +37,6 @@  #include "via_drv.h"  #include "via_3d_reg.h" -#define PCI_BUF_SIZE 512000  #define CMDBUF_ALIGNMENT_SIZE   (0x100)  #define CMDBUF_ALIGNMENT_MASK   (0xff) @@ -66,10 +65,6 @@  	*vb++ = (w2);				\  	dev_priv->dma_low += 8;  - -static char pci_buf[PCI_BUF_SIZE]; -static unsigned long pci_bufsiz = PCI_BUF_SIZE;   -  static void via_cmdbuf_start(drm_via_private_t * dev_priv);  static void via_cmdbuf_pause(drm_via_private_t * dev_priv);  static void via_cmdbuf_reset(drm_via_private_t * dev_priv); @@ -266,12 +261,12 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)  		return DRM_ERR(EFAULT);  	} -	if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { +	if (cmd->size > VIA_PCI_BUF_SIZE) {  		return DRM_ERR(ENOMEM);  	}  -	if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) +	if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))  		return DRM_ERR(EFAULT);  	/* @@ -281,7 +276,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)  	 */ -	if ((ret = via_verify_command_stream((uint32_t *)pci_buf, cmd->size, dev, 1))) { +	if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) {  		return ret;  	} @@ -290,7 +285,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)  		return DRM_ERR(EAGAIN);  	} -	memcpy(vb, pci_buf, cmd->size); +	memcpy(vb, dev_priv->pci_buf, cmd->size);  	dev_priv->dma_low += cmd->size;  	via_cmdbuf_pause(dev_priv); @@ -344,12 +339,17 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  	drm_via_private_t *dev_priv = dev->dev_private;  	const uint32_t *regbuf = (const uint32_t *) buf;  	const uint32_t *regend = regbuf + (size >> 2); +	const uint32_t *next_fire;  +	int fire_count = 0;  	int ret;  	int check_2d_cmd = 1; + +  	if ((ret = via_verify_command_stream(regbuf, size, dev, 0)))  		return ret; +	next_fire = dev_priv->fire_offsets[fire_count];  	while (regbuf != regend) {	  		if ( *regbuf == HALCYON_HEADER2 ) { @@ -362,9 +362,14 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  			register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2;  			VIA_WRITE( addr, *regbuf++ ); -		} else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) { +		} else if ( (fire_count < dev_priv->num_fire_offsets) &&  +			    (regbuf == next_fire) && +			    (( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD) ) { + +			next_fire = dev_priv->fire_offsets[++fire_count];  			VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++); +  			if ( ( regbuf != regend ) &&   			     ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD))  				regbuf++; @@ -383,14 +388,15 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,  				      drm_via_cmdbuffer_t * cmd)  { +	drm_via_private_t *dev_priv = dev->dev_private;  	int ret; -	if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { +	if (cmd->size > VIA_PCI_BUF_SIZE) {  		return DRM_ERR(ENOMEM);  	}  -	if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) +	if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))  		return DRM_ERR(EFAULT); -	ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size); +	ret = via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size);  	return ret;  } diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h index f8824301..ac90da5a 100644 --- a/shared-core/via_drv.h +++ b/shared-core/via_drv.h @@ -28,14 +28,17 @@  #define DRIVER_NAME		"via"  #define DRIVER_DESC		"VIA Unichrome" -#define DRIVER_DATE		"20050107" +#define DRIVER_DATE		"20050127"  #define DRIVER_MAJOR		2  #define DRIVER_MINOR		4 -#define DRIVER_PATCHLEVEL	3 +#define DRIVER_PATCHLEVEL	4  #include "via_verifier.h" +#define VIA_PCI_BUF_SIZE 120000 +#define VIA_FIRE_BUF_SIZE  2048 +  typedef struct drm_via_ring_buffer {  	drm_map_t map;  	char *virtual_start; @@ -60,6 +63,9 @@ typedef struct drm_via_private {          int last_vblank_valid;          unsigned usec_per_vblank;  	drm_via_state_t hc_state; +	char pci_buf[VIA_PCI_BUF_SIZE]; +	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; +	uint32_t num_fire_offsets;  } drm_via_private_t;  /* VIA MMIO register access */ diff --git a/shared-core/via_verifier.c b/shared-core/via_verifier.c index ad32141e..6b08f5d8 100644 --- a/shared-core/via_verifier.c +++ b/shared-core/via_verifier.c @@ -496,6 +496,7 @@ static __inline__ int  via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,  		    drm_via_state_t *cur_seq)  { +	drm_via_private_t *dev_priv = (drm_via_private_t *) cur_seq->dev->dev_private;  	uint32_t a_fire, bcmd , dw_count;  	int ret = 0;  	int have_fire; @@ -540,6 +541,12 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,  		while(buf < buf_end) {  			if (*buf == a_fire) { +				if (dev_priv->num_fire_offsets >= VIA_FIRE_BUF_SIZE) { +					DRM_ERROR("Fire offset buffer full.\n"); +					ret = 1; +					break; +				} +				dev_priv->fire_offsets[dev_priv->num_fire_offsets++] = buf;  			        have_fire = 1;  				buf++;  				if (buf < buf_end && *buf == a_fire)  @@ -827,6 +834,7 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t  	hc_state->map_cache = NULL;  	hc_state->agp = agp;  	hc_state->buf_start = buf; +	dev_priv->num_fire_offsets = 0;  	while (buf < buf_end) { diff --git a/shared/via.h b/shared/via.h index 91c52073..ee46b139 100644 --- a/shared/via.h +++ b/shared/via.h @@ -30,11 +30,11 @@  #define DRIVER_NAME		"via"  #define DRIVER_DESC		"VIA Unichrome" -#define DRIVER_DATE		"20050107" +#define DRIVER_DATE		"20050127"  #define DRIVER_MAJOR		2  #define DRIVER_MINOR		4 -#define DRIVER_PATCHLEVEL	3 +#define DRIVER_PATCHLEVEL	4  #define DRIVER_IOCTLS							\          [DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)]  = { via_mem_alloc,  1, 0 }, \ diff --git a/shared/via_dma.c b/shared/via_dma.c index 0c4418c4..6f877c5c 100644 --- a/shared/via_dma.c +++ b/shared/via_dma.c @@ -38,7 +38,6 @@  #include "via_drv.h"  #include "via_3d_reg.h" -#define PCI_BUF_SIZE 512000  #define CMDBUF_ALIGNMENT_SIZE   (0x100)  #define CMDBUF_ALIGNMENT_MASK   (0xff) @@ -67,10 +66,6 @@  	*vb++ = (w2);				\  	dev_priv->dma_low += 8;  - -static char pci_buf[PCI_BUF_SIZE]; -static unsigned long pci_bufsiz = PCI_BUF_SIZE;   -  static void via_cmdbuf_start(drm_via_private_t * dev_priv);  static void via_cmdbuf_pause(drm_via_private_t * dev_priv);  static void via_cmdbuf_reset(drm_via_private_t * dev_priv); @@ -267,12 +262,12 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)  		return DRM_ERR(EFAULT);  	} -	if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { +	if (cmd->size > VIA_PCI_BUF_SIZE) {  		return DRM_ERR(ENOMEM);  	}  -	if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) +	if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))  		return DRM_ERR(EFAULT);  	/* @@ -282,7 +277,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)  	 */ -	if ((ret = via_verify_command_stream((uint32_t *)pci_buf, cmd->size, dev, 1))) { +	if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) {  		return ret;  	} @@ -291,7 +286,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)  		return DRM_ERR(EAGAIN);  	} -	memcpy(vb, pci_buf, cmd->size); +	memcpy(vb, dev_priv->pci_buf, cmd->size);  	dev_priv->dma_low += cmd->size;  	via_cmdbuf_pause(dev_priv); @@ -345,12 +340,17 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  	drm_via_private_t *dev_priv = dev->dev_private;  	const uint32_t *regbuf = (const uint32_t *) buf;  	const uint32_t *regend = regbuf + (size >> 2); +	const uint32_t *next_fire;  +	int fire_count = 0;  	int ret;  	int check_2d_cmd = 1; + +  	if ((ret = via_verify_command_stream(regbuf, size, dev, 0)))  		return ret; +	next_fire = dev_priv->fire_offsets[fire_count];  	while (regbuf != regend) {	  		if ( *regbuf == HALCYON_HEADER2 ) { @@ -363,9 +363,14 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  			register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2;  			VIA_WRITE( addr, *regbuf++ ); -		} else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) { +		} else if ( (fire_count < dev_priv->num_fire_offsets) &&  +			    (regbuf == next_fire) && +			    (( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD) ) { + +			next_fire = dev_priv->fire_offsets[++fire_count];  			VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++); +  			if ( ( regbuf != regend ) &&   			     ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD))  				regbuf++; @@ -384,14 +389,15 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,  static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,  				      drm_via_cmdbuffer_t * cmd)  { +	drm_via_private_t *dev_priv = dev->dev_private;  	int ret; -	if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { +	if (cmd->size > VIA_PCI_BUF_SIZE) {  		return DRM_ERR(ENOMEM);  	}  -	if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) +	if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))  		return DRM_ERR(EFAULT); -	ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size); +	ret = via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size);  	return ret;  } diff --git a/shared/via_drv.h b/shared/via_drv.h index e1a8b6c3..5d90c9ca 100644 --- a/shared/via_drv.h +++ b/shared/via_drv.h @@ -27,6 +27,9 @@  #include "via_drm.h"  #include "via_verifier.h" +#define VIA_PCI_BUF_SIZE 120000 +#define VIA_FIRE_BUF_SIZE  2048 +  typedef struct drm_via_ring_buffer {  	drm_map_t map;  	char *virtual_start; @@ -51,6 +54,9 @@ typedef struct drm_via_private {          int last_vblank_valid;          unsigned usec_per_vblank;  	drm_via_state_t hc_state; +	char pci_buf[VIA_PCI_BUF_SIZE]; +	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; +	uint32_t num_fire_offsets;  } drm_via_private_t;  /* VIA MMIO register access */ diff --git a/shared/via_verifier.c b/shared/via_verifier.c index ada28929..edc9decd 100644 --- a/shared/via_verifier.c +++ b/shared/via_verifier.c @@ -497,6 +497,7 @@ static __inline__ int  via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,  		    drm_via_state_t *cur_seq)  { +	drm_via_private_t *dev_priv = (drm_via_private_t *) cur_seq->dev->dev_private;  	uint32_t a_fire, bcmd , dw_count;  	int ret = 0;  	int have_fire; @@ -541,6 +542,12 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,  		while(buf < buf_end) {  			if (*buf == a_fire) { +				if (dev_priv->num_fire_offsets >= VIA_FIRE_BUF_SIZE) { +					DRM_ERROR("Fire offset buffer full.\n"); +					ret = 1; +					break; +				} +				dev_priv->fire_offsets[dev_priv->num_fire_offsets++] = buf;  			        have_fire = 1;  				buf++;  				if (buf < buf_end && *buf == a_fire)  @@ -828,6 +835,7 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t  	hc_state->map_cache = NULL;  	hc_state->agp = agp;  	hc_state->buf_start = buf; +	dev_priv->num_fire_offsets = 0;  	while (buf < buf_end) { | 
