Fixed multiple devices DMA bug. Fixed PCI path FIRE command detection
parent
77045dc516
commit
cd9ef39c76
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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 }, \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue