radeon: CS2 make it all work with new relocs style

This commit is contained in:
Dave Airlie 2008-11-03 09:40:52 +10:00
parent 35f0805592
commit 6000fa6862
2 changed files with 74 additions and 25 deletions

View file

@ -1242,21 +1242,58 @@ static int radeon_gem_ib_destroy(struct drm_device *dev)
return 0;
}
static int radeon_gem_find_reloc(struct drm_radeon_cs_parser *parser,
uint32_t offset, uint32_t *handle,
uint32_t *read_domains, uint32_t *write_domain)
{
struct drm_device *dev = parser->dev;
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_kernel_chunk *reloc_chunk = &parser->chunks[parser->reloc_index];
if (!reloc_chunk->kdata)
return -EINVAL;
if (offset > reloc_chunk->length_dw){
DRM_ERROR("Offset larger than chunk %d %d\n", offset, reloc_chunk->length_dw);
return -EINVAL;
}
*handle = reloc_chunk->kdata[offset];
*read_domains = reloc_chunk->kdata[offset + 1];
*write_domain = reloc_chunk->kdata[offset + 2];
return 0;
}
static int radeon_gem_relocate(struct drm_radeon_cs_parser *parser,
uint32_t *reloc, uint32_t *offset)
{
struct drm_device *dev = parser->dev;
drm_radeon_private_t *dev_priv = dev->dev_private;
/* relocate the handle */
uint32_t read_domains = reloc[2];
uint32_t write_domain = reloc[3];
uint32_t read_domains, write_domain;
struct drm_gem_object *obj;
int flags = 0;
int ret;
struct drm_radeon_gem_object *obj_priv;
obj = drm_gem_object_lookup(dev, parser->file_priv, reloc[1]);
if (!obj)
return -EINVAL;
if (parser->reloc_index == -1) {
obj = drm_gem_object_lookup(dev, parser->file_priv, reloc[1]);
if (!obj)
return -EINVAL;
read_domains = reloc[2];
write_domain = reloc[3];
} else {
uint32_t handle;
/* have to lookup handle in other chunk */
ret = radeon_gem_find_reloc(parser, reloc[1], &handle, &read_domains, &write_domain);
if (ret < 0)
return ret;
obj = drm_gem_object_lookup(dev, parser->file_priv, handle);
if (!obj)
return -EINVAL;
}
obj_priv = obj->driver_private;
radeon_gem_set_domain(obj, read_domains, write_domain, &flags, false);

View file

@ -68,6 +68,8 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
goto out;
}
parser.dev = dev;
parser.file_priv = fpriv;
parser.reloc_index = -1;
parser.ib_index = -1;
parser.num_chunks = cs->num_chunks;
@ -103,24 +105,29 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data;
parser.chunks[i].kdata = NULL;
size = parser.chunks[i].length_dw * sizeof(uint32_t);
switch(parser.chunks[i].chunk_id) {
case RADEON_CHUNK_ID_RELOCS:
case RADEON_CHUNK_ID_IB:
case RADEON_CHUNK_ID_OLD: {
/* copy from user the relocs chunk */
int size = parser.chunks[i].length_dw * sizeof(uint32_t);
parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER);
if (!parser.chunks[i].kdata) {
r = -ENOMEM;
case RADEON_CHUNK_ID_OLD:
if (size == 0) {
r = -EINVAL;
goto out;
}
if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) {
r = -EFAULT;
goto out;
}
}
case RADEON_CHUNK_ID_RELOCS:
if (size) {
parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER);
if (!parser.chunks[i].kdata) {
r = -ENOMEM;
goto out;
}
if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) {
r = -EFAULT;
goto out;
}
} else
parser.chunks[i].kdata = NULL;
break;
default:
break;
@ -266,6 +273,7 @@ static int radeon_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *r
return 0;
}
#define RELOC_SIZE 2
#define RELOC_SIZE_NEW 0
#define RADEON_2D_OFFSET_MASK 0x3fffff
static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
@ -288,9 +296,17 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa
/* this is too strict we may want to expand the length in the future and have
old kernels ignore it. */
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg);
return -EINVAL;
if (parser->reloc_index == -1) {
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg);
return -EINVAL;
}
} else {
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16))) {
DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg);
return -EINVAL;
}
}
switch(reg) {
@ -371,9 +387,7 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser,
int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
{
drm_radeon_private_t *dev_priv = parser->dev->dev_private;
uint32_t hdr, num_dw, reg;
int need_reloc = 0;
int count_dw = 1;
int ret;
@ -422,8 +436,6 @@ int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
int radeon_cs_parse(struct drm_radeon_cs_parser *parser)
{
struct drm_device *dev = parser->dev;
drm_radeon_private_t *dev_priv = parser->dev->dev_private;
volatile int rb;
struct drm_radeon_kernel_chunk *ib_chunk;
/* scan the packet for various things */