radeon: CS2 make it all work with new relocs style
authorDave Airlie <airlied@redhat.com>
Sun, 2 Nov 2008 23:40:52 +0000 (09:40 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 2 Nov 2008 23:40:52 +0000 (09:40 +1000)
linux-core/radeon_gem.c
shared-core/radeon_cs.c

index 7899490..851a95d 100644 (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);
index 14f3dcd..31cd53d 100644 (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 */