static unsigned radeon_add_reloc(struct radeon_drm_cs *cs, struct radeon_bo *bo, enum radeon_bo_usage usage, enum radeon_bo_domain domains, enum radeon_bo_domain *added_domains) { struct radeon_cs_context *csc = cs->csc; struct drm_radeon_cs_reloc *reloc; unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1); enum radeon_bo_domain rd = usage & RADEON_USAGE_READ ? domains : 0; enum radeon_bo_domain wd = usage & RADEON_USAGE_WRITE ? domains : 0; bool update_hash = TRUE; int i; *added_domains = 0; if (csc->is_handle_added[hash]) { i = csc->reloc_indices_hashlist[hash]; reloc = &csc->relocs[i]; if (reloc->handle != bo->handle) { /* Hash collision, look for the BO in the list of relocs linearly. */ for (i = csc->crelocs - 1; i >= 0; i--) { reloc = &csc->relocs[i]; if (reloc->handle == bo->handle) { /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/ break; } } } if (i >= 0) { /* On DMA ring we need to emit as many relocation as there is use of the bo * thus each time this function is call we should grow add again the bo to * the relocation buffer * * Do not update the hash table if it's dma ring, so that first hash always point * to first bo relocation which will the one used by the kernel. Following relocation * will be ignore by the kernel memory placement (but still use by the kernel to * update the cmd stream with proper buffer offset). */ update_hash = FALSE; update_reloc_domains(reloc, rd, wd, added_domains); if (cs->base.ring_type != RING_DMA) { csc->reloc_indices_hashlist[hash] = i; return i; } } } /* New relocation, check if the backing array is large enough. */ if (csc->crelocs >= csc->nrelocs) { uint32_t size; csc->nrelocs += 10; size = csc->nrelocs * sizeof(struct radeon_bo*); csc->relocs_bo = realloc(csc->relocs_bo, size); size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc); csc->relocs = realloc(csc->relocs, size); csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs; } /* Initialize the new relocation. */ csc->relocs_bo[csc->crelocs] = NULL; radeon_bo_reference(&csc->relocs_bo[csc->crelocs], bo); p_atomic_inc(&bo->num_cs_references); reloc = &csc->relocs[csc->crelocs]; reloc->handle = bo->handle; reloc->read_domains = rd; reloc->write_domain = wd; reloc->flags = 0; csc->is_handle_added[hash] = TRUE; if (update_hash) { csc->reloc_indices_hashlist[hash] = csc->crelocs; } csc->chunks[1].length_dw += RELOC_DWORDS; *added_domains = rd | wd; return csc->crelocs++; }
static unsigned radeon_add_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo, enum radeon_bo_usage usage, enum radeon_bo_domain domains, enum radeon_bo_domain *added_domains) { struct drm_radeon_cs_reloc *reloc; unsigned i; unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1); enum radeon_bo_domain rd = usage & RADEON_USAGE_READ ? domains : 0; enum radeon_bo_domain wd = usage & RADEON_USAGE_WRITE ? domains : 0; if (csc->is_handle_added[hash]) { i = csc->reloc_indices_hashlist[hash]; reloc = &csc->relocs[i]; if (reloc->handle == bo->handle) { update_reloc_domains(reloc, rd, wd, added_domains); return i; } /* Hash collision, look for the BO in the list of relocs linearly. */ for (i = csc->crelocs; i != 0;) { --i; reloc = &csc->relocs[i]; if (reloc->handle == bo->handle) { update_reloc_domains(reloc, rd, wd, added_domains); csc->reloc_indices_hashlist[hash] = i; /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/ return i; } } } /* New relocation, check if the backing array is large enough. */ if (csc->crelocs >= csc->nrelocs) { uint32_t size; csc->nrelocs += 10; size = csc->nrelocs * sizeof(struct radeon_bo*); csc->relocs_bo = realloc(csc->relocs_bo, size); size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc); csc->relocs = realloc(csc->relocs, size); csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs; } /* Initialize the new relocation. */ csc->relocs_bo[csc->crelocs] = NULL; radeon_bo_reference(&csc->relocs_bo[csc->crelocs], bo); p_atomic_inc(&bo->num_cs_references); reloc = &csc->relocs[csc->crelocs]; reloc->handle = bo->handle; reloc->read_domains = rd; reloc->write_domain = wd; reloc->flags = 0; csc->is_handle_added[hash] = TRUE; csc->reloc_indices_hashlist[hash] = csc->crelocs; csc->chunks[1].length_dw += RELOC_DWORDS; *added_domains = rd | wd; return csc->crelocs++; }