diff options
-rw-r--r-- | libdrm/radeon/Makefile.am | 2 | ||||
-rw-r--r-- | libdrm/radeon/radeon_cs.h | 33 | ||||
-rw-r--r-- | libdrm/radeon/radeon_cs_gem.c | 103 | ||||
-rw-r--r-- | linux-core/radeon_gem.c | 4 |
4 files changed, 84 insertions, 58 deletions
diff --git a/libdrm/radeon/Makefile.am b/libdrm/radeon/Makefile.am index cc4951a9..d15a266b 100644 --- a/libdrm/radeon/Makefile.am +++ b/libdrm/radeon/Makefile.am @@ -29,7 +29,7 @@ AM_CFLAGS = \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/shared-core -libdrm_radeon_la_LTLIBRARIES = libdrm_radeon.la +libdrm_radeon_la_LTLIBRARIES = libdrm-radeon.la libdrm_radeon_ladir = $(libdir) libdrm_radeon_la_LDFLAGS = -version-number 1:0:0 -no-undefined libdrm_radeon_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ diff --git a/libdrm/radeon/radeon_cs.h b/libdrm/radeon/radeon_cs.h index 347e9f35..63f104b6 100644 --- a/libdrm/radeon/radeon_cs.h +++ b/libdrm/radeon/radeon_cs.h @@ -37,10 +37,11 @@ struct radeon_cs_reloc { struct radeon_bo *bo; - uint32_t soffset; - uint32_t eoffset; - uint32_t size; - uint32_t domains; + uint32_t start_offset; + uint32_t end_offset; + uint32_t read_domain; + uint32_t write_domain; + uint32_t flags; }; struct radeon_cs_manager; @@ -68,9 +69,11 @@ struct radeon_cs_funcs { int (*cs_write_dword)(struct radeon_cs *cs, uint32_t dword); int (*cs_write_reloc)(struct radeon_cs *cs, struct radeon_bo *bo, - uint32_t soffset, - uint32_t eoffset, - uint32_t domains); + uint32_t start_offset, + uint32_t end_offset, + uint32_t read_domain, + uint32_t write_domain, + uint32_t flags); int (*cs_begin)(struct radeon_cs *cs, uint32_t ndw, const char *file, @@ -104,11 +107,19 @@ static inline int radeon_cs_write_dword(struct radeon_cs *cs, uint32_t dword) static inline int radeon_cs_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, - uint32_t soffset, - uint32_t eoffset, - uint32_t domains) + uint32_t start_offset, + uint32_t end_offset, + uint32_t read_domain, + uint32_t write_domain, + uint32_t flags) { - return cs->csm->funcs->cs_write_reloc(cs, bo, soffset, eoffset, domains); + return cs->csm->funcs->cs_write_reloc(cs, + bo, + start_offset, + end_offset, + read_domain, + write_domain, + flags); } static inline int radeon_cs_begin(struct radeon_cs *cs, diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c index 6be1728f..f9c9fabb 100644 --- a/libdrm/radeon/radeon_cs_gem.c +++ b/libdrm/radeon/radeon_cs_gem.c @@ -43,9 +43,11 @@ #pragma pack(1) struct cs_reloc_gem { uint32_t handle; - uint32_t rdomain; - uint32_t wdomain; - uint32_t cnt; + uint32_t start_offset; + uint32_t end_offset; + uint32_t read_domain; + uint32_t write_domain; + uint32_t flags; }; #pragma pack() @@ -125,50 +127,74 @@ static int cs_gem_write_dword(struct radeon_cs *cs, uint32_t dword) static int cs_gem_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, - uint32_t soffset, - uint32_t eoffset, - uint32_t domains) + uint32_t start_offset, + uint32_t end_offset, + uint32_t read_domain, + uint32_t write_domain, + uint32_t flags) { struct cs_gem *csg = (struct cs_gem*)cs; struct cs_reloc_gem *reloc; uint32_t idx; unsigned i; + /* check domains */ + if ((read_domain && write_domain) || (!read_domain && !write_domain)) { + /* in one CS a bo can only be in read or write domain but not + * in read & write domain at the same sime + */ + return -EINVAL; + } + if (read_domain == RADEON_GEM_DOMAIN_CPU) { + return -EINVAL; + } + if (write_domain == RADEON_GEM_DOMAIN_CPU) { + return -EINVAL; + } /* check reloc window */ - if (eoffset > bo->size) { + if (end_offset > bo->size) { return -EINVAL; } - if (soffset > eoffset) { + if (start_offset > end_offset) { return -EINVAL; } /* check if bo is already referenced */ for(i = 0; i < cs->crelocs; i++) { - idx = i * 4; + idx = i * 6; reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; - if (reloc->handle == bo->handle) { - /* update start offset and size */ - switch (bo->domains) { - case RADEON_GEM_DOMAIN_VRAM: - reloc->rdomain = 0; - reloc->wdomain = RADEON_GEM_DOMAIN_VRAM; - break; - case RADEON_GEM_DOMAIN_GTT: - reloc->rdomain = RADEON_GEM_DOMAIN_GTT; - reloc->wdomain = 0; - break; - default: - exit(0); - break; + /* Check domains must be in read or write. As we check already + * checked that in argument one of the read or write domain was + * set we only need to check that if previous reloc as the read + * domain set then the read_domain should also be set for this + * new relocation. + */ + if (reloc->read_domain && !read_domain) { + return -EINVAL; + } + if (reloc->write_domain && !write_domain) { + return -EINVAL; + } + reloc->read_domain |= read_domain; + reloc->write_domain |= write_domain; + /* update start and end offset */ + if (start_offset < reloc->start_offset) { + reloc->start_offset = start_offset; } - reloc->cnt++; + if (end_offset > reloc->end_offset) { + reloc->end_offset = end_offset; + } + /* update flags */ + reloc->flags |= (flags & reloc->flags); + /* write relocation packet */ cs_gem_write_dword(cs, 0xc0001000); cs_gem_write_dword(cs, idx); return 0; } } - /* add bo */ + /* new relocation */ if (csg->base.crelocs >= csg->nrelocs) { + /* allocate more memory (TODO: should use a slab allocatore maybe) */ uint32_t *tmp, size; size = ((csg->nrelocs + 1) * sizeof(struct radeon_bo*)); tmp = (uint32_t*)realloc(csg->relocs_bo, size); @@ -176,7 +202,7 @@ static int cs_gem_write_reloc(struct radeon_cs *cs, return -ENOMEM; } csg->relocs_bo = (struct radeon_bo**)tmp; - size = ((csg->nrelocs + 1) * 4 * 4); + size = ((csg->nrelocs + 1) * 6 * 4); tmp = (uint32_t*)realloc(csg->relocs, size); if (tmp == NULL) { return -ENOMEM; @@ -186,26 +212,15 @@ static int cs_gem_write_reloc(struct radeon_cs *cs, csg->chunks[1].chunk_data = (uint64_t)(intptr_t)csg->relocs; } csg->relocs_bo[csg->base.crelocs] = bo; - idx = (csg->base.crelocs++) * 4; + idx = (csg->base.crelocs++) * 6; reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; reloc->handle = bo->handle; - reloc->rdomain = bo->domains; - reloc->wdomain = bo->domains; - switch (bo->domains) { - case RADEON_GEM_DOMAIN_VRAM: - reloc->rdomain = 0; - reloc->wdomain = RADEON_GEM_DOMAIN_VRAM; - break; - case RADEON_GEM_DOMAIN_GTT: - reloc->rdomain = RADEON_GEM_DOMAIN_GTT; - reloc->wdomain = 0; - break; - default: - exit(0); - break; - } - reloc->cnt = 1; - csg->chunks[1].length_dw += 4; + reloc->start_offset = start_offset; + reloc->end_offset = end_offset; + reloc->read_domain = read_domain; + reloc->write_domain = write_domain; + reloc->flags = flags; + csg->chunks[1].length_dw += 6; radeon_bo_ref(bo); cs->relocs_total_size += bo->size; cs_gem_write_dword(cs, 0xc0001000); diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 2ed9bfc1..b2e1d7fe 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1213,8 +1213,8 @@ static int radeon_gem_find_reloc(struct drm_radeon_cs_parser *parser, } *handle = reloc_chunk->kdata[offset]; - *read_domains = reloc_chunk->kdata[offset + 1]; - *write_domain = reloc_chunk->kdata[offset + 2]; + *read_domains = reloc_chunk->kdata[offset + 3]; + *write_domain = reloc_chunk->kdata[offset + 4]; return 0; } |